• Stars
    star
    387
  • Rank 110,971 (Top 3 %)
  • Language
    Kotlin
  • License
    Apache License 2.0
  • Created about 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Multiplatform UI DSL with screen management in common code for mobile (android & ios) Kotlin Multiplatform development

moko-widgets
GitHub license Download kotlin-version

Mobile Kotlin widgets

This is a Kotlin MultiPlatform library that provides declarative UI and application screens management in common code. You can implement full application for Android and iOS only from common code with it.

Sample Screen

Android iOS
Sample Android Sample iOS

Code of screen structure:

class LoginScreen(
    private val theme: Theme,
    private val loginViewModelFactory: () -> LoginViewModel
) : WidgetScreen<Args.Empty>() {

    override fun createContentWidget() = with(theme) {
        val viewModel = getViewModel(loginViewModelFactory)

        constraint(size = WidgetSize.AsParent) {
            val logoImage = +image(
                size = WidgetSize.Const(SizeSpec.WrapContent, SizeSpec.WrapContent),
                image = const(Image.resource(MR.images.logo)),
                scaleType = ImageWidget.ScaleType.FIT
            )

            val emailInput = +input(
                size = WidgetSize.WidthAsParentHeightWrapContent,
                id = Id.EmailInputId,
                label = const("Email".desc() as StringDesc),
                field = viewModel.emailField,
                inputType = InputType.PHONE
            )
            val passwordInput = +input(
                size = WidgetSize.WidthAsParentHeightWrapContent,
                id = Id.PasswordInputId,
                label = const("Password".desc() as StringDesc),
                field = viewModel.passwordField
            )
            val loginButton = +button(
                size = WidgetSize.Const(SizeSpec.AsParent, SizeSpec.Exact(50f)),
                content = ButtonWidget.Content.Text(Value.data("Login".desc())),
                onTap = viewModel::onLoginPressed
            )

            val registerButton = +button(
                id = Id.RegistrationButtonId,
                size = WidgetSize.Const(SizeSpec.WrapContent, SizeSpec.Exact(40f)),
                content = ButtonWidget.Content.Text(Value.data("Registration".desc())),
                onTap = viewModel::onRegistrationPressed
            )

            val copyrightText = +text(
                size = WidgetSize.WrapContent,
                text = const("IceRock Development")
            )

            constraints {
                passwordInput centerYToCenterY root
                passwordInput leftRightToLeftRight root offset 16

                emailInput bottomToTop passwordInput offset 8
                emailInput leftRightToLeftRight root offset 16

                loginButton topToBottom passwordInput
                loginButton leftRightToLeftRight root

                registerButton topToBottom loginButton
                registerButton rightToRight root

                // logo image height must be automatic ?
                logoImage centerXToCenterX root
                logoImage.verticalCenterBetween(
                    top = root.top,
                    bottom = emailInput.top
                )

                copyrightText centerXToCenterX root
                copyrightText bottomToBottom root.safeArea offset 8
            }
        }
    }

    object Id {
        object EmailInputId : InputWidget.Id
        object PasswordInputId : InputWidget.Id
        object RegistrationButtonId : ButtonWidget.Id
    }
}

Code of theme:

val loginScreen = Theme(baseTheme) {
    factory[ConstraintWidget.DefaultCategory] = ConstraintViewFactory(
        padding = PaddingValues(16f),
        background = Background(
            fill = Fill.Solid(Colors.white)
        )
    )

    factory[InputWidget.DefaultCategory] = SystemInputViewFactory(
        margins = MarginValues(bottom = 8f),
        underLineColor = Color(0x000000DD),
        underLineFocusedColor = Color(0x3949ABFF),
        labelTextStyle = TextStyle(
            size = 12,
            color = Color(0x3949ABFF),
            fontStyle = FontStyle.BOLD
        ),
        errorTextStyle = TextStyle(
            size = 12,
            color = Color(0xB00020FF),
            fontStyle = FontStyle.BOLD
        ),
        textStyle = TextStyle(
            size = 16,
            color = Color(0x000000FF),
            fontStyle = FontStyle.MEDIUM
        )
    )

    val corners = platformSpecific(android = 8f, ios = 25f)

    factory[ButtonWidget.DefaultCategory] = SystemButtonViewFactory(
        margins = MarginValues(top = 32f),
        background = {
            val bg: (Color) -> Background = {
                Background(
                    fill = Fill.Solid(it),
                    shape = Shape.Rectangle(
                        cornerRadius = corners
                    )
                )
            }
            StateBackground(
                normal = bg(Color(0x6770e0FF)),
                pressed = bg(Color(0x6770e0EE)),
                disabled = bg(Color(0x6770e0BB))
            )
        }.invoke(),
        textStyle = TextStyle(
            color = Colors.white
        )
    )

    factory[LoginScreen.Id.RegistrationButtonId] = SystemButtonViewFactory(
        background = {
            val bg: (Color) -> Background = {
                Background(
                    fill = Fill.Solid(it),
                    shape = Shape.Rectangle(
                        cornerRadius = corners
                    )
                )
            }
            StateBackground(
                normal = bg(Color(0xFFFFFF00)),
                pressed = bg(Color(0xE7E7EEEE)),
                disabled = bg(Color(0x000000BB))
            )
        }.invoke(),
        margins = MarginValues(top = 16f),
        textStyle = TextStyle(
            color = Color(0x777889FF)
        ),
        androidElevationEnabled = false
    )
}

Table of Contents

Features

  • compliance with platform rules;
  • declare structure, not rendering;
  • compile-time safety;
  • reactive data handling.

Requirements

  • Gradle version 6.8+
  • Android API 16+
  • iOS version 11.0+

Installation

root build.gradle

allprojects {
    repositories {
        mavenCentral()
    }
}

project build.gradle

dependencies {
    commonMainApi("dev.icerock.moko:widgets:0.2.4")

    commonMainApi("dev.icerock.moko:widgets-bottomsheet:0.2.4") // show bottom sheets
    commonMainApi("dev.icerock.moko:widgets-collection:0.2.4") // collection widget
    commonMainApi("dev.icerock.moko:widgets-datetime-picker:0.2.4") // show datepicker
    commonMainApi("dev.icerock.moko:widgets-image-network:0.2.4") // images with load from url
    commonMainApi("dev.icerock.moko:widgets-sms:0.2.4") // input with sms autofill
    commonMainApi("dev.icerock.moko:widgets-media:0.2.4") // moko-media integration
    commonMainApi("dev.icerock.moko:widgets-permissions:0.2.4") // moko-permissions integration
}

Codegen for new Widgets with @WidgetDef

root build.gradle

buildscript {
    repositories {
        gradlePluginPortal()
    }

    dependencies {
        classpath "dev.icerock.moko.widgets:gradle-plugin:0.2.4"
    }
}

project build.gradle

apply plugin: "dev.icerock.mobile.multiplatform-widgets-generator" // must apply before kotlin-multiplatform plugin

Usage

Hello world

Multiplatform application definition at mpp-library/src/commonMain/kotlin/App.kt:

class App : BaseApplication() {
    override fun setup(): ScreenDesc<Args.Empty> {
        val theme = Theme()

        return registerScreen(HelloWorldScreen::class) { HelloWorldScreen(theme) }
    }
}

Screen definition mpp-library/src/commonMain/kotlin/HelloWorldScreen.kt:

class HelloWorldScreen(
    private val theme: Theme
) : WidgetScreen<Args.Empty>() {

    override fun createContentWidget() = with(theme) {
        container(size = WidgetSize.AsParent) {
            center {
                text(
                    size = WidgetSize.WrapContent,
                    text = const("Hello World!")
                )
            }
        }
    }
}

Result:

Android iOS
HelloWorld Android HelloWorld iOS

Configure styles

Setup theme config:

val theme = Theme {
    factory[TextWidget.DefaultCategory] = SystemTextViewFactory(
        textStyle = TextStyle(
            size = 24,
            color = Colors.black
        ),
        padding = PaddingValues(padding = 16f)
    )
}

Result:

Android iOS
Custom style Android Custom style iOS

Bind data to UI

class TimerScreen(
    private val theme: Theme
) : WidgetScreen<Args.Empty>() {
    override fun createContentWidget(): Widget<WidgetSize.Const<SizeSpec.AsParent, SizeSpec.AsParent>> {
        val viewModel = getViewModel { TimerViewModel() }

        return with(theme) {
            container(size = WidgetSize.AsParent) {
                center {
                    text(
                        size = WidgetSize.WrapContent,
                        text = viewModel.text
                    )
                }
            }
        }
    }
}

class TimerViewModel : ViewModel() {
    private val iteration = MutableLiveData<Int>(0)
    val text: LiveData<StringDesc> = iteration.map { it.toString().desc() }

    init {
        viewModelScope.launch {
            while (isActive) {
                delay(1000)
                iteration.value = iteration.value + 1
            }
        }
    }
}

Samples

Please see more examples in the sample directory.

Set Up Locally

Contributing

All development (both new features and bug fixes) is performed in the develop branch. This way master always contains the sources of the most recently released version. Please send PRs with bug fixes to the develop branch. Documentation fixes in the markdown files are an exception to this rule. They are updated directly in master.

The develop branch is pushed to master on release.

For more details on contributing please see the contributing guide.

License

Copyright 2019 IceRock MAG Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

More Repositories

1

moko-resources

Resources access for mobile (android & ios) Kotlin Multiplatform development
Kotlin
1,064
star
2

moko-mvvm

Model-View-ViewModel architecture components for mobile (android & ios) Kotlin Multiplatform development
Kotlin
1,016
star
3

moko-template

Template project of a Mobile (Android & iOS) Kotlin MultiPlatform project with the MOKO libraries and modularized architecture
Kotlin
460
star
4

moko-kswift

Swift-friendly api generator for Kotlin/Native frameworks
Kotlin
350
star
5

moko-permissions

Runtime permissions controls for mobile (android & ios) Kotlin Multiplatform development
Kotlin
349
star
6

libs.kmp.icerock.dev

Kotlin Multiplatform libraries list with info auto-fetch
JavaScript
244
star
7

moko-network

Network components with codegeneration of rest api for mobile (android & ios) Kotlin Multiplatform development
Kotlin
151
star
8

moko-geo

Geolocation access for mobile (android & ios) Kotlin Multiplatform development
Kotlin
149
star
9

moko-socket-io

MOKO SocketIo by IceRock is Socket.IO implementation Kotlin Multiplatform library
Kotlin
122
star
10

moko-media

Media selection & presenting for mobile (android & ios) Kotlin Multiplatform development
Kotlin
116
star
11

mobile-multiplatform-gradle-plugin

Gradle plugin for simplify Kotlin Multiplatform mobile configurations
Kotlin
94
star
12

moko-maps

Control your map from common code for mobile (android & ios) Kotlin Multiplatform development
Kotlin
83
star
13

moko-parcelize

@Parcelize support for mobile (android & ios) Kotlin Multiplatform development
Kotlin
64
star
14

moko-paging

Pagination logic in common code for mobile (android & ios) Kotlin Multiplatform development
Kotlin
59
star
15

moko-errors

Automated exceptions handler for mobile (android & ios) Kotlin Multiplatform development.
Kotlin
52
star
16

moko-biometry

Biometry authentication with Touch ID, Face ID from common code with Kotlin Multiplatform Mobile
Kotlin
43
star
17

moko-web3

Ethereum Web3 implementation for mobile (android & ios) Kotlin Multiplatform development
Kotlin
41
star
18

moko-crash-reporting

Fatal and Non-Fatal reporting to Crashlytics for Kotlin Multiplatform Mobile
Kotlin
27
star
19

moko-units

Composing units into list and show in RecyclerView/UITableView/UICollectionView. Control your lists from common code for mobile (android & ios) Kotlin Multiplatform development
Kotlin
25
star
20

kmm.icerock.dev

JavaScript
24
star
21

redwood-sample

Kotlin
21
star
22

moko-tensorflow

Tensorflow Lite bindings for mobile (android & ios) Kotlin Multiplatform development
Kotlin
21
star
23

moko-fields

Input forms for mobile (android & ios) Kotlin Multiplatform development
Kotlin
20
star
24

moko-graphics

Graphics primitives for mobile (android & ios) Kotlin Multiplatform development
Kotlin
19
star
25

moko-javascript

JavaScript evaluation from kotlin common code for android & iOS
Kotlin
15
star
26

moko-core

Core classes for mobile (android & ios) Kotlin Multiplatform development
Kotlin
13
star
27

shaper

File structure generation tool from templates on Handlebars
Kotlin
12
star
28

moko-test

Test utilities for mobile (android & ios) Kotlin Multiplatform development
Kotlin
11
star
29

moko-widgets-template

Template project of a Mobile (Android & iOS) Kotlin MultiPlatform project with the MOKO widgets and other MOKO libs
Kotlin
10
star
30

kotlin-version-badge

badge with kotlin version, automatically fetched from mavenCentral package of latest version
Kotlin
10
star
31

moko

MOKO libraries umbrella project
9
star
32

gpuimage-filters-editor

iPad application photo editor with filters by GPUImage
Objective-C
9
star
33

email-service

Email sending service for kotlin - part of BOKO libs
Kotlin
8
star
34

codelabs.kmp.icerock.dev

Education of Kotlin Multiplatform Mobile
JavaScript
8
star
35

mobile-multiplatform-education

Internal lessons of mobile multiplatform development
Kotlin
8
star
36

moko.icerock.dev

Home page of moko libraries
HTML
7
star
37

moko-doctor

doctor script for checking the KMM developer's environment
Shell
6
star
38

admin-toolkit

Toolkit to create admin panels - part of BOKO libs
TypeScript
6
star
39

binance-futures-kotlin-api

Kotlin
6
star
40

fcm-push-service

Tools for sending fcm push by kotlin - part of BOKO libs
Kotlin
5
star
41

sms-service

Sms sending service for kotlin - part of BOKO libs
Kotlin
5
star
42

yellowdoor-app

Kotlin
4
star
43

storage-service

Tools for work with s3 storage and generate preview - part of BOKO libs
Kotlin
4
star
44

prototyping.icerock.dev

JavaScript
4
star
45

moko-time

Timestamp and timers for mobile (android & ios) Kotlin Multiplatform development
Kotlin
4
star
46

moko-gradle-plugin

Kotlin
3
star
47

moko-utils

Utilities for mobile (android & ios) Kotlin Multiplatform development
Kotlin
3
star
48

db-utils

Common tools for work with postgres via exposed - part of BOKO libs
Kotlin
3
star
49

web-utils

Common tools for create web application (ktor based) - part of BOKO libs
Kotlin
3
star
50

tinkoff-merchant-api

Tinkoff Merchant API Kotlin Client - part of BOKO libs
Kotlin
3
star
51

moko-intellij-plugin

Kotlin
3
star
52

slackbot-gitlab-ci

GitLab CI slackbot (beepboophq.com version)
JavaScript
2
star
53

auth-service

Common tools for JWT auth - part of BOKO libs
Kotlin
2
star
54

icerock-talaiot-config-plugin

Kotlin
2
star
55

PopupBottomNavigation

Popup menu with additional tabs for UITabBarController
Swift
2
star
56

IRPDFKit

PDF viewer with search for iOS
JavaScript
2
star
57

kafka-service

Common tools for kafka - part of BOKO libs
Kotlin
2
star
58

boko-validation

Konform based validation for Kotlin/JVM - part of BOKO libs
Kotlin
2
star
59

kmp.icerock.dev

Kotlin Mobile MultiPlatform materials landing
HTML
2
star
60

delivery.icerock.dev

Handlebars
1
star
61

shaper-templates

Templates for Shaper generation tool
Handlebars
1
star