From 25756c773c85225c6da11c5f70e4b5804888ae93 Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 11:33:12 +0700 Subject: [PATCH 01/48] #128 Result route navigation fix --- .../screen/navigation/NavigationScreen.kt | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index b073a821..7572924c 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -25,11 +25,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import dev.icerock.moko.parcelize.Parcelable import dev.icerock.moko.widgets.core.View -import dev.icerock.moko.widgets.screen.Args -import dev.icerock.moko.widgets.screen.FragmentNavigation -import dev.icerock.moko.widgets.screen.Screen -import dev.icerock.moko.widgets.screen.TypedScreenDesc -import dev.icerock.moko.widgets.screen.unsafeSetScreenArgument +import dev.icerock.moko.widgets.screen.* import dev.icerock.moko.widgets.style.view.FontStyle import dev.icerock.moko.widgets.utils.ThemeAttrs import dev.icerock.moko.widgets.utils.dp @@ -78,8 +74,7 @@ actual abstract class NavigationScreen actual constructor( val resultTarget = f.screenId if (resultTarget != null) { - val target = fm.fragments - .filterIsInstance>() + val target = fm.getAllScreens() .firstOrNull { it.resultCode == resultTarget } detachHandlers[f] = Runnable { @@ -110,6 +105,17 @@ actual abstract class NavigationScreen actual constructor( updateBackCallbackState() } + private fun FragmentManager.getAllScreens(): List> { + val list = fragments + .filterIsInstance>() + .toMutableList() + val childScreens = list.map { + it.childFragmentManager.getAllScreens() + } + childScreens.forEach { list.addAll(it) } + return list + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, From db72f7f27e9348259600944dd1f8a764b7898aa6 Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 11:38:39 +0700 Subject: [PATCH 02/48] #128 import fix --- .../moko/widgets/screen/navigation/NavigationScreen.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index 7572924c..2c28b824 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -25,7 +25,11 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import dev.icerock.moko.parcelize.Parcelable import dev.icerock.moko.widgets.core.View -import dev.icerock.moko.widgets.screen.* +import dev.icerock.moko.widgets.screen.Args +import dev.icerock.moko.widgets.screen.FragmentNavigation +import dev.icerock.moko.widgets.screen.Screen +import dev.icerock.moko.widgets.screen.TypedScreenDesc +import dev.icerock.moko.widgets.screen.unsafeSetScreenArgument import dev.icerock.moko.widgets.style.view.FontStyle import dev.icerock.moko.widgets.utils.ThemeAttrs import dev.icerock.moko.widgets.utils.dp From ddc92f01136c4236d82a848e08661c5dba15e480 Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 16:58:15 +0700 Subject: [PATCH 03/48] #90 Add android DatePicker --- moko-widgets-datepicker.podspec | 22 ++ settings.gradle.kts | 1 + widgets-datepicker/build.gradle.kts | 52 +++++ .../src/androidMain/AndroidManifest.xml | 2 + .../widgets/datepicker/ShowDatePickerExt.kt | 205 ++++++++++++++++++ .../widgets/datepicker/ShowDatePickerExt.kt | 37 ++++ .../swift/BottomSheetController.swift | 90 ++++++++ .../widgets/datepicker/ShowDatePickerExt.kt | 55 +++++ .../iosMain/swift/BottomSheetController.swift | 90 ++++++++ .../widgets/bottomSheet/ShowDatePickerExt.kt | 56 +++++ .../swift/BottomSheetController.swift | 90 ++++++++ 11 files changed, 700 insertions(+) create mode 100644 moko-widgets-datepicker.podspec create mode 100644 widgets-datepicker/build.gradle.kts create mode 100644 widgets-datepicker/src/androidMain/AndroidManifest.xml create mode 100644 widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt create mode 100644 widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt create mode 100644 widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift create mode 100644 widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt create mode 100644 widgets-datepicker/src/iosMain/swift/BottomSheetController.swift create mode 100644 widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt create mode 100644 widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift diff --git a/moko-widgets-datepicker.podspec b/moko-widgets-datepicker.podspec new file mode 100644 index 00000000..3955f4ce --- /dev/null +++ b/moko-widgets-datepicker.podspec @@ -0,0 +1,22 @@ +Pod::Spec.new do |spec| + spec.name = 'moko-widgets-datepicker' + spec.version = '0.1.0' + spec.homepage = 'https://github.com/icerockdev/moko-widgets' + spec.source = { :git => "https://github.com/icerockdev/moko-widgets.git", :tag => "release/#{spec.version}" } + spec.authors = 'IceRock Development' + spec.license = { :type => 'Apache 2', :file => 'LICENSE.md' } + spec.summary = 'Swift additions to moko-widgets Kotlin/Native library' + spec.module_name = "mokoWidgetsDatePicker" + + spec.source_files = "widgets-datepicker/src/iosMain/swift/**/*.{h,m,swift}" + spec.resources = "widgets-datepicker/src/iosMain/bundle/**/*" + + spec.dependency 'FloatingPanel' + + spec.ios.deployment_target = '11.0' + spec.swift_version = '5.0' + + spec.pod_target_xcconfig = { + 'VALID_ARCHS' => '$(ARCHS_STANDARD_64_BIT)' + } +end diff --git a/settings.gradle.kts b/settings.gradle.kts index 754cd9a8..9c1535f5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -42,6 +42,7 @@ if (!pluginPublish) { include(":widgets-flat") include(":widgets-sms") include(":widgets-bottomsheet") + include(":widgets-datepicker") if (!libraryPublish) { include(":sample:android-app") diff --git a/widgets-datepicker/build.gradle.kts b/widgets-datepicker/build.gradle.kts new file mode 100644 index 00000000..7fc410a0 --- /dev/null +++ b/widgets-datepicker/build.gradle.kts @@ -0,0 +1,52 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.multiplatform") + id("dev.icerock.mobile.multiplatform") + id("maven-publish") +} + +group = "dev.icerock.moko" +version = Versions.Libs.MultiPlatform.mokoWidgets + +android { + compileSdkVersion(Versions.Android.compileSdk) + + defaultConfig { + minSdkVersion(Versions.Android.minSdk) + targetSdkVersion(Versions.Android.targetSdk) + } +} + +dependencies { + mppLibrary(Deps.Libs.MultiPlatform.kotlinStdLib) + mppLibrary(Deps.Libs.MultiPlatform.coroutines) + + mppLibrary(Deps.Libs.MultiPlatform.mokoMvvm) + mppLibrary(Deps.Libs.MultiPlatform.mokoResources) + mppLibrary(Deps.Libs.MultiPlatform.mokoFields) + mppLibrary(Deps.Libs.MultiPlatform.mokoWidgets) + + androidLibrary(Deps.Libs.Android.lifecycle) + androidLibrary(Deps.Libs.Android.material) +} + +publishing { + repositories.maven("https://api.bintray.com/maven/icerockdev/moko/moko-widgets/;publish=1") { + name = "bintray" + + credentials { + username = System.getProperty("BINTRAY_USER") + password = System.getProperty("BINTRAY_KEY") + } + } +} + +cocoaPods { + podsProject = file("../sample/ios-app/Pods/Pods.xcodeproj") + + pod("moko-widgets-datapicker", "mokoWidgetsDataPicker") +} diff --git a/widgets-datepicker/src/androidMain/AndroidManifest.xml b/widgets-datepicker/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..c7f0d738 --- /dev/null +++ b/widgets-datepicker/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt b/widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt new file mode 100644 index 00000000..7d56de5e --- /dev/null +++ b/widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt @@ -0,0 +1,205 @@ +package dev.icerock.moko.widgets.datepicker + +import android.app.DatePickerDialog +import android.app.Dialog +import android.content.Context +import android.os.Bundle +import android.os.Parcel +import android.os.Parcelable +import androidx.fragment.app.DialogFragment +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.widgets.screen.Screen +import java.text.SimpleDateFormat +import java.util.* +import kotlin.properties.ReadOnlyProperty + +actual fun Screen<*>.showDatePickerDialog( + dialogId: Int, + factory: DatePickerDialogBuilder.() -> Unit +) { + val alert = DatePickerDialogBuilder( + dialogId, + this + ) + factory(alert) + alert.show() +} + +actual class DatePickerDialogHandler + +actual fun Screen<*>.registerDatePickerDialogHandler( + positive: ((dialogId: Int, date: DateTime) -> Unit)?, + negative: ((dialogId: Int) -> Unit)? +): ReadOnlyProperty, DatePickerDialogHandler> = + registerAttachFragmentHook(DatePickerDialogHandler()) { fragment -> + if (fragment !is DatePickerDialogFragment) return@registerAttachFragmentHook + + fragment.listener = object : + DatePickerDialogFragment.Listener { + override fun onPositivePressed(dialogId: Int, date: DateTime) { + positive?.invoke(dialogId, date) + } + + override fun onNegativePressed(dialogId: Int) { + negative?.invoke(dialogId) + } + } + } + +actual class DatePickerDialogBuilder(private val dialogId: Int, private val screen: Screen<*>) { + private val context: Context = screen.requireContext() + + private var format: String = "" + private var startDate: DateTime? = null + private var endDate: DateTime? = null + + actual fun dateFormat(format: String) { + this.format = format + } + + actual fun accentColor(color: Color) { + //android color from style + } + + actual fun handler(handler: DatePickerDialogHandler) { + // handler is just mark that `Screen` have registered alert handler + } + + actual fun startDate(date: DateTime) { + startDate = date + } + + actual fun endDate(date: DateTime) { + endDate = date + } + + internal fun show() { + val alertDialogFragment = + DatePickerDialogFragment.instantiate( + arg = DatePickerDialogFragment.Args( + dialogId = dialogId, + format = format, + startDate = startDate, + endDate = endDate + ) + ) + alertDialogFragment.show(screen.childFragmentManager, null) + } +} + +class DatePickerDialogFragment : DialogFragment() { + var listener: Listener? = null + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val argument = arguments?.getParcelable( + ARG_KEY + ) + requireNotNull(argument) { "can't be opened without argument" } + + val dialogId = argument.dialogId + val formatter = SimpleDateFormat(argument.format ?: "", Locale.getDefault()) + val currentDate = Calendar.getInstance() + val dialog = DatePickerDialog( + context, { _ + , year + , month + , day + -> + val date = Calendar.getInstance() + date.set(year, month, day) + listener?.onPositivePressed(dialogId, DateTime.timeInMillis(date.timeInMillis)) + }, + currentDate.get(Calendar.YEAR), + currentDate.get(Calendar.MONTH), + currentDate.get(Calendar.DAY_OF_MONTH) + ) + argument.endDate?.let { dialog.datePicker.maxDate = it.date.time } + argument.startDate?.let { dialog.datePicker.minDate = it.date.time } + dialog.setOnCancelListener { listener?.onNegativePressed(dialogId) } + return dialog + } + + interface Listener { + fun onPositivePressed(dialogId: Int, date: DateTime) + fun onNegativePressed(dialogId: Int) + } + + data class Args( + val dialogId: Int, + val format: String?, + val startDate: DateTime?, + val endDate: DateTime? + ) : Parcelable { + constructor(parcel: Parcel) : this( + parcel.readInt(), + parcel.readString(), + parcel.readLong().let { + if (it == 0L) null + else DateTime.timeInMillis(it) + }, + parcel.readLong().let { + if (it == 0L) null + else DateTime.timeInMillis(it) + } + ) + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeInt(dialogId) + parcel.writeString(format) + parcel.writeLong(startDate?.date?.time ?: 0L) + parcel.writeLong(endDate?.date?.time ?: 0L) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): Args { + return Args( + parcel + ) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + + } + + companion object { + private const val ARG_KEY = "arg_bundle" + + fun instantiate(arg: Args): DatePickerDialogFragment { + return DatePickerDialogFragment() + .apply { + arguments = Bundle().apply { + putParcelable(ARG_KEY, arg) + } + } + } + } +} + +actual sealed class DateTime { + + abstract val date: Date + + actual fun format(format: String): String { + return SimpleDateFormat(format, Locale.getDefault()).format(date) + } + + actual class timeInMillis actual constructor(mills: Long) : DateTime() { + override val date = Date(mills) + } + + actual class fromString actual constructor(time: String, format: String) : DateTime() { + override val date: Date = SimpleDateFormat(format, Locale.getDefault()).parse(time) + } + + actual class now actual constructor() : DateTime() { + override val date = Date() + } + +} diff --git a/widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt b/widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt new file mode 100644 index 00000000..8969724c --- /dev/null +++ b/widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt @@ -0,0 +1,37 @@ +package dev.icerock.moko.widgets.datepicker + +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.widgets.screen.Screen +import kotlin.properties.ReadOnlyProperty + +expect class DatePickerDialogHandler + +expect fun Screen<*>.registerDatePickerDialogHandler( + positive: ((dialogId: Int, date: DateTime) -> Unit)?, + negative: ((dialogId: Int) -> Unit)? = null +): ReadOnlyProperty, DatePickerDialogHandler> + +expect class DatePickerDialogBuilder { + fun dateFormat(format: String) + fun handler(handler: DatePickerDialogHandler) + fun accentColor(color: Color) + fun startDate(date: DateTime) + fun endDate(date: DateTime) +} + +expect fun Screen<*>.showDatePickerDialog( + dialogId: Int, + factory: DatePickerDialogBuilder.() -> Unit +) + +expect sealed class DateTime { + + fun format(format: String): String + + class timeInMillis(mills: Long) : DateTime + + class fromString(time: String, format: String) : + DateTime + + class now() : DateTime +} \ No newline at end of file diff --git a/widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift b/widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift new file mode 100644 index 00000000..8b32554b --- /dev/null +++ b/widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift @@ -0,0 +1,90 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +import UIKit +import FloatingPanel + +private var AssociatedDelegateHandle: UInt8 = 0 + +@objc public class BottomSheetController: NSObject, FloatingPanelControllerDelegate { + + @objc public func show( + onViewController vc: UIViewController, + withContent view: UIView, + onDismiss: @escaping () -> Void + ) { + view.updateConstraints() + view.layoutSubviews() + + let maxSize = CGSize(width: UIScreen.main.bounds.width, height: UIView.layoutFittingCompressedSize.height) + view.frame = UIScreen.main.bounds + + let floatLayout = BottomSheetLayout( + preferredHeight: view.systemLayoutSizeFitting( + UIView.layoutFittingCompressedSize, + withHorizontalFittingPriority: UILayoutPriority.required, + verticalFittingPriority: .defaultLow).height + ) + + let delegate = FloatingDelegate( + floatingLayout: floatLayout, + onDismiss: onDismiss + ) + + let contentVC = UIViewController() + contentVC.view = view + let fpc = FloatingPanelController() + fpc.set(contentViewController: contentVC) + fpc.delegate = delegate + fpc.backdropView.backgroundColor = UIColor.black + fpc.isRemovalInteractionEnabled = true + + objc_setAssociatedObject(fpc, &AssociatedDelegateHandle, delegate, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) + + vc.present(fpc, animated: true, completion: nil) + } +} + +class FloatingDelegate: FloatingPanelControllerDelegate { + private let floatingLayout: FloatingPanelLayout + private let onDismiss: () -> Void + + init(floatingLayout: FloatingPanelLayout, onDismiss: @escaping () -> Void) { + self.floatingLayout = floatingLayout + self.onDismiss = onDismiss + } + + func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { + return floatingLayout + } + + func floatingPanelDidEndRemove(_ vc: FloatingPanelController) { + onDismiss() + } +} + +class BottomSheetLayout: FloatingPanelLayout { + var initialPosition: FloatingPanelPosition = .half + + private let preferredHeight: CGFloat + + init(preferredHeight: CGFloat) { + self.preferredHeight = preferredHeight + } + + func insetFor(position: FloatingPanelPosition) -> CGFloat? { + switch (position) { + case .half: return preferredHeight + case .full: return 0 + case .tip: return 0 + case .hidden: return nil + } + } + + var supportedPositions: Set = [.half, .tip] + + func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { + return 0.3 + } +} diff --git a/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt b/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt new file mode 100644 index 00000000..74fab98f --- /dev/null +++ b/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ +package dev.icerock.moko.widgets.datepicker + +import cocoapods.mokoWidgetsBottomSheet.BottomSheetController +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.widgets.screen.Screen +import platform.UIKit.* +import kotlin.properties.ReadOnlyProperty + +actual fun Screen<*>.showDatePickerDialog( + dialogId: Int, + factory: DatePickerDialogBuilder.() -> Unit +) { + BottomSheetController().showOnViewController( + vc = this.viewController, + withContent = UIDatePicker(), + onDismiss = {} + ) +} + +actual class DatePickerDialogHandler( + val positive: ((dialogId: Int, date: String) -> Unit)?, + val negative: ((dialogId: Int) -> Unit)? +) + +actual fun Screen<*>.registerDatePickerDialogHandler( + positive: ((dialogId: Int, date: String) -> Unit)?, + negative: ((dialogId: Int) -> Unit)? +): ReadOnlyProperty, DatePickerDialogHandler> { + val handler = DatePickerDialogHandler( + positive = positive, + negative = negative + ) + return createConstReadOnlyProperty(handler) +} + +actual class DatePickerDialogBuilder(private val dialogId: Int, val screen: Screen<*>) { + + private var handler: DatePickerDialogHandler? = null + private var format: String = "" + + actual fun dateFormat(format: String) { + this.format = format + } + + actual fun handler(handler: DatePickerDialogHandler) { + this.handler = handler + } + + internal fun show() { + + } +} diff --git a/widgets-datepicker/src/iosMain/swift/BottomSheetController.swift b/widgets-datepicker/src/iosMain/swift/BottomSheetController.swift new file mode 100644 index 00000000..8b32554b --- /dev/null +++ b/widgets-datepicker/src/iosMain/swift/BottomSheetController.swift @@ -0,0 +1,90 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +import UIKit +import FloatingPanel + +private var AssociatedDelegateHandle: UInt8 = 0 + +@objc public class BottomSheetController: NSObject, FloatingPanelControllerDelegate { + + @objc public func show( + onViewController vc: UIViewController, + withContent view: UIView, + onDismiss: @escaping () -> Void + ) { + view.updateConstraints() + view.layoutSubviews() + + let maxSize = CGSize(width: UIScreen.main.bounds.width, height: UIView.layoutFittingCompressedSize.height) + view.frame = UIScreen.main.bounds + + let floatLayout = BottomSheetLayout( + preferredHeight: view.systemLayoutSizeFitting( + UIView.layoutFittingCompressedSize, + withHorizontalFittingPriority: UILayoutPriority.required, + verticalFittingPriority: .defaultLow).height + ) + + let delegate = FloatingDelegate( + floatingLayout: floatLayout, + onDismiss: onDismiss + ) + + let contentVC = UIViewController() + contentVC.view = view + let fpc = FloatingPanelController() + fpc.set(contentViewController: contentVC) + fpc.delegate = delegate + fpc.backdropView.backgroundColor = UIColor.black + fpc.isRemovalInteractionEnabled = true + + objc_setAssociatedObject(fpc, &AssociatedDelegateHandle, delegate, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) + + vc.present(fpc, animated: true, completion: nil) + } +} + +class FloatingDelegate: FloatingPanelControllerDelegate { + private let floatingLayout: FloatingPanelLayout + private let onDismiss: () -> Void + + init(floatingLayout: FloatingPanelLayout, onDismiss: @escaping () -> Void) { + self.floatingLayout = floatingLayout + self.onDismiss = onDismiss + } + + func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { + return floatingLayout + } + + func floatingPanelDidEndRemove(_ vc: FloatingPanelController) { + onDismiss() + } +} + +class BottomSheetLayout: FloatingPanelLayout { + var initialPosition: FloatingPanelPosition = .half + + private let preferredHeight: CGFloat + + init(preferredHeight: CGFloat) { + self.preferredHeight = preferredHeight + } + + func insetFor(position: FloatingPanelPosition) -> CGFloat? { + switch (position) { + case .half: return preferredHeight + case .full: return 0 + case .tip: return 0 + case .hidden: return nil + } + } + + var supportedPositions: Set = [.half, .tip] + + func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { + return 0.3 + } +} diff --git a/widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt b/widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt new file mode 100644 index 00000000..d07c1315 --- /dev/null +++ b/widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ +package dev.icerock.moko.widgets.bottomsheet + +import cocoapods.mokoWidgetsBottomSheet.BottomSheetController +import dev.icerock.moko.widgets.datepicker.DatePickerDialogBuilder +import dev.icerock.moko.widgets.datepicker.DatePickerDialogHandler +import dev.icerock.moko.widgets.screen.Screen +import platform.UIKit.UIDatePicker +import kotlin.properties.ReadOnlyProperty + +actual fun Screen<*>.showDatePickerDialog( + dialogId: Int, + factory: DatePickerDialogBuilder.() -> Unit +) { + BottomSheetController().showOnViewController( + vc = this.viewController, + withContent = UIDatePicker(), + onDismiss = {} + ) +} + +actual class DatePickerDialogHandler( + val positive: ((dialogId: Int, date: String) -> Unit)?, + val negative: ((dialogId: Int) -> Unit)? +) + +actual fun Screen<*>.registerDatePickerDialogHandler( + positive: ((dialogId: Int, date: String) -> Unit)?, + negative: ((dialogId: Int) -> Unit)? +): ReadOnlyProperty, DatePickerDialogHandler> { + val handler = dev.icerock.moko.widgets.datepicker.DatePickerDialogHandler( + positive = positive, + negative = negative + ) + return createConstReadOnlyProperty(handler) +} + +actual class DatePickerDialogBuilder(private val dialogId: Int, val screen: Screen<*>) { + + private var handler: DatePickerDialogHandler? = null + private var format: String = "" + + actual fun dateFormat(format: String) { + this.format = format + } + + actual fun handler(handler: DatePickerDialogHandler) { + this.handler = handler + } + + internal fun show() { + + } +} diff --git a/widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift b/widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift new file mode 100644 index 00000000..8b32554b --- /dev/null +++ b/widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift @@ -0,0 +1,90 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +import UIKit +import FloatingPanel + +private var AssociatedDelegateHandle: UInt8 = 0 + +@objc public class BottomSheetController: NSObject, FloatingPanelControllerDelegate { + + @objc public func show( + onViewController vc: UIViewController, + withContent view: UIView, + onDismiss: @escaping () -> Void + ) { + view.updateConstraints() + view.layoutSubviews() + + let maxSize = CGSize(width: UIScreen.main.bounds.width, height: UIView.layoutFittingCompressedSize.height) + view.frame = UIScreen.main.bounds + + let floatLayout = BottomSheetLayout( + preferredHeight: view.systemLayoutSizeFitting( + UIView.layoutFittingCompressedSize, + withHorizontalFittingPriority: UILayoutPriority.required, + verticalFittingPriority: .defaultLow).height + ) + + let delegate = FloatingDelegate( + floatingLayout: floatLayout, + onDismiss: onDismiss + ) + + let contentVC = UIViewController() + contentVC.view = view + let fpc = FloatingPanelController() + fpc.set(contentViewController: contentVC) + fpc.delegate = delegate + fpc.backdropView.backgroundColor = UIColor.black + fpc.isRemovalInteractionEnabled = true + + objc_setAssociatedObject(fpc, &AssociatedDelegateHandle, delegate, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) + + vc.present(fpc, animated: true, completion: nil) + } +} + +class FloatingDelegate: FloatingPanelControllerDelegate { + private let floatingLayout: FloatingPanelLayout + private let onDismiss: () -> Void + + init(floatingLayout: FloatingPanelLayout, onDismiss: @escaping () -> Void) { + self.floatingLayout = floatingLayout + self.onDismiss = onDismiss + } + + func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { + return floatingLayout + } + + func floatingPanelDidEndRemove(_ vc: FloatingPanelController) { + onDismiss() + } +} + +class BottomSheetLayout: FloatingPanelLayout { + var initialPosition: FloatingPanelPosition = .half + + private let preferredHeight: CGFloat + + init(preferredHeight: CGFloat) { + self.preferredHeight = preferredHeight + } + + func insetFor(position: FloatingPanelPosition) -> CGFloat? { + switch (position) { + case .half: return preferredHeight + case .full: return 0 + case .tip: return 0 + case .hidden: return nil + } + } + + var supportedPositions: Set = [.half, .tip] + + func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { + return 0.3 + } +} From 4770a138999475169161e92df76112e01de79ebd Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 17:40:05 +0700 Subject: [PATCH 04/48] #90 Ios fix --- buildSrc/src/main/kotlin/Deps.kt | 5 ++ widgets-datepicker/build.gradle.kts | 2 +- widgets-datepicker/src/iosArm64Main | 1 + .../swift/BottomSheetController.swift | 90 ------------------- .../widgets/datepicker/ShowDatePickerExt.kt | 65 +++++++------- widgets-datepicker/src/iosX64Main | 1 + .../widgets/bottomSheet/ShowDatePickerExt.kt | 56 ------------ .../swift/BottomSheetController.swift | 90 ------------------- 8 files changed, 41 insertions(+), 269 deletions(-) create mode 120000 widgets-datepicker/src/iosArm64Main delete mode 100644 widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift create mode 120000 widgets-datepicker/src/iosX64Main delete mode 100644 widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt delete mode 100644 widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt index a4b55dfe..9992904d 100755 --- a/buildSrc/src/main/kotlin/Deps.kt +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -70,6 +70,11 @@ object Deps { iosX64 = "dev.icerock.moko:widgets-bottomsheet-iosx64:${Versions.Libs.MultiPlatform.mokoWidgets}", iosArm64 = "dev.icerock.moko:widgets-bottomsheet-iosarm64:${Versions.Libs.MultiPlatform.mokoWidgets}" ) + val mokoWidgetsDatePicker = MultiPlatformLibrary( + common = "dev.icerock.moko:widgets-datepicker:${Versions.Libs.MultiPlatform.mokoWidgets}", + iosX64 = "dev.icerock.moko:widgets-datepicker-iosx64:${Versions.Libs.MultiPlatform.mokoWidgets}", + iosArm64 = "dev.icerock.moko:widgets-datepicker-iosarm64:${Versions.Libs.MultiPlatform.mokoWidgets}" + ) val mokoResources = MultiPlatformLibrary( common = "dev.icerock.moko:resources:${Versions.Libs.MultiPlatform.mokoResources}", iosX64 = "dev.icerock.moko:resources-iosx64:${Versions.Libs.MultiPlatform.mokoResources}", diff --git a/widgets-datepicker/build.gradle.kts b/widgets-datepicker/build.gradle.kts index 7fc410a0..0caf518e 100644 --- a/widgets-datepicker/build.gradle.kts +++ b/widgets-datepicker/build.gradle.kts @@ -48,5 +48,5 @@ publishing { cocoaPods { podsProject = file("../sample/ios-app/Pods/Pods.xcodeproj") - pod("moko-widgets-datapicker", "mokoWidgetsDataPicker") + pod("moko-widgets-datepicker", "mokoWidgetsDataPicker") } diff --git a/widgets-datepicker/src/iosArm64Main b/widgets-datepicker/src/iosArm64Main new file mode 120000 index 00000000..93d7d747 --- /dev/null +++ b/widgets-datepicker/src/iosArm64Main @@ -0,0 +1 @@ +iosMain \ No newline at end of file diff --git a/widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift b/widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift deleted file mode 100644 index 8b32554b..00000000 --- a/widgets-datepicker/src/iosArm64Main/swift/BottomSheetController.swift +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -import UIKit -import FloatingPanel - -private var AssociatedDelegateHandle: UInt8 = 0 - -@objc public class BottomSheetController: NSObject, FloatingPanelControllerDelegate { - - @objc public func show( - onViewController vc: UIViewController, - withContent view: UIView, - onDismiss: @escaping () -> Void - ) { - view.updateConstraints() - view.layoutSubviews() - - let maxSize = CGSize(width: UIScreen.main.bounds.width, height: UIView.layoutFittingCompressedSize.height) - view.frame = UIScreen.main.bounds - - let floatLayout = BottomSheetLayout( - preferredHeight: view.systemLayoutSizeFitting( - UIView.layoutFittingCompressedSize, - withHorizontalFittingPriority: UILayoutPriority.required, - verticalFittingPriority: .defaultLow).height - ) - - let delegate = FloatingDelegate( - floatingLayout: floatLayout, - onDismiss: onDismiss - ) - - let contentVC = UIViewController() - contentVC.view = view - let fpc = FloatingPanelController() - fpc.set(contentViewController: contentVC) - fpc.delegate = delegate - fpc.backdropView.backgroundColor = UIColor.black - fpc.isRemovalInteractionEnabled = true - - objc_setAssociatedObject(fpc, &AssociatedDelegateHandle, delegate, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) - - vc.present(fpc, animated: true, completion: nil) - } -} - -class FloatingDelegate: FloatingPanelControllerDelegate { - private let floatingLayout: FloatingPanelLayout - private let onDismiss: () -> Void - - init(floatingLayout: FloatingPanelLayout, onDismiss: @escaping () -> Void) { - self.floatingLayout = floatingLayout - self.onDismiss = onDismiss - } - - func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { - return floatingLayout - } - - func floatingPanelDidEndRemove(_ vc: FloatingPanelController) { - onDismiss() - } -} - -class BottomSheetLayout: FloatingPanelLayout { - var initialPosition: FloatingPanelPosition = .half - - private let preferredHeight: CGFloat - - init(preferredHeight: CGFloat) { - self.preferredHeight = preferredHeight - } - - func insetFor(position: FloatingPanelPosition) -> CGFloat? { - switch (position) { - case .half: return preferredHeight - case .full: return 0 - case .tip: return 0 - case .hidden: return nil - } - } - - var supportedPositions: Set = [.half, .tip] - - func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { - return 0.3 - } -} diff --git a/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt b/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt index 74fab98f..89841500 100644 --- a/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt +++ b/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt @@ -3,53 +3,54 @@ */ package dev.icerock.moko.widgets.datepicker -import cocoapods.mokoWidgetsBottomSheet.BottomSheetController -import dev.icerock.moko.resources.desc.StringDesc + +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.screen.Screen -import platform.UIKit.* import kotlin.properties.ReadOnlyProperty -actual fun Screen<*>.showDatePickerDialog( - dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit -) { - BottomSheetController().showOnViewController( - vc = this.viewController, - withContent = UIDatePicker(), - onDismiss = {} - ) -} - -actual class DatePickerDialogHandler( - val positive: ((dialogId: Int, date: String) -> Unit)?, - val negative: ((dialogId: Int) -> Unit)? -) +actual class DatePickerDialogHandler actual fun Screen<*>.registerDatePickerDialogHandler( - positive: ((dialogId: Int, date: String) -> Unit)?, + positive: ((dialogId: Int, date: DateTime) -> Unit)?, negative: ((dialogId: Int) -> Unit)? ): ReadOnlyProperty, DatePickerDialogHandler> { - val handler = DatePickerDialogHandler( - positive = positive, - negative = negative - ) - return createConstReadOnlyProperty(handler) + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } -actual class DatePickerDialogBuilder(private val dialogId: Int, val screen: Screen<*>) { - - private var handler: DatePickerDialogHandler? = null - private var format: String = "" - +actual class DatePickerDialogBuilder { actual fun dateFormat(format: String) { - this.format = format } actual fun handler(handler: DatePickerDialogHandler) { - this.handler = handler } - internal fun show() { + actual fun accentColor(color: Color) { + } + + actual fun startDate(date: DateTime) { + } + actual fun endDate(date: DateTime) { } } + +actual fun Screen<*>.showDatePickerDialog( + dialogId: Int, + factory: DatePickerDialogBuilder.() -> Unit +) { +} + +actual sealed class DateTime { + actual fun format(format: String): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + actual class timeInMillis actual constructor(mills: Long) : + DateTime() + + actual class fromString actual constructor(time: String, format: String) : + DateTime() + + actual class now actual constructor() : DateTime() + +} \ No newline at end of file diff --git a/widgets-datepicker/src/iosX64Main b/widgets-datepicker/src/iosX64Main new file mode 120000 index 00000000..93d7d747 --- /dev/null +++ b/widgets-datepicker/src/iosX64Main @@ -0,0 +1 @@ +iosMain \ No newline at end of file diff --git a/widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt b/widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt deleted file mode 100644 index d07c1315..00000000 --- a/widgets-datepicker/src/iosX64Main/kotlin/dev/icerock/moko/widgets/bottomSheet/ShowDatePickerExt.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ -package dev.icerock.moko.widgets.bottomsheet - -import cocoapods.mokoWidgetsBottomSheet.BottomSheetController -import dev.icerock.moko.widgets.datepicker.DatePickerDialogBuilder -import dev.icerock.moko.widgets.datepicker.DatePickerDialogHandler -import dev.icerock.moko.widgets.screen.Screen -import platform.UIKit.UIDatePicker -import kotlin.properties.ReadOnlyProperty - -actual fun Screen<*>.showDatePickerDialog( - dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit -) { - BottomSheetController().showOnViewController( - vc = this.viewController, - withContent = UIDatePicker(), - onDismiss = {} - ) -} - -actual class DatePickerDialogHandler( - val positive: ((dialogId: Int, date: String) -> Unit)?, - val negative: ((dialogId: Int) -> Unit)? -) - -actual fun Screen<*>.registerDatePickerDialogHandler( - positive: ((dialogId: Int, date: String) -> Unit)?, - negative: ((dialogId: Int) -> Unit)? -): ReadOnlyProperty, DatePickerDialogHandler> { - val handler = dev.icerock.moko.widgets.datepicker.DatePickerDialogHandler( - positive = positive, - negative = negative - ) - return createConstReadOnlyProperty(handler) -} - -actual class DatePickerDialogBuilder(private val dialogId: Int, val screen: Screen<*>) { - - private var handler: DatePickerDialogHandler? = null - private var format: String = "" - - actual fun dateFormat(format: String) { - this.format = format - } - - actual fun handler(handler: DatePickerDialogHandler) { - this.handler = handler - } - - internal fun show() { - - } -} diff --git a/widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift b/widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift deleted file mode 100644 index 8b32554b..00000000 --- a/widgets-datepicker/src/iosX64Main/swift/BottomSheetController.swift +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -import UIKit -import FloatingPanel - -private var AssociatedDelegateHandle: UInt8 = 0 - -@objc public class BottomSheetController: NSObject, FloatingPanelControllerDelegate { - - @objc public func show( - onViewController vc: UIViewController, - withContent view: UIView, - onDismiss: @escaping () -> Void - ) { - view.updateConstraints() - view.layoutSubviews() - - let maxSize = CGSize(width: UIScreen.main.bounds.width, height: UIView.layoutFittingCompressedSize.height) - view.frame = UIScreen.main.bounds - - let floatLayout = BottomSheetLayout( - preferredHeight: view.systemLayoutSizeFitting( - UIView.layoutFittingCompressedSize, - withHorizontalFittingPriority: UILayoutPriority.required, - verticalFittingPriority: .defaultLow).height - ) - - let delegate = FloatingDelegate( - floatingLayout: floatLayout, - onDismiss: onDismiss - ) - - let contentVC = UIViewController() - contentVC.view = view - let fpc = FloatingPanelController() - fpc.set(contentViewController: contentVC) - fpc.delegate = delegate - fpc.backdropView.backgroundColor = UIColor.black - fpc.isRemovalInteractionEnabled = true - - objc_setAssociatedObject(fpc, &AssociatedDelegateHandle, delegate, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) - - vc.present(fpc, animated: true, completion: nil) - } -} - -class FloatingDelegate: FloatingPanelControllerDelegate { - private let floatingLayout: FloatingPanelLayout - private let onDismiss: () -> Void - - init(floatingLayout: FloatingPanelLayout, onDismiss: @escaping () -> Void) { - self.floatingLayout = floatingLayout - self.onDismiss = onDismiss - } - - func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { - return floatingLayout - } - - func floatingPanelDidEndRemove(_ vc: FloatingPanelController) { - onDismiss() - } -} - -class BottomSheetLayout: FloatingPanelLayout { - var initialPosition: FloatingPanelPosition = .half - - private let preferredHeight: CGFloat - - init(preferredHeight: CGFloat) { - self.preferredHeight = preferredHeight - } - - func insetFor(position: FloatingPanelPosition) -> CGFloat? { - switch (position) { - case .half: return preferredHeight - case .full: return 0 - case .tip: return 0 - case .hidden: return nil - } - } - - var supportedPositions: Set = [.half, .tip] - - func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { - return 0.3 - } -} From d64efc6703425bacc9a00a22c81d8014a2b4b9f2 Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 17:48:51 +0700 Subject: [PATCH 05/48] #90 fix module name --- widgets-datepicker/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets-datepicker/build.gradle.kts b/widgets-datepicker/build.gradle.kts index 0caf518e..1f5188ee 100644 --- a/widgets-datepicker/build.gradle.kts +++ b/widgets-datepicker/build.gradle.kts @@ -48,5 +48,5 @@ publishing { cocoaPods { podsProject = file("../sample/ios-app/Pods/Pods.xcodeproj") - pod("moko-widgets-datepicker", "mokoWidgetsDataPicker") + pod("moko-widgets-datepicker", "mokoWidgetsDatePicker") } From 5aeb87f72660540f16c0ffe0fe31b2a4fbdfcf86 Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 18:33:26 +0700 Subject: [PATCH 06/48] #90 fix review --- buildSrc/src/main/kotlin/Deps.kt | 5 ++ buildSrc/src/main/kotlin/Versions.kt | 1 + settings.gradle.kts | 1 - widgets-datepicker/build.gradle.kts | 52 ----------- .../src/androidMain/AndroidManifest.xml | 2 - widgets-datepicker/src/iosArm64Main | 1 - .../iosMain/swift/BottomSheetController.swift | 90 ------------------- widgets-datepicker/src/iosX64Main | 1 - widgets/build.gradle.kts | 1 + .../widgets/screen/DatePickerDialogHandler.kt | 53 +++-------- .../moko/widgets/screen}/ShowDatePickerExt.kt | 19 +--- .../moko/widgets/screen}/ShowDatePickerExt.kt | 22 +---- 12 files changed, 23 insertions(+), 225 deletions(-) delete mode 100644 widgets-datepicker/build.gradle.kts delete mode 100644 widgets-datepicker/src/androidMain/AndroidManifest.xml delete mode 120000 widgets-datepicker/src/iosArm64Main delete mode 100644 widgets-datepicker/src/iosMain/swift/BottomSheetController.swift delete mode 120000 widgets-datepicker/src/iosX64Main rename widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt => widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt (75%) rename {widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker => widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen}/ShowDatePickerExt.kt (64%) rename {widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker => widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen}/ShowDatePickerExt.kt (64%) diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt index 9992904d..d2593ae5 100755 --- a/buildSrc/src/main/kotlin/Deps.kt +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -115,6 +115,11 @@ object Deps { common = "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:${Versions.Libs.MultiPlatform.coroutines}", ios = "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.Libs.MultiPlatform.coroutines}" ) + val klock = MultiPlatformLibrary( + android = "com.soywiz.korlibs.klock:klock-android:${Versions.Libs.MultiPlatform.klockVersion}", + common = "com.soywiz.korlibs.klock:klock:${Versions.Libs.MultiPlatform.klockVersion}", + ios = "com.soywiz.korlibs.klock:klock:${Versions.Libs.MultiPlatform.klockVersion}" + ) } object Jvm { diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 2efe49e6..1eebc427 100755 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -44,6 +44,7 @@ object Versions { const val mokoMedia = "0.2.0" const val mokoGraphics = "0.2.0" const val mokoParcelize = "0.2.0" + const val klockVersion = "1.8.4" } } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 9c1535f5..754cd9a8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -42,7 +42,6 @@ if (!pluginPublish) { include(":widgets-flat") include(":widgets-sms") include(":widgets-bottomsheet") - include(":widgets-datepicker") if (!libraryPublish) { include(":sample:android-app") diff --git a/widgets-datepicker/build.gradle.kts b/widgets-datepicker/build.gradle.kts deleted file mode 100644 index 1f5188ee..00000000 --- a/widgets-datepicker/build.gradle.kts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -plugins { - id("com.android.library") - id("org.jetbrains.kotlin.multiplatform") - id("dev.icerock.mobile.multiplatform") - id("maven-publish") -} - -group = "dev.icerock.moko" -version = Versions.Libs.MultiPlatform.mokoWidgets - -android { - compileSdkVersion(Versions.Android.compileSdk) - - defaultConfig { - minSdkVersion(Versions.Android.minSdk) - targetSdkVersion(Versions.Android.targetSdk) - } -} - -dependencies { - mppLibrary(Deps.Libs.MultiPlatform.kotlinStdLib) - mppLibrary(Deps.Libs.MultiPlatform.coroutines) - - mppLibrary(Deps.Libs.MultiPlatform.mokoMvvm) - mppLibrary(Deps.Libs.MultiPlatform.mokoResources) - mppLibrary(Deps.Libs.MultiPlatform.mokoFields) - mppLibrary(Deps.Libs.MultiPlatform.mokoWidgets) - - androidLibrary(Deps.Libs.Android.lifecycle) - androidLibrary(Deps.Libs.Android.material) -} - -publishing { - repositories.maven("https://api.bintray.com/maven/icerockdev/moko/moko-widgets/;publish=1") { - name = "bintray" - - credentials { - username = System.getProperty("BINTRAY_USER") - password = System.getProperty("BINTRAY_KEY") - } - } -} - -cocoaPods { - podsProject = file("../sample/ios-app/Pods/Pods.xcodeproj") - - pod("moko-widgets-datepicker", "mokoWidgetsDatePicker") -} diff --git a/widgets-datepicker/src/androidMain/AndroidManifest.xml b/widgets-datepicker/src/androidMain/AndroidManifest.xml deleted file mode 100644 index c7f0d738..00000000 --- a/widgets-datepicker/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/widgets-datepicker/src/iosArm64Main b/widgets-datepicker/src/iosArm64Main deleted file mode 120000 index 93d7d747..00000000 --- a/widgets-datepicker/src/iosArm64Main +++ /dev/null @@ -1 +0,0 @@ -iosMain \ No newline at end of file diff --git a/widgets-datepicker/src/iosMain/swift/BottomSheetController.swift b/widgets-datepicker/src/iosMain/swift/BottomSheetController.swift deleted file mode 100644 index 8b32554b..00000000 --- a/widgets-datepicker/src/iosMain/swift/BottomSheetController.swift +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -import UIKit -import FloatingPanel - -private var AssociatedDelegateHandle: UInt8 = 0 - -@objc public class BottomSheetController: NSObject, FloatingPanelControllerDelegate { - - @objc public func show( - onViewController vc: UIViewController, - withContent view: UIView, - onDismiss: @escaping () -> Void - ) { - view.updateConstraints() - view.layoutSubviews() - - let maxSize = CGSize(width: UIScreen.main.bounds.width, height: UIView.layoutFittingCompressedSize.height) - view.frame = UIScreen.main.bounds - - let floatLayout = BottomSheetLayout( - preferredHeight: view.systemLayoutSizeFitting( - UIView.layoutFittingCompressedSize, - withHorizontalFittingPriority: UILayoutPriority.required, - verticalFittingPriority: .defaultLow).height - ) - - let delegate = FloatingDelegate( - floatingLayout: floatLayout, - onDismiss: onDismiss - ) - - let contentVC = UIViewController() - contentVC.view = view - let fpc = FloatingPanelController() - fpc.set(contentViewController: contentVC) - fpc.delegate = delegate - fpc.backdropView.backgroundColor = UIColor.black - fpc.isRemovalInteractionEnabled = true - - objc_setAssociatedObject(fpc, &AssociatedDelegateHandle, delegate, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) - - vc.present(fpc, animated: true, completion: nil) - } -} - -class FloatingDelegate: FloatingPanelControllerDelegate { - private let floatingLayout: FloatingPanelLayout - private let onDismiss: () -> Void - - init(floatingLayout: FloatingPanelLayout, onDismiss: @escaping () -> Void) { - self.floatingLayout = floatingLayout - self.onDismiss = onDismiss - } - - func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { - return floatingLayout - } - - func floatingPanelDidEndRemove(_ vc: FloatingPanelController) { - onDismiss() - } -} - -class BottomSheetLayout: FloatingPanelLayout { - var initialPosition: FloatingPanelPosition = .half - - private let preferredHeight: CGFloat - - init(preferredHeight: CGFloat) { - self.preferredHeight = preferredHeight - } - - func insetFor(position: FloatingPanelPosition) -> CGFloat? { - switch (position) { - case .half: return preferredHeight - case .full: return 0 - case .tip: return 0 - case .hidden: return nil - } - } - - var supportedPositions: Set = [.half, .tip] - - func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { - return 0.3 - } -} diff --git a/widgets-datepicker/src/iosX64Main b/widgets-datepicker/src/iosX64Main deleted file mode 120000 index 93d7d747..00000000 --- a/widgets-datepicker/src/iosX64Main +++ /dev/null @@ -1 +0,0 @@ -iosMain \ No newline at end of file diff --git a/widgets/build.gradle.kts b/widgets/build.gradle.kts index f4fb51a5..860a90de 100644 --- a/widgets/build.gradle.kts +++ b/widgets/build.gradle.kts @@ -36,6 +36,7 @@ dependencies { mppLibrary(Deps.Libs.MultiPlatform.mokoMedia) mppLibrary(Deps.Libs.MultiPlatform.mokoGraphics) mppLibrary(Deps.Libs.MultiPlatform.mokoParcelize) + mppLibrary(Deps.Libs.MultiPlatform.klock) androidLibrary(Deps.Libs.Android.appCompat) androidLibrary(Deps.Libs.Android.recyclerView) diff --git a/widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt similarity index 75% rename from widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt rename to widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt index 7d56de5e..400d1091 100644 --- a/widgets-datepicker/src/androidMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt @@ -1,4 +1,4 @@ -package dev.icerock.moko.widgets.datepicker +package dev.icerock.moko.widgets.screen import android.app.DatePickerDialog import android.app.Dialog @@ -7,9 +7,8 @@ import android.os.Bundle import android.os.Parcel import android.os.Parcelable import androidx.fragment.app.DialogFragment +import com.soywiz.klock.DateTime import dev.icerock.moko.graphics.Color -import dev.icerock.moko.widgets.screen.Screen -import java.text.SimpleDateFormat import java.util.* import kotlin.properties.ReadOnlyProperty @@ -49,14 +48,9 @@ actual fun Screen<*>.registerDatePickerDialogHandler( actual class DatePickerDialogBuilder(private val dialogId: Int, private val screen: Screen<*>) { private val context: Context = screen.requireContext() - private var format: String = "" - private var startDate: DateTime? = null + private var startDate: DateTime? = null private var endDate: DateTime? = null - actual fun dateFormat(format: String) { - this.format = format - } - actual fun accentColor(color: Color) { //android color from style } @@ -78,7 +72,6 @@ actual class DatePickerDialogBuilder(private val dialogId: Int, private val scre DatePickerDialogFragment.instantiate( arg = DatePickerDialogFragment.Args( dialogId = dialogId, - format = format, startDate = startDate, endDate = endDate ) @@ -97,7 +90,6 @@ class DatePickerDialogFragment : DialogFragment() { requireNotNull(argument) { "can't be opened without argument" } val dialogId = argument.dialogId - val formatter = SimpleDateFormat(argument.format ?: "", Locale.getDefault()) val currentDate = Calendar.getInstance() val dialog = DatePickerDialog( context, { _ @@ -107,14 +99,14 @@ class DatePickerDialogFragment : DialogFragment() { -> val date = Calendar.getInstance() date.set(year, month, day) - listener?.onPositivePressed(dialogId, DateTime.timeInMillis(date.timeInMillis)) + listener?.onPositivePressed(dialogId, DateTime(date.timeInMillis)) }, currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DAY_OF_MONTH) ) - argument.endDate?.let { dialog.datePicker.maxDate = it.date.time } - argument.startDate?.let { dialog.datePicker.minDate = it.date.time } + argument.endDate?.let { dialog.datePicker.maxDate = it.unixMillisLong } + argument.startDate?.let { dialog.datePicker.minDate = it.unixMillisLong } dialog.setOnCancelListener { listener?.onNegativePressed(dialogId) } return dialog } @@ -126,28 +118,25 @@ class DatePickerDialogFragment : DialogFragment() { data class Args( val dialogId: Int, - val format: String?, val startDate: DateTime?, val endDate: DateTime? ) : Parcelable { constructor(parcel: Parcel) : this( parcel.readInt(), - parcel.readString(), parcel.readLong().let { if (it == 0L) null - else DateTime.timeInMillis(it) + else DateTime(it) }, parcel.readLong().let { if (it == 0L) null - else DateTime.timeInMillis(it) + else DateTime(it) } ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(dialogId) - parcel.writeString(format) - parcel.writeLong(startDate?.date?.time ?: 0L) - parcel.writeLong(endDate?.date?.time ?: 0L) + parcel.writeLong(startDate?.unixMillisLong ?: 0L) + parcel.writeLong(endDate?.unixMillisLong ?: 0L) } override fun describeContents(): Int { @@ -181,25 +170,3 @@ class DatePickerDialogFragment : DialogFragment() { } } } - -actual sealed class DateTime { - - abstract val date: Date - - actual fun format(format: String): String { - return SimpleDateFormat(format, Locale.getDefault()).format(date) - } - - actual class timeInMillis actual constructor(mills: Long) : DateTime() { - override val date = Date(mills) - } - - actual class fromString actual constructor(time: String, format: String) : DateTime() { - override val date: Date = SimpleDateFormat(format, Locale.getDefault()).parse(time) - } - - actual class now actual constructor() : DateTime() { - override val date = Date() - } - -} diff --git a/widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt similarity index 64% rename from widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt rename to widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index 8969724c..e18c7095 100644 --- a/widgets-datepicker/src/commonMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -1,7 +1,7 @@ -package dev.icerock.moko.widgets.datepicker +package dev.icerock.moko.widgets.screen +import com.soywiz.klock.DateTime import dev.icerock.moko.graphics.Color -import dev.icerock.moko.widgets.screen.Screen import kotlin.properties.ReadOnlyProperty expect class DatePickerDialogHandler @@ -12,7 +12,6 @@ expect fun Screen<*>.registerDatePickerDialogHandler( ): ReadOnlyProperty, DatePickerDialogHandler> expect class DatePickerDialogBuilder { - fun dateFormat(format: String) fun handler(handler: DatePickerDialogHandler) fun accentColor(color: Color) fun startDate(date: DateTime) @@ -22,16 +21,4 @@ expect class DatePickerDialogBuilder { expect fun Screen<*>.showDatePickerDialog( dialogId: Int, factory: DatePickerDialogBuilder.() -> Unit -) - -expect sealed class DateTime { - - fun format(format: String): String - - class timeInMillis(mills: Long) : DateTime - - class fromString(time: String, format: String) : - DateTime - - class now() : DateTime -} \ No newline at end of file +) \ No newline at end of file diff --git a/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt similarity index 64% rename from widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt rename to widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index 89841500..e3e24f9d 100644 --- a/widgets-datepicker/src/iosMain/kotlin/dev/icerock/moko/widgets/datepicker/ShowDatePickerExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -1,9 +1,10 @@ /* * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. */ -package dev.icerock.moko.widgets.datepicker +package dev.icerock.moko.widgets.screen +import com.soywiz.klock.DateTime import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.screen.Screen import kotlin.properties.ReadOnlyProperty @@ -18,9 +19,6 @@ actual fun Screen<*>.registerDatePickerDialogHandler( } actual class DatePickerDialogBuilder { - actual fun dateFormat(format: String) { - } - actual fun handler(handler: DatePickerDialogHandler) { } @@ -38,19 +36,5 @@ actual fun Screen<*>.showDatePickerDialog( dialogId: Int, factory: DatePickerDialogBuilder.() -> Unit ) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } - -actual sealed class DateTime { - actual fun format(format: String): String { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - - actual class timeInMillis actual constructor(mills: Long) : - DateTime() - - actual class fromString actual constructor(time: String, format: String) : - DateTime() - - actual class now actual constructor() : DateTime() - -} \ No newline at end of file From eba2e181287980fa502d37bbf4bcde3543c0759f Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 18:47:07 +0700 Subject: [PATCH 07/48] #90 fix review --- .../widgets/screen/DatePickerDialogHandler.kt | 73 +++++-------------- .../moko/widgets/screen/ShowDatePickerExt.kt | 4 +- .../moko/widgets/screen/ShowDatePickerExt.kt | 5 +- 3 files changed, 23 insertions(+), 59 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt index 400d1091..e0142fba 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt @@ -2,23 +2,24 @@ package dev.icerock.moko.widgets.screen import android.app.DatePickerDialog import android.app.Dialog -import android.content.Context import android.os.Bundle -import android.os.Parcel import android.os.Parcelable import androidx.fragment.app.DialogFragment import com.soywiz.klock.DateTime import dev.icerock.moko.graphics.Color +import dev.icerock.moko.parcelize.Parcelize import java.util.* import kotlin.properties.ReadOnlyProperty actual fun Screen<*>.showDatePickerDialog( dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit + factory: DatePickerDialogBuilder.() -> Unit, + handler: DatePickerDialogHandler ) { val alert = DatePickerDialogBuilder( dialogId, - this + this, + handler ) factory(alert) alert.show() @@ -45,20 +46,18 @@ actual fun Screen<*>.registerDatePickerDialogHandler( } } -actual class DatePickerDialogBuilder(private val dialogId: Int, private val screen: Screen<*>) { - private val context: Context = screen.requireContext() - - private var startDate: DateTime? = null +actual class DatePickerDialogBuilder( + private val dialogId: Int, + private val screen: Screen<*>, + private val handler: DatePickerDialogHandler +) { + private var startDate: DateTime? = null private var endDate: DateTime? = null actual fun accentColor(color: Color) { //android color from style } - actual fun handler(handler: DatePickerDialogHandler) { - // handler is just mark that `Screen` have registered alert handler - } - actual fun startDate(date: DateTime) { startDate = date } @@ -72,8 +71,8 @@ actual class DatePickerDialogBuilder(private val dialogId: Int, private val scre DatePickerDialogFragment.instantiate( arg = DatePickerDialogFragment.Args( dialogId = dialogId, - startDate = startDate, - endDate = endDate + startDate = startDate?.unixMillisLong, + endDate = endDate?.unixMillisLong ) ) alertDialogFragment.show(screen.childFragmentManager, null) @@ -105,8 +104,8 @@ class DatePickerDialogFragment : DialogFragment() { currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DAY_OF_MONTH) ) - argument.endDate?.let { dialog.datePicker.maxDate = it.unixMillisLong } - argument.startDate?.let { dialog.datePicker.minDate = it.unixMillisLong } + argument.endDate?.let { dialog.datePicker.maxDate = it } + argument.startDate?.let { dialog.datePicker.minDate = it } dialog.setOnCancelListener { listener?.onNegativePressed(dialogId) } return dialog } @@ -116,46 +115,12 @@ class DatePickerDialogFragment : DialogFragment() { fun onNegativePressed(dialogId: Int) } + @Parcelize data class Args( val dialogId: Int, - val startDate: DateTime?, - val endDate: DateTime? - ) : Parcelable { - constructor(parcel: Parcel) : this( - parcel.readInt(), - parcel.readLong().let { - if (it == 0L) null - else DateTime(it) - }, - parcel.readLong().let { - if (it == 0L) null - else DateTime(it) - } - ) - - override fun writeToParcel(parcel: Parcel, flags: Int) { - parcel.writeInt(dialogId) - parcel.writeLong(startDate?.unixMillisLong ?: 0L) - parcel.writeLong(endDate?.unixMillisLong ?: 0L) - } - - override fun describeContents(): Int { - return 0 - } - - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): Args { - return Args( - parcel - ) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } - - } + val startDate: Long?, + val endDate: Long? + ) : Parcelable companion object { private const val ARG_KEY = "arg_bundle" diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index e18c7095..349895d6 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -12,7 +12,6 @@ expect fun Screen<*>.registerDatePickerDialogHandler( ): ReadOnlyProperty, DatePickerDialogHandler> expect class DatePickerDialogBuilder { - fun handler(handler: DatePickerDialogHandler) fun accentColor(color: Color) fun startDate(date: DateTime) fun endDate(date: DateTime) @@ -20,5 +19,6 @@ expect class DatePickerDialogBuilder { expect fun Screen<*>.showDatePickerDialog( dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit + factory: DatePickerDialogBuilder.() -> Unit, + handler: DatePickerDialogHandler ) \ No newline at end of file diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index e3e24f9d..5516bd84 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -19,8 +19,6 @@ actual fun Screen<*>.registerDatePickerDialogHandler( } actual class DatePickerDialogBuilder { - actual fun handler(handler: DatePickerDialogHandler) { - } actual fun accentColor(color: Color) { } @@ -34,7 +32,8 @@ actual class DatePickerDialogBuilder { actual fun Screen<*>.showDatePickerDialog( dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit + factory: DatePickerDialogBuilder.() -> Unit, + handler: DatePickerDialogHandler ) { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } From d950d3b630fb9bc4617c8ff9d0ec265281012494 Mon Sep 17 00:00:00 2001 From: alobynya Date: Thu, 20 Feb 2020 19:05:58 +0700 Subject: [PATCH 08/48] #90 fix review --- buildSrc/src/main/kotlin/Deps.kt | 5 ----- moko-widgets-datepicker.podspec | 22 ------------------- .../widgets/screen/DatePickerDialogHandler.kt | 15 ++++++++----- .../moko/widgets/screen/ShowDatePickerExt.kt | 8 +++++-- .../moko/widgets/screen/ShowDatePickerExt.kt | 5 ++--- 5 files changed, 18 insertions(+), 37 deletions(-) delete mode 100644 moko-widgets-datepicker.podspec diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt index d2593ae5..1995fc9e 100755 --- a/buildSrc/src/main/kotlin/Deps.kt +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -70,11 +70,6 @@ object Deps { iosX64 = "dev.icerock.moko:widgets-bottomsheet-iosx64:${Versions.Libs.MultiPlatform.mokoWidgets}", iosArm64 = "dev.icerock.moko:widgets-bottomsheet-iosarm64:${Versions.Libs.MultiPlatform.mokoWidgets}" ) - val mokoWidgetsDatePicker = MultiPlatformLibrary( - common = "dev.icerock.moko:widgets-datepicker:${Versions.Libs.MultiPlatform.mokoWidgets}", - iosX64 = "dev.icerock.moko:widgets-datepicker-iosx64:${Versions.Libs.MultiPlatform.mokoWidgets}", - iosArm64 = "dev.icerock.moko:widgets-datepicker-iosarm64:${Versions.Libs.MultiPlatform.mokoWidgets}" - ) val mokoResources = MultiPlatformLibrary( common = "dev.icerock.moko:resources:${Versions.Libs.MultiPlatform.mokoResources}", iosX64 = "dev.icerock.moko:resources-iosx64:${Versions.Libs.MultiPlatform.mokoResources}", diff --git a/moko-widgets-datepicker.podspec b/moko-widgets-datepicker.podspec deleted file mode 100644 index 3955f4ce..00000000 --- a/moko-widgets-datepicker.podspec +++ /dev/null @@ -1,22 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = 'moko-widgets-datepicker' - spec.version = '0.1.0' - spec.homepage = 'https://github.com/icerockdev/moko-widgets' - spec.source = { :git => "https://github.com/icerockdev/moko-widgets.git", :tag => "release/#{spec.version}" } - spec.authors = 'IceRock Development' - spec.license = { :type => 'Apache 2', :file => 'LICENSE.md' } - spec.summary = 'Swift additions to moko-widgets Kotlin/Native library' - spec.module_name = "mokoWidgetsDatePicker" - - spec.source_files = "widgets-datepicker/src/iosMain/swift/**/*.{h,m,swift}" - spec.resources = "widgets-datepicker/src/iosMain/bundle/**/*" - - spec.dependency 'FloatingPanel' - - spec.ios.deployment_target = '11.0' - spec.swift_version = '5.0' - - spec.pod_target_xcconfig = { - 'VALID_ARCHS' => '$(ARCHS_STANDARD_64_BIT)' - } -end diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt index e0142fba..213caafd 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + package dev.icerock.moko.widgets.screen import android.app.DatePickerDialog @@ -5,6 +9,7 @@ import android.app.Dialog import android.os.Bundle import android.os.Parcelable import androidx.fragment.app.DialogFragment +import androidx.fragment.app.FragmentManager import com.soywiz.klock.DateTime import dev.icerock.moko.graphics.Color import dev.icerock.moko.parcelize.Parcelize @@ -13,12 +18,12 @@ import kotlin.properties.ReadOnlyProperty actual fun Screen<*>.showDatePickerDialog( dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit, - handler: DatePickerDialogHandler + handler: DatePickerDialogHandler, + factory: DatePickerDialogBuilder.() -> Unit ) { val alert = DatePickerDialogBuilder( dialogId, - this, + this.childFragmentManager, handler ) factory(alert) @@ -48,7 +53,7 @@ actual fun Screen<*>.registerDatePickerDialogHandler( actual class DatePickerDialogBuilder( private val dialogId: Int, - private val screen: Screen<*>, + private val fragmentManager: FragmentManager, private val handler: DatePickerDialogHandler ) { private var startDate: DateTime? = null @@ -75,7 +80,7 @@ actual class DatePickerDialogBuilder( endDate = endDate?.unixMillisLong ) ) - alertDialogFragment.show(screen.childFragmentManager, null) + alertDialogFragment.show(fragmentManager, null) } } diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index 349895d6..03ed1eea 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + package dev.icerock.moko.widgets.screen import com.soywiz.klock.DateTime @@ -19,6 +23,6 @@ expect class DatePickerDialogBuilder { expect fun Screen<*>.showDatePickerDialog( dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit, - handler: DatePickerDialogHandler + handler: DatePickerDialogHandler, + factory: DatePickerDialogBuilder.() -> Unit ) \ No newline at end of file diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index 5516bd84..4939e84d 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -6,7 +6,6 @@ package dev.icerock.moko.widgets.screen import com.soywiz.klock.DateTime import dev.icerock.moko.graphics.Color -import dev.icerock.moko.widgets.screen.Screen import kotlin.properties.ReadOnlyProperty actual class DatePickerDialogHandler @@ -32,8 +31,8 @@ actual class DatePickerDialogBuilder { actual fun Screen<*>.showDatePickerDialog( dialogId: Int, - factory: DatePickerDialogBuilder.() -> Unit, - handler: DatePickerDialogHandler + handler: DatePickerDialogHandler, + factory: DatePickerDialogBuilder.() -> Unit ) { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } From f3dde8fb4953b20e8ae5c2ed2872803ba959f99e Mon Sep 17 00:00:00 2001 From: Aleksandr Gusev Date: Fri, 21 Feb 2020 11:44:31 +0700 Subject: [PATCH 09/48] #100, Added expect-actual classes for search screen --- .../dev/icerock/moko/widgets/screen/SearchScreen.kt | 11 +++++++++++ .../dev/icerock/moko/widgets/screen/SearchScreen.kt | 12 ++++++++++++ .../dev/icerock/moko/widgets/screen/SearchScreen.kt | 11 +++++++++++ 3 files changed, 34 insertions(+) create mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt create mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt create mode 100644 widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt new file mode 100644 index 00000000..2cd33c77 --- /dev/null +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -0,0 +1,11 @@ +package dev.icerock.moko.widgets.screen + +import dev.icerock.moko.mvvm.livedata.LiveData +import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.core.Theme + +actual abstract class SearchScreen: Screen() { + actual abstract val searchQuery: MutableLiveData + actual abstract val searchItems: LiveData> +} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt new file mode 100644 index 00000000..51e74bb3 --- /dev/null +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -0,0 +1,12 @@ +package dev.icerock.moko.widgets.screen + +import dev.icerock.moko.mvvm.livedata.LiveData +import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.screen.navigation.Route + +expect abstract class SearchScreen: Screen { + abstract val searchQuery: MutableLiveData + abstract val searchItems: LiveData> +} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt new file mode 100644 index 00000000..c0dbbd4c --- /dev/null +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -0,0 +1,11 @@ +package dev.icerock.moko.widgets.screen + +import dev.icerock.moko.mvvm.livedata.LiveData +import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.units.TableUnitItem + + +actual abstract class SearchScreen: Screen() { + actual abstract val searchQuery: MutableLiveData + actual abstract val searchItems: LiveData> +} From f6948a7799534ed3ae153f3337039f317cb38508 Mon Sep 17 00:00:00 2001 From: Andrey Dorofeev Date: Fri, 21 Feb 2020 11:53:29 +0700 Subject: [PATCH 10/48] fixed secureTextEntry for input type on iOS --- .../iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt index 8d8ff6d9..3f05b158 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt @@ -19,7 +19,7 @@ fun UITextField.applyInputTypeIfNeeded( ) { if (type == null) return this.keyboardType = type.toPlatformInputType() - this.secureTextEntry = type == InputType.Password() + this.secureTextEntry = type is InputType.Password } private fun InputType.toPlatformInputType(): UIKeyboardType { From 8ecad73c0e41e435f48f2064bfdd68fa2297e1db Mon Sep 17 00:00:00 2001 From: Aleksandr Gusev Date: Fri, 21 Feb 2020 14:47:11 +0700 Subject: [PATCH 11/48] #100, Added iOS native screen and viewcontroller --- .../iosMain/bundle/SearchViewController.xib | 39 ++++++++++++++++++ .../iosMain/swift/SearchViewController.swift | 40 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 widgets/src/iosMain/bundle/SearchViewController.xib create mode 100644 widgets/src/iosMain/swift/SearchViewController.swift diff --git a/widgets/src/iosMain/bundle/SearchViewController.xib b/widgets/src/iosMain/bundle/SearchViewController.xib new file mode 100644 index 00000000..32fc1c91 --- /dev/null +++ b/widgets/src/iosMain/bundle/SearchViewController.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/widgets/src/iosMain/swift/SearchViewController.swift b/widgets/src/iosMain/swift/SearchViewController.swift new file mode 100644 index 00000000..597ea5f7 --- /dev/null +++ b/widgets/src/iosMain/swift/SearchViewController.swift @@ -0,0 +1,40 @@ +/* +* Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. +*/ + +import UIKit + +@objc public class SearchViewController: UIViewController { + @IBOutlet weak var navItem: UINavigationItem! + + @objc public static func create() -> SearchViewController { + return SearchViewController( + nibName: nil, + bundle: Bundle(for: SearchViewController.self) + ) + } + + func setupSearchController() { + let searchController = UISearchController(searchResultsController: nil) + // Setup the Search Controller + searchController.searchResultsUpdater = self + searchController.obscuresBackgroundDuringPresentation = false + searchController.searchBar.placeholder = "Search" + navItem.searchController = searchController + definesPresentationContext = true + + let searchField = searchController.searchBar.searchTextField + searchField.textColor = UIColor.red + + //tableView.tableHeaderView = searchController.searchBar + } +} + +// MARK: - UISearchResultsUpdating Delegate +extension SearchViewController: UISearchResultsUpdating { + + public func updateSearchResults(for searchController: UISearchController) { + print("\n updateSearchResults \n") + } +} + From 1458dec3673d19770a7a352b70fbf903e047e632 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Fri, 21 Feb 2020 15:07:21 +0700 Subject: [PATCH 12/48] #131 rework tabs customization --- .../widgets/factory/SystemTabsViewFactory.kt | 47 ++++++++++-- .../widgets/factory/SystemTabsViewFactory.kt | 10 ++- .../widgets/factory/SystemTabsViewFactory.kt | 71 ++++++++++++++++--- 3 files changed, 112 insertions(+), 16 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index d87882ca..aa962644 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -4,6 +4,7 @@ package dev.icerock.moko.widgets.factory +import android.content.res.ColorStateList import android.view.ContextThemeWrapper import android.view.Gravity import android.view.View @@ -13,6 +14,8 @@ import android.widget.LinearLayout import android.widget.TabHost import android.widget.TabWidget import android.widget.TextView +import androidx.core.view.ViewCompat +import dev.icerock.moko.graphics.Color import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.widgets.TabsWidget import dev.icerock.moko.widgets.core.ViewBundle @@ -27,8 +30,13 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bindNotNull actual class SystemTabsViewFactory actual constructor( - private val background: Background?, - private val padding: PaddingValues?, + private val tabsTintColor: Color?, + private val selectedTitleColor: Color?, + private val normalTitleColor: Color?, + private val tabsBackground: Background?, + private val contentBackground: Background?, + private val tabsPadding: PaddingValues?, + private val contentPadding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { @@ -42,12 +50,12 @@ actual class SystemTabsViewFactory actual constructor( val tabHost = TabHost(context).apply { id = android.R.id.tabhost - - applyBackgroundIfNeeded(this@SystemTabsViewFactory.background) } val container = LinearLayout(context).apply { orientation = LinearLayout.VERTICAL + + applyBackgroundIfNeeded(this@SystemTabsViewFactory.contentBackground) } tabHost.addView( @@ -58,6 +66,8 @@ actual class SystemTabsViewFactory actual constructor( val tabWidget = TabWidget(context).apply { id = android.R.id.tabs + + applyBackgroundIfNeeded(this@SystemTabsViewFactory.tabsBackground) } container.addView( @@ -66,10 +76,18 @@ actual class SystemTabsViewFactory actual constructor( ViewGroup.LayoutParams.WRAP_CONTENT ) + tabsPadding?.also { + val mlp = tabWidget.layoutParams as ViewGroup.MarginLayoutParams + mlp.topMargin = it.top.toInt() + mlp.bottomMargin = it.bottom.toInt() + mlp.leftMargin = it.start.toInt() + mlp.rightMargin = it.end.toInt() + } + val content = FrameLayout(context).apply { id = android.R.id.tabcontent - applyPaddingIfNeeded(padding) + applyPaddingIfNeeded(contentPadding) } container.addView( content, @@ -95,6 +113,25 @@ actual class SystemTabsViewFactory actual constructor( ).apply { text = stringDesc.toString(context) } + tabsTintColor?.also { + ViewCompat.setBackgroundTintList(tabContainer, ColorStateList.valueOf(it.argb.toInt())) + } + val selected = selectedTitleColor?.argb?.toInt() + val normal = normalTitleColor?.argb?.toInt() + if (selected != null && normal != null) { + text.setTextColor( + ColorStateList( + arrayOf( + intArrayOf(android.R.attr.state_selected), + intArrayOf(-android.R.attr.state_selected) + ), + intArrayOf( + selected, + normal + ) + ) + ) + } tabContainer.addView( text, FrameLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index 36c9d90a..ad196bde 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -4,6 +4,7 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.TabsWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background @@ -12,7 +13,12 @@ import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemTabsViewFactory( - background: Background? = null, - padding: PaddingValues? = null, + tabsTintColor: Color? = null, + selectedTitleColor: Color? = null, + normalTitleColor: Color? = null, + tabsBackground: Background? = null, + contentBackground: Background? = null, + tabsPadding: PaddingValues? = null, + contentPadding: PaddingValues? = null, margins: MarginValues? = null ) : ViewFactory> diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index cd0a4e91..796f1ddd 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -4,6 +4,8 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.graphics.toUIColor import dev.icerock.moko.widgets.TabsWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory @@ -21,7 +23,11 @@ import dev.icerock.moko.widgets.utils.setEventHandler import kotlinx.cinterop.readValue import platform.CoreGraphics.CGFloat import platform.CoreGraphics.CGRectZero +import platform.UIKit.NSForegroundColorAttributeName import platform.UIKit.UIControlEventValueChanged +import platform.UIKit.UIControlStateNormal +import platform.UIKit.UIControlStateSelected +import platform.UIKit.UIDevice import platform.UIKit.UILayoutConstraintAxisVertical import platform.UIKit.UILayoutPriorityDefaultLow import platform.UIKit.UILayoutPriorityRequired @@ -35,13 +41,19 @@ import platform.UIKit.hidden import platform.UIKit.leadingAnchor import platform.UIKit.setContentHuggingPriority import platform.UIKit.subviews +import platform.UIKit.tintColor import platform.UIKit.topAnchor import platform.UIKit.trailingAnchor import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemTabsViewFactory actual constructor( - private val background: Background?, - private val padding: PaddingValues?, + private val tabsTintColor: Color?, + private val selectedTitleColor: Color?, + private val normalTitleColor: Color?, + private val tabsBackground: Background?, + private val contentBackground: Background?, + private val tabsPadding: PaddingValues?, + private val contentPadding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { @@ -60,6 +72,16 @@ actual class SystemTabsViewFactory actual constructor( UILayoutPriorityDefaultLow, forAxis = UILayoutConstraintAxisVertical ) + + tabsTintColor?.also { + if (UIDevice.currentDevice.systemVersion.compareTo("13.0") < 0) { + tintColor = it.toUIColor() + } else { + selectedSegmentTintColor = it.toUIColor() + } + } + + applyBackgroundIfNeeded(tabsBackground) } val container = UIView(frame = CGRectZero.readValue()).apply { @@ -68,6 +90,26 @@ actual class SystemTabsViewFactory actual constructor( UILayoutPriorityRequired, forAxis = UILayoutConstraintAxisVertical ) + + applyBackgroundIfNeeded(contentBackground) + } + + + selectedTitleColor?.also { + segmentedControl.setTitleTextAttributes( + attributes = mapOf( + NSForegroundColorAttributeName to it.toUIColor() + ), + forState = UIControlStateSelected + ) + } + normalTitleColor?.also { + segmentedControl.setTitleTextAttributes( + attributes = mapOf( + NSForegroundColorAttributeName to it.toUIColor() + ), + forState = UIControlStateNormal + ) } widget.tabs.forEachIndexed { index, tabWidget -> @@ -96,7 +138,7 @@ actual class SystemTabsViewFactory actual constructor( val edges: Edges = applySizeToChild( rootView = container, - rootPadding = padding, + rootPadding = contentPadding, childView = view, childSize = viewBundle.size, childMargins = viewBundle.margins @@ -123,16 +165,27 @@ actual class SystemTabsViewFactory actual constructor( val view = UIView(frame = CGRectZero.readValue()).apply { translatesAutoresizingMaskIntoConstraints = false - applyBackgroundIfNeeded(background) addSubview(segmentedControl) addSubview(container) - segmentedControl.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true - segmentedControl.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true - segmentedControl.topAnchor.constraintEqualToAnchor(topAnchor).active = true - - container.topAnchor.constraintEqualToAnchor(segmentedControl.bottomAnchor).active = true + segmentedControl.leadingAnchor.constraintEqualToAnchor( + leadingAnchor, + constant = tabsPadding?.start?.toDouble() ?: 0.0 + ).active = true + trailingAnchor.constraintEqualToAnchor( + segmentedControl.trailingAnchor, + constant = tabsPadding?.end?.toDouble() ?: 0.0 + ).active = true + segmentedControl.topAnchor.constraintEqualToAnchor( + topAnchor, + constant = tabsPadding?.top?.toDouble() ?: 0.0 + ).active = true + + container.topAnchor.constraintEqualToAnchor( + segmentedControl.bottomAnchor, + constant = tabsPadding?.bottom?.toDouble() ?: 0.0 + ).active = true container.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true container.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true From 7a4d198606aa7119b35ee78cc82c9036ac7a2147 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Fri, 21 Feb 2020 15:07:38 +0700 Subject: [PATCH 13/48] #131 add sample of usage --- sample/mpp-library/src/commonMain/kotlin/App.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sample/mpp-library/src/commonMain/kotlin/App.kt b/sample/mpp-library/src/commonMain/kotlin/App.kt index c32ef708..c5fd757e 100644 --- a/sample/mpp-library/src/commonMain/kotlin/App.kt +++ b/sample/mpp-library/src/commonMain/kotlin/App.kt @@ -21,6 +21,7 @@ import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.widgets.ButtonWidget import dev.icerock.moko.widgets.ImageWidget import dev.icerock.moko.widgets.InputWidget +import dev.icerock.moko.widgets.TabsWidget import dev.icerock.moko.widgets.button import dev.icerock.moko.widgets.container import dev.icerock.moko.widgets.core.Theme @@ -31,6 +32,7 @@ import dev.icerock.moko.widgets.factory.IconGravity import dev.icerock.moko.widgets.factory.LinearViewFactory import dev.icerock.moko.widgets.factory.SystemImageViewFactory import dev.icerock.moko.widgets.factory.SystemInputViewFactory +import dev.icerock.moko.widgets.factory.SystemTabsViewFactory import dev.icerock.moko.widgets.flat.FlatInputViewFactory import dev.icerock.moko.widgets.sample.InputWidgetGalleryScreen import dev.icerock.moko.widgets.sample.ScrollContentScreen @@ -51,7 +53,6 @@ import dev.icerock.moko.widgets.screen.navigation.Route import dev.icerock.moko.widgets.screen.navigation.SelectStates import dev.icerock.moko.widgets.screen.navigation.createPushResultRoute import dev.icerock.moko.widgets.screen.navigation.createPushRoute -import dev.icerock.moko.widgets.screen.navigation.createReplaceRoute import dev.icerock.moko.widgets.screen.navigation.createRouter import dev.icerock.moko.widgets.screen.navigation.route import dev.icerock.moko.widgets.style.background.Background @@ -62,6 +63,7 @@ import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.utils.platformSpecific class App() : BaseApplication() { @@ -175,6 +177,12 @@ class App() : BaseApplication() { color = Color(0x16171AFF) ) ) + factory[TabsWidget.DefaultCategory] = SystemTabsViewFactory( + tabsTintColor = Color(0xD20C0AFF), + tabsPadding = platformSpecific(android = null, ios = PaddingValues(padding = 16f)), + selectedTitleColor = Color(platformSpecific(android = 0x151515FF, ios = 0xFFFFFFFF)), + normalTitleColor = platformSpecific(android = Color(0x15151599), ios = null) + ) } val mainScreen = registerScreen(MainBottomNavigationScreen::class) { From 64295ffa8031dac076236cd4f6c9bb84c4e43da0 Mon Sep 17 00:00:00 2001 From: alobynya Date: Fri, 21 Feb 2020 16:19:11 +0700 Subject: [PATCH 14/48] #100 android search screen --- .../moko/widgets/screen/SearchScreen.kt | 98 ++++++++++++++++++- .../moko/widgets/screen/SearchScreen.kt | 8 +- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 2cd33c77..cf046e3e 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -1,11 +1,107 @@ package dev.icerock.moko.widgets.screen +import android.graphics.Color +import android.os.Bundle +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.SearchView +import androidx.cardview.widget.CardView import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.ListWidget import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.core.ViewFactoryContext +import dev.icerock.moko.widgets.list +import dev.icerock.moko.widgets.style.view.WidgetSize + +actual abstract class SearchScreen actual constructor() : Screen() { -actual abstract class SearchScreen: Screen() { actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> + actual open val theme: Theme? = null + actual open val listCategory: ListWidget.Category? = null + actual abstract fun onReachEnd() + open val searchHint: StringDesc? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): android.view.View? { + + val rootLayout = LinearLayout(context) + rootLayout.orientation = LinearLayout.VERTICAL + + context?.let { context -> + + val cardView = CardView(context) + + val radius = 8 * context.resources.displayMetrics.density + val padding = radius.toInt() + cardView.radius = radius + cardView.layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + setMargins(padding, padding, padding, padding) + } + + val searchView = SearchView(context) + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?): Boolean { + searchQuery.value = query ?: "" + return true + } + + override fun onQueryTextChange(newText: String?): Boolean { + if (newText?.isEmpty() == true) { + searchQuery.value = newText + return true + } + return false + } + + }) + searchView.setOnSearchClickListener { _ -> + searchQuery.value = searchView.query.toString() + } + searchView.queryHint = searchHint?.toString(context) + + searchView.setBackgroundColor(Color.WHITE) + + cardView.addView(searchView) + + rootLayout.addView(cardView) + } + + val listWidget = + (theme ?: Theme()).list( + size = WidgetSize.AsParent, + id = Ids.ListId, + category = listCategory ?: ListWidget.DefaultCategory, + items = searchItems, + onReachEnd = ::onReachEnd + ) + + val view = listWidget.buildView( + ViewFactoryContext( + context = requireContext(), + lifecycleOwner = this, + parent = container + ) + ).view + + rootLayout.background = view.background + view.background = null + + rootLayout.addView(view) + return rootLayout + } + + object Ids { + object ListId : ListWidget.Id + } } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index c0dbbd4c..744347a2 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -2,10 +2,16 @@ package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.ListWidget +import dev.icerock.moko.widgets.core.Theme -actual abstract class SearchScreen: Screen() { +actual abstract class SearchScreen actual constructor() : Screen() { actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> + actual abstract fun onReachEnd() + actual open val theme: Theme? = null + actual open val listCategory: ListWidget.Category? = null } From 5d0ec22d4ae724b88ed762faa1d123c4b1c07694 Mon Sep 17 00:00:00 2001 From: Andrew Kovalev Date: Fri, 21 Feb 2020 16:43:17 +0700 Subject: [PATCH 15/48] #133 Multiline input widget factory implementation --- .../factory/MultilineInputViewFactory.kt | 141 ++++++++++++++++ .../factory/MultilineInputViewFactory.kt | 31 ++++ .../factory/MultilineInputViewFactory.kt | 154 ++++++++++++++++++ .../icerock/moko/widgets/style/InputTypes.kt | 9 + .../moko/widgets/utils/TextStyleExt.kt | 17 ++ 5 files changed, 352 insertions(+) create mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt create mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt create mode 100644 widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt new file mode 100644 index 00000000..02cb2b09 --- /dev/null +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt @@ -0,0 +1,141 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.factory + +import android.annotation.SuppressLint +import android.graphics.drawable.GradientDrawable +import android.text.Editable +import android.text.TextWatcher +import android.view.ViewGroup +import android.widget.EditText +import android.widget.LinearLayout +import androidx.core.view.MarginLayoutParamsCompat +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.graphics.colorInt +import dev.icerock.moko.widgets.InputWidget +import dev.icerock.moko.widgets.core.ViewBundle +import dev.icerock.moko.widgets.core.ViewFactory +import dev.icerock.moko.widgets.core.ViewFactoryContext +import dev.icerock.moko.widgets.style.applyInputType +import dev.icerock.moko.widgets.style.applyPaddingIfNeeded +import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded +import dev.icerock.moko.widgets.style.ext.getGravityForTextAlignment +import dev.icerock.moko.widgets.style.view.CornerRadiusValue +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.utils.androidId +import dev.icerock.moko.widgets.utils.bind +import dev.icerock.moko.widgets.utils.dp +import kotlin.math.ceil + +actual class MultilineInputViewFactory actual constructor( + private val cornerRadiusValue: CornerRadiusValue?, + private val borderColor: Color?, + private val borderWidth: Float?, + private val backgroundViewColor: Color?, + private val margins: MarginValues?, + private val padding: PaddingValues?, + private val textStyle: TextStyle?, + private val labelTextColor: Color?, + private val textHorizontalAlignment: TextHorizontalAlignment? +) : ViewFactory> { + + @SuppressLint("RestrictedApi") + override fun build( + widget: InputWidget, + size: WS, + viewFactoryContext: ViewFactoryContext + ): ViewBundle { + val context = viewFactoryContext.androidContext + val lifecycleOwner = viewFactoryContext.lifecycleOwner + + val editText = EditText(context).apply { + applyPaddingIfNeeded(padding) + + val backgroundDrawable = GradientDrawable() + val scale = context.resources.displayMetrics.density + + backgroundViewColor?.let { + backgroundDrawable.setColor(it.colorInt()) + } + + cornerRadiusValue?.radius?.let { + backgroundDrawable.cornerRadius = it * scale + } + + borderColor?.let { + backgroundDrawable.setStroke(ceil((borderWidth ?: 1f) * scale).toInt(), it.colorInt()) + } + background = backgroundDrawable + + id = widget.id.androidId + + layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + // EditText's default background have paddings 4dp, while we not change background to own we just change margins + // https://stackoverflow.com/questions/31735291/removing-the-left-padding-on-an-android-edittext/44497551 + val dp4 = (-4).dp(context) + MarginLayoutParamsCompat.setMarginStart(this, dp4) + MarginLayoutParamsCompat.setMarginEnd(this, dp4) + } + + applyTextStyleIfNeeded(textStyle) + widget.inputType?.also { applyInputType(it) } + + // If there is any nonnull text alignment argument, then set it to gravity + // otherwise gravity will be with default value. + if(textHorizontalAlignment != null) { + gravity = getGravityForTextAlignment( + textHorizontalAlignment = textHorizontalAlignment, + textVerticalAlignment = null + ) + } + + setOnFocusChangeListener { _, hasFocus -> + if (!hasFocus) widget.field.validate() + } + addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(s: Editable?) {} + + override fun beforeTextChanged( + s: CharSequence?, + start: Int, + count: Int, + after: Int + ) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + if (s == null) return + + widget.field.data.value = s.toString() + } + }) + + // setting hint text color + labelTextColor?.let { setHintTextColor(it.colorInt()) } + } + + widget.field.data.bind(lifecycleOwner) { data -> + if (editText.text?.toString() == data) return@bind + + editText.setText(data) + } + + widget.label.bind(lifecycleOwner) { editText.hint = it?.toString(context) } + widget.enabled?.bind(lifecycleOwner) { editText.isEnabled = it == true } + editText.setSingleLine(false) + + return ViewBundle( + view = editText, + size = size, + margins = margins + ) + } +} \ No newline at end of file diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt new file mode 100644 index 00000000..fdb72fbc --- /dev/null +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.factory + +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.widgets.InputWidget +import dev.icerock.moko.widgets.core.ViewFactory +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Border +import dev.icerock.moko.widgets.style.view.CornerRadiusValue +import dev.icerock.moko.widgets.style.view.IOSFieldBorderStyle +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.TextVerticalAlignment +import dev.icerock.moko.widgets.style.view.WidgetSize + +expect class MultilineInputViewFactory( + cornerRadiusValue: CornerRadiusValue?, + borderColor: Color?, + borderWidth: Float?, + backgroundViewColor: Color?, + margins: MarginValues? = null, + padding: PaddingValues? = null, + textStyle: TextStyle? = null, + labelTextColor: Color? = null, + textHorizontalAlignment: TextHorizontalAlignment? = null +) : ViewFactory> \ No newline at end of file diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt new file mode 100644 index 00000000..21942f56 --- /dev/null +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt @@ -0,0 +1,154 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.factory + +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.graphics.toUIColor +import dev.icerock.moko.widgets.InputWidget +import dev.icerock.moko.widgets.core.ViewBundle +import dev.icerock.moko.widgets.core.ViewFactory +import dev.icerock.moko.widgets.core.ViewFactoryContext +import dev.icerock.moko.widgets.objc.setAssociatedObject +import dev.icerock.moko.widgets.style.applyInputTypeIfNeeded +import dev.icerock.moko.widgets.style.view.CornerRadiusValue +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.utils.applyTextStyleIfNeeded +import dev.icerock.moko.widgets.utils.bind +import kotlinx.cinterop.readValue +import platform.CoreGraphics.CGRectZero +import platform.UIKit.NSTextAlignmentCenter +import platform.UIKit.NSTextAlignmentLeft +import platform.UIKit.NSTextAlignmentRight +import platform.UIKit.UIColor +import platform.UIKit.UITextView +import platform.UIKit.UITextViewDelegateProtocol +import platform.UIKit.backgroundColor +import platform.UIKit.clipsToBounds +import platform.UIKit.translatesAutoresizingMaskIntoConstraints +import platform.darwin.NSObject + +actual class MultilineInputViewFactory actual constructor( + private val cornerRadiusValue: CornerRadiusValue?, + private val borderColor: Color?, + private val borderWidth: Float?, + private val backgroundViewColor: Color?, + private val margins: MarginValues?, + private val padding: PaddingValues?, + private val textStyle: TextStyle?, + private val labelTextColor: Color?, + private val textHorizontalAlignment: TextHorizontalAlignment? +) : ViewFactory> { + + private var isPlaceholderShow: Boolean = false + + override fun build( + widget: InputWidget, + size: WS, + viewFactoryContext: ViewFactoryContext + ): ViewBundle { + + val textView = UITextView(frame = CGRectZero.readValue()).apply { + translatesAutoresizingMaskIntoConstraints = false + + borderColor?.let { + layer.borderColor = it.toUIColor().CGColor + } + + borderWidth?.let { + layer.borderWidth = it.toDouble() + } + + cornerRadiusValue?.let { + layer.cornerRadius = it.radius.toDouble() + } + + backgroundViewColor?.let { + backgroundColor = it.toUIColor() + } + + applyTextStyleIfNeeded(textStyle) + applyInputTypeIfNeeded(widget.inputType) + + clipsToBounds = true + + when (textHorizontalAlignment) { + TextHorizontalAlignment.LEFT -> textAlignment = NSTextAlignmentLeft + TextHorizontalAlignment.CENTER -> textAlignment = NSTextAlignmentCenter + TextHorizontalAlignment.RIGHT -> textAlignment = NSTextAlignmentRight + null -> { + } + } + } + + widget.enabled?.bind { textView.editable = it } + widget.field.data.bind { textView.text = it } + + + val textDelegate = TextViewDelegate( + textChangedHandler = { newValue -> + val currentValue = widget.field.data.value + + if (currentValue != newValue) { + widget.field.data.value = newValue + } + }, + didBeginEditHandler = { + if (isPlaceholderShow) { + textView.text = "" + textView.textColor = textStyle?.color?.toUIColor() ?: UIColor.blackColor + isPlaceholderShow = false + } + }, + didEndEditHandler = { + if (textView.text.isEmpty()) { + textView.text = widget.label.value.localized() + textView.textColor = labelTextColor?.toUIColor() ?: UIColor.grayColor + isPlaceholderShow = true + } + } + ) + + if (widget.label.value.localized().isNotEmpty()) { + if (widget.field.data.value.isEmpty()) { + isPlaceholderShow = true + textView.text = widget.label.value.localized() + textView.textColor = labelTextColor?.toUIColor() ?: UIColor.grayColor + } + } + + setAssociatedObject(textView, textDelegate) + textView.delegate = textDelegate + + return ViewBundle( + view = textView, + size = size, + margins = margins + ) + } + + private class TextViewDelegate( + private val textChangedHandler: (String) -> Unit, + private val didBeginEditHandler: (() -> Unit)?, + private val didEndEditHandler: (() -> Unit)? + ) : NSObject(), UITextViewDelegateProtocol { + + override fun textViewDidChange(textView: UITextView) { + textChangedHandler(textView.text) + } + + override fun textViewDidBeginEditing(textView: UITextView) { + didBeginEditHandler?.invoke() + } + + override fun textViewDidEndEditing(textView: UITextView) { + didEndEditHandler?.invoke() + } + } +} + diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt index 8d8ff6d9..14ec2a15 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/InputTypes.kt @@ -12,6 +12,7 @@ import platform.UIKit.UIKeyboardTypeDefault import platform.UIKit.UIKeyboardTypeDecimalPad import platform.UIKit.UIKeyboardTypePhonePad import platform.UIKit.UIKeyboardTypeNumberPad +import platform.UIKit.UITextView fun UITextField.applyInputTypeIfNeeded( @@ -22,6 +23,14 @@ fun UITextField.applyInputTypeIfNeeded( this.secureTextEntry = type == InputType.Password() } +fun UITextView.applyInputTypeIfNeeded( + type: InputType? +) { + if (type == null) return + this.keyboardType = type.toPlatformInputType() + this.secureTextEntry = type == InputType.Password() +} + private fun InputType.toPlatformInputType(): UIKeyboardType { return when (this) { is InputType.Email -> UIKeyboardTypeEmailAddress diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt index 5d9e1214..b0b64db0 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt @@ -17,6 +17,7 @@ import platform.UIKit.UILabel import platform.UIKit.UITextField import platform.UIKit.systemFontSize import platform.UIKit.UIFontWeightMedium +import platform.UIKit.UITextView fun TextStyle.toUIFont(defautlFontSize: Double = 17.0): UIFont? { // If this is ok, can be applied to other methods val styleSize = size?.toDouble() @@ -90,3 +91,19 @@ fun CATextLayer.applyTextStyleIfNeeded(textStyle: TextStyle?) { ) } } + +fun UITextView.applyTextStyleIfNeeded(textStyle: TextStyle?) { + if (textStyle == null) return + + val currentFontSize = font?.pointSize ?: UIFont.systemFontSize + val styleSize = textStyle.size?.toDouble() + val styleStyle = textStyle.fontStyle + if (styleStyle != null || styleSize != null) { + val fontSize = styleSize ?: currentFontSize + font = when (styleStyle) { + FontStyle.BOLD -> UIFont.boldSystemFontOfSize(fontSize = fontSize) + else -> UIFont.systemFontOfSize(fontSize = fontSize) + } + } + textStyle.color?.also { textColor = it.toUIColor() } +} From dbc1b0c06294c2ed5eef8d0e8f68c289c218881c Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Fri, 21 Feb 2020 22:20:07 +0700 Subject: [PATCH 16/48] #138 separate solid and Gradient background in api to limit where used sublayer background in iOS #13 add support of different textcolor for button states #117 remove text-specific code - wrapper of UILabel is removed --- .../mpp-library/src/commonMain/kotlin/App.kt | 17 +- .../kotlin/com/icerockdev/library/AppTheme.kt | 43 ++--- .../icerockdev/library/sample/StateSample.kt | 5 +- .../moko/widgets/flat/FlatInputViewFactory.kt | 2 +- .../moko/widgets/flat/FlatInputViewFactory.kt | 2 +- .../moko/widgets/flat/FlatInputViewFactory.kt | 2 +- .../factory/ButtonWithIconViewFactory.kt | 38 ++-- .../moko/widgets/factory/CardViewFactory.kt | 7 +- .../factory/CheckboxSwitchViewFactory.kt | 6 + .../widgets/factory/ConstraintViewFactory.kt | 3 +- .../widgets/factory/ContainerViewFactory.kt | 3 +- .../widgets/factory/FlatAlertViewFactory.kt | 163 ------------------ .../factory/FloatingLabelInputViewFactory.kt | 9 +- .../moko/widgets/factory/LinearViewFactory.kt | 5 +- .../widgets/factory/StatefulViewFactory.kt | 5 +- .../factory/SystemButtonViewFactory.kt | 9 +- .../factory/SystemCollectionViewFactory.kt | 5 +- .../widgets/factory/SystemImageViewFactory.kt | 7 +- .../widgets/factory/SystemInputViewFactory.kt | 18 +- .../widgets/factory/SystemListViewFactory.kt | 3 +- .../factory/SystemScrollViewFactory.kt | 3 +- .../factory/SystemSingleChoiceViewFactory.kt | 7 +- .../factory/SystemSwitchViewFactory.kt | 34 +--- .../widgets/factory/SystemTabsViewFactory.kt | 5 +- .../widgets/factory/SystemTextViewFactory.kt | 6 +- .../moko/widgets/factory/WebViewFactory.kt | 5 +- .../moko/widgets/style/StateListColorExt.kt | 22 +++ .../widgets/style/StateListDrawableExt.kt | 26 +++ .../icerock/moko/widgets/style/TextViewExt.kt | 44 ++--- .../dev/icerock/moko/widgets/style/ViewExt.kt | 38 +--- .../widgets/style/background/BackgroundExt.kt | 17 +- .../icerock/moko/widgets/FlatAlertWidget.kt | 41 ----- .../factory/ButtonWithIconViewFactory.kt | 15 +- .../moko/widgets/factory/CardViewFactory.kt | 5 +- .../factory/CheckboxSwitchViewFactory.kt | 3 + .../widgets/factory/ConstraintViewFactory.kt | 3 +- .../widgets/factory/ContainerViewFactory.kt | 3 +- .../widgets/factory/FlatAlertViewFactory.kt | 16 -- .../factory/FloatingLabelInputViewFactory.kt | 15 +- .../moko/widgets/factory/LinearViewFactory.kt | 9 +- .../widgets/factory/StatefulViewFactory.kt | 5 +- .../factory/SystemButtonViewFactory.kt | 9 +- .../factory/SystemCollectionViewFactory.kt | 5 +- .../widgets/factory/SystemImageViewFactory.kt | 3 +- .../widgets/factory/SystemInputViewFactory.kt | 13 +- .../widgets/factory/SystemListViewFactory.kt | 3 +- .../factory/SystemScrollViewFactory.kt | 3 +- .../factory/SystemSingleChoiceViewFactory.kt | 7 +- .../factory/SystemSwitchViewFactory.kt | 7 +- .../widgets/factory/SystemTabsViewFactory.kt | 6 +- .../widgets/factory/SystemTextViewFactory.kt | 6 +- .../widgets/factory/VisibilityViewFactory.kt | 1 - .../moko/widgets/factory/WebViewFactory.kt | 3 +- .../screen/navigation/NavigationScreen.kt | 3 +- .../icerock/moko/widgets/style/ColorStyle.kt | 19 -- .../widgets/style/background/Background.kt | 6 +- .../moko/widgets/style/background/Shape.kt | 10 -- .../style/background/StateBackground.kt | 11 -- .../moko/widgets/style/input/InputType.kt | 14 +- .../widgets/style/state/FocusableState.kt | 12 ++ .../widgets/style/state/PressableState.kt | 13 ++ .../widgets/style/state/SelectableState.kt | 12 ++ .../moko/widgets/style/view/Backgrounded.kt | 11 -- .../widgets/style/view/StateBackgrounded.kt | 11 -- .../moko/widgets/style/view/TextStyle.kt | 6 +- .../factory/ButtonWithIconViewFactory.kt | 27 +-- .../moko/widgets/factory/CardViewFactory.kt | 33 +++- .../factory/CheckboxSwitchViewFactory.kt | 11 +- .../widgets/factory/ConstraintViewFactory.kt | 3 +- .../widgets/factory/ContainerViewFactory.kt | 5 +- .../widgets/factory/FlatAlertViewFactory.kt | 116 ------------- .../factory/FloatingLabelInputViewFactory.kt | 34 ++-- .../moko/widgets/factory/LinearViewFactory.kt | 5 +- .../widgets/factory/StatefulViewFactory.kt | 5 +- .../factory/SystemButtonViewFactory.kt | 16 +- .../factory/SystemCollectionViewFactory.kt | 11 +- .../widgets/factory/SystemImageViewFactory.kt | 5 +- .../widgets/factory/SystemInputViewFactory.kt | 20 ++- .../widgets/factory/SystemListViewFactory.kt | 3 +- .../factory/SystemScrollViewFactory.kt | 3 +- .../factory/SystemSingleChoiceViewFactory.kt | 7 +- .../factory/SystemSwitchViewFactory.kt | 10 +- .../widgets/factory/SystemTabsViewFactory.kt | 5 +- .../widgets/factory/SystemTextViewFactory.kt | 49 +----- .../moko/widgets/factory/WebViewFactory.kt | 17 +- .../moko/widgets/utils/BackgroundExt.kt | 66 +++---- .../moko/widgets/utils/TextStyleExt.kt | 39 ++++- 87 files changed, 538 insertions(+), 820 deletions(-) delete mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt create mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListColorExt.kt create mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListDrawableExt.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/ColorStyle.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Shape.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/StateBackground.kt create mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/FocusableState.kt create mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/PressableState.kt create mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/SelectableState.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Backgrounded.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/StateBackgrounded.kt delete mode 100644 widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt diff --git a/sample/mpp-library/src/commonMain/kotlin/App.kt b/sample/mpp-library/src/commonMain/kotlin/App.kt index c5fd757e..203fd56f 100644 --- a/sample/mpp-library/src/commonMain/kotlin/App.kt +++ b/sample/mpp-library/src/commonMain/kotlin/App.kt @@ -57,8 +57,7 @@ import dev.icerock.moko.widgets.screen.navigation.createRouter import dev.icerock.moko.widgets.screen.navigation.route import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill -import dev.icerock.moko.widgets.style.background.StateBackground -import dev.icerock.moko.widgets.style.view.CornerRadiusValue +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle @@ -148,25 +147,25 @@ class App() : BaseApplication() { val loginTheme = Theme(AppTheme.loginScreen) { factory[LoginScreen.Id.EmailInputId] = FlatInputViewFactory( - textStyle = TextStyle( - size = 16, - color = Color(0x16171AFF) - ), +// textStyle = TextStyle( +// size = 16, +// color = Color(0x16171AFF) +// ), backgroundColor = Color(0xF5F5F5FF) ) factory[LoginScreen.Id.RegistrationButtonId] = ButtonWithIconViewFactory( - icon = MR.images.stars_black_18, + icon = PressableState(all = MR.images.stars_black_18), iconGravity = IconGravity.TEXT_END, iconPadding = 8.0f, padding = PaddingValues(padding = 16f), - background = StateBackground( + background = PressableState( normal = Background(fill = Fill.Solid(color = Color(0xAAFFFFFF))), pressed = Background(fill = Fill.Solid(color = Color(0x88FFFFFF))), disabled = Background(fill = Fill.Solid(color = Color(0x55FFFFFF))) ) ) factory[ImageWidget.DefaultCategory] = SystemImageViewFactory( - cornerRadiusValue = CornerRadiusValue(16.0f) + cornerRadius = 16.0f ) } diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt index 2991676a..3f11c9d5 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt @@ -24,8 +24,7 @@ import dev.icerock.moko.widgets.factory.SystemTextViewFactory import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Border import dev.icerock.moko.widgets.style.background.Fill -import dev.icerock.moko.widgets.style.background.Shape -import dev.icerock.moko.widgets.style.background.StateBackground +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.Colors import dev.icerock.moko.widgets.style.view.FontStyle import dev.icerock.moko.widgets.style.view.MarginValues @@ -63,7 +62,7 @@ object AppTheme { background = { val normalBackground = Background( fill = Fill.Solid(color = Color(0x1375F8FF)), - shape = Shape.Rectangle(cornerRadius = 22f) + cornerRadius = 22f ) val disabledBackground = normalBackground.copy( fill = Fill.Solid(color = Color(0x1375F880)) @@ -71,18 +70,19 @@ object AppTheme { val pressedBackground = normalBackground.copy( fill = Fill.Solid(color = Color(0x1375F8BB)) ) - StateBackground( + PressableState( normal = normalBackground, disabled = disabledBackground, pressed = pressedBackground ) - }() + }(), + textStyle = TextStyle(color = PressableState(all = Colors.white)) ) factory[CryptoProfileScreen.Id.TryDemoButton] = SystemButtonViewFactory( background = { val normalBackground = Background( fill = Fill.Solid(color = Color(0x303030FF)), - shape = Shape.Rectangle(cornerRadius = 22f), + cornerRadius = 22f, border = Border( color = Colors.white, width = 1f @@ -94,12 +94,19 @@ object AppTheme { val pressedBackground = normalBackground.copy( fill = Fill.Solid(color = Color(0x303030BB)) ) - StateBackground( + PressableState( normal = normalBackground, disabled = disabledBackground, pressed = pressedBackground ) - }() + }(), + textStyle = TextStyle( + color = PressableState( + normal = Colors.white, + pressed = Color(0xAA0000FF), + disabled = Colors.white + ) + ) ) factory[PostsCollection] = SystemCollectionViewFactory( @@ -141,36 +148,32 @@ object AppTheme { factory[ButtonWidget.DefaultCategory] = SystemButtonViewFactory( margins = MarginValues(top = 32f), background = { - val bg: (Color) -> Background = { + val bg: (Color) -> Background = { Background( fill = Fill.Solid(it), - shape = Shape.Rectangle( - cornerRadius = corners - ) + cornerRadius = corners ) } - StateBackground( + PressableState( normal = bg(Color(0x6770e0FF)), pressed = bg(Color(0x6770e0EE)), disabled = bg(Color(0x6770e0BB)) ) }.invoke(), textStyle = TextStyle( - color = Colors.white + color = PressableState(all = Colors.white) ) ) factory[LoginScreen.Id.RegistrationButtonId] = SystemButtonViewFactory( background = { - val bg: (Color) -> Background = { + val bg: (Color) -> Background = { Background( fill = Fill.Solid(it), - shape = Shape.Rectangle( - cornerRadius = corners - ) + cornerRadius = corners ) } - StateBackground( + PressableState( normal = bg(Color(0xFFFFFF00)), pressed = bg(Color(0xE7E7EEEE)), disabled = bg(Color(0x000000BB)) @@ -178,7 +181,7 @@ object AppTheme { }.invoke(), margins = MarginValues(top = 16f), textStyle = TextStyle( - color = Color(0x777889FF) + color = PressableState(all = Color(0x777889FF)) ), androidElevationEnabled = false ) diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt index 39fc0585..b2a1fa56 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt @@ -17,7 +17,6 @@ import dev.icerock.moko.widgets.container import dev.icerock.moko.widgets.core.Theme import dev.icerock.moko.widgets.core.Value import dev.icerock.moko.widgets.core.Widget -import dev.icerock.moko.widgets.flatAlert import dev.icerock.moko.widgets.linear import dev.icerock.moko.widgets.progressBar import dev.icerock.moko.widgets.stateful @@ -93,9 +92,9 @@ open class StateScreen( private fun Theme.flatAlertWrapped(message: LiveData) = container(size = WidgetSize.AsParent) { center { - flatAlert( + text( size = WidgetSize.WrapContent, - message = message + text = message.map { it ?: "".desc() } ) } } diff --git a/widgets-flat/src/androidMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt b/widgets-flat/src/androidMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt index 05039901..271cbf07 100644 --- a/widgets-flat/src/androidMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt +++ b/widgets-flat/src/androidMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt @@ -20,7 +20,7 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bind actual class FlatInputViewFactory actual constructor( - private val textStyle: TextStyle?, + private val textStyle: TextStyle?, private val backgroundColor: Color?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets-flat/src/commonMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt b/widgets-flat/src/commonMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt index b0bc52c4..58738a13 100644 --- a/widgets-flat/src/commonMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt +++ b/widgets-flat/src/commonMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt @@ -12,7 +12,7 @@ import dev.icerock.moko.widgets.style.view.TextStyle import dev.icerock.moko.widgets.style.view.WidgetSize expect class FlatInputViewFactory( - textStyle: TextStyle? = null, + textStyle: TextStyle? = null, backgroundColor: Color? = null, margins: MarginValues? = null ) : ViewFactory> diff --git a/widgets-flat/src/iosMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt b/widgets-flat/src/iosMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt index df15ef8e..9ecebd18 100644 --- a/widgets-flat/src/iosMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt +++ b/widgets-flat/src/iosMain/kotlin/dev/icerock/moko/widgets/flat/FlatInputViewFactory.kt @@ -27,7 +27,7 @@ import platform.UIKit.UIKeyboardTypePhonePad import platform.UIKit.backgroundColor actual class FlatInputViewFactory actual constructor( - private val textStyle: TextStyle?, + private val textStyle: TextStyle?, private val backgroundColor: Color?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt index f42e09c6..6db144c4 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt @@ -5,42 +5,41 @@ package dev.icerock.moko.widgets.factory import android.annotation.SuppressLint -import android.content.res.ColorStateList -import android.graphics.PorterDuff import android.os.Build import android.view.ContextThemeWrapper import android.view.Gravity -import android.view.View -import android.widget.Button -import android.widget.ImageButton -import android.widget.TextView -import androidx.core.content.ContextCompat import com.google.android.material.button.MaterialButton +import dev.icerock.moko.graphics.Color import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.widgets.ButtonWidget import dev.icerock.moko.widgets.R -import dev.icerock.moko.widgets.core.* +import dev.icerock.moko.widgets.core.ViewBundle +import dev.icerock.moko.widgets.core.ViewFactory +import dev.icerock.moko.widgets.core.ViewFactoryContext +import dev.icerock.moko.widgets.core.bind import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.applyStateBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded -import dev.icerock.moko.widgets.style.background.StateBackground -import dev.icerock.moko.widgets.style.background.buildBackground -import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.PressableState +import dev.icerock.moko.widgets.style.toStateList import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bind actual class ButtonWithIconViewFactory actual constructor( - private val background: StateBackground?, - private val textStyle: TextStyle?, + private val background: PressableState>?, + private val textStyle: TextStyle>?, private val isAllCaps: Boolean?, private val padding: PaddingValues?, private val margins: MarginValues?, private val androidElevationEnabled: Boolean?, private val iconGravity: IconGravity?, private val iconPadding: Float?, - private val icon: ImageResource + private val icon: PressableState ) : ViewFactory> { @SuppressLint("RestrictedApi") @@ -51,8 +50,8 @@ actual class ButtonWithIconViewFactory actual constructor( ): ViewBundle { val ctx = viewFactoryContext.androidContext val caps = isAllCaps - val icDrawable = ContextCompat.getDrawable(ctx, icon.drawableResId) - val icGravity = when(iconGravity) { + val icDrawable = icon.toStateList(context = ctx) + val icGravity = when (iconGravity) { IconGravity.START -> MaterialButton.ICON_GRAVITY_START IconGravity.END -> MaterialButton.ICON_GRAVITY_END IconGravity.TEXT_START, null -> MaterialButton.ICON_GRAVITY_TEXT_START @@ -73,10 +72,11 @@ actual class ButtonWithIconViewFactory actual constructor( iconGravity = icGravity iconPadding = icPadding.toInt() - when(this@ButtonWithIconViewFactory.iconGravity) { + when (this@ButtonWithIconViewFactory.iconGravity) { IconGravity.START -> gravity = Gravity.END IconGravity.END -> gravity = Gravity.START - else -> {} + else -> { + } } } } @@ -106,4 +106,4 @@ actual class ButtonWithIconViewFactory actual constructor( margins = margins ) } -} \ No newline at end of file +} diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt index 1ea95ca0..87b5e8bc 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt @@ -13,9 +13,9 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.applyMargin import dev.icerock.moko.widgets.style.ext.toPlatformSize -import dev.icerock.moko.widgets.style.view.CornerRadiusValue import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -23,8 +23,7 @@ import dev.icerock.moko.widgets.style.view.WidgetSize actual class CardViewFactory actual constructor( private val padding: PaddingValues?, private val margins: MarginValues?, - private val background: Background?, - private val cornerRadius: CornerRadiusValue? + private val background: Background? ) : ViewFactory> { override fun build( @@ -39,7 +38,7 @@ actual class CardViewFactory actual constructor( val root = CardView(context).apply { applyBackgroundIfNeeded(this@CardViewFactory.background) applyPaddingIfNeeded(padding) - radius = cornerRadius?.radius ?: 0f + radius = this@CardViewFactory.background?.cornerRadius ?: 0f } val childBundle = widget.child.buildView( diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt index 7b063db9..dcf5c206 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt @@ -12,11 +12,15 @@ import dev.icerock.moko.widgets.SwitchWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext +import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.androidId import dev.icerock.moko.widgets.utils.bindNotNull actual class CheckboxSwitchViewFactory actual constructor( + private val background: Background?, private val checkedImage: ImageResource, private val uncheckedImage: ImageResource ) : ViewFactory> { @@ -30,6 +34,8 @@ actual class CheckboxSwitchViewFactory actual constructor( val checkbox = CheckBox(context).apply { id = widget.id.androidId + + applyBackgroundIfNeeded(this@CheckboxSwitchViewFactory.background) } val drawable = StateListDrawable().apply { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt index 408ba12b..de94f358 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt @@ -19,6 +19,7 @@ import dev.icerock.moko.widgets.core.Widget import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.applyMargin import dev.icerock.moko.widgets.style.ext.toPlatformSize import dev.icerock.moko.widgets.style.view.MarginValues @@ -28,7 +29,7 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.dp actual class ConstraintViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val padding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt index 8d2f0abe..e498f67f 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt @@ -17,6 +17,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.applyMargin import dev.icerock.moko.widgets.style.ext.toPlatformSize import dev.icerock.moko.widgets.style.view.Alignment @@ -29,7 +30,7 @@ import dev.icerock.moko.widgets.view.AspectRatioFrameLayout actual class ContainerViewFactory actual constructor( private val padding: PaddingValues?, private val margins: MarginValues?, - private val background: Background? + private val background: Background? ) : ViewFactory> { override fun build( diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt deleted file mode 100644 index aa38d40a..00000000 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.factory - -import android.view.Gravity -import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import android.widget.LinearLayout -import android.widget.TextView -import androidx.appcompat.widget.AppCompatButton -import androidx.core.content.ContextCompat -import androidx.core.widget.TextViewCompat -import dev.icerock.moko.widgets.FlatAlertWidget -import dev.icerock.moko.widgets.core.ViewBundle -import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded -import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.MarginValues -import dev.icerock.moko.widgets.style.view.WidgetSize -import dev.icerock.moko.widgets.utils.bind -import dev.icerock.moko.widgets.utils.dp - -actual class FlatAlertViewFactory actual constructor( - private val background: Background?, - private val margins: MarginValues? -) : ViewFactory> { - - override fun build( - widget: FlatAlertWidget, - size: WS, - viewFactoryContext: ViewFactoryContext - ): ViewBundle { - val context = viewFactoryContext.context - val lifecycleOwner = viewFactoryContext.lifecycleOwner - - val rowsContainer = LinearLayout(context).apply { - orientation = LinearLayout.VERTICAL - } - rowsContainer.applyBackgroundIfNeeded(background) - - // drawable - val drawableLiveData = widget.drawable - if (drawableLiveData != null) { - val imageView = ImageView(context).apply { - layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - bottomMargin = 16.dp(context) - gravity = Gravity.CENTER_HORIZONTAL - } - } - - rowsContainer.addView(imageView) - - drawableLiveData.bind(lifecycleOwner) { resource -> - if (resource == null) { - imageView.setImageDrawable(null) - imageView.visibility = View.GONE - } else { - imageView.visibility = View.VISIBLE - val drawable = ContextCompat.getDrawable(context, resource.drawableResId) - imageView.setImageDrawable(drawable) - } - } - } - - // title - val titleLiveData = widget.title - if (titleLiveData != null) { - val textView = TextView(context).apply { - layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - bottomMargin = 8.dp(context) - gravity = Gravity.CENTER_HORIZONTAL - } - gravity = Gravity.CENTER - TextViewCompat.setTextAppearance( - this, - android.R.style.TextAppearance_Material_Headline - ) - } - - rowsContainer.addView(textView) - - titleLiveData.bind(lifecycleOwner) { title -> - if (title == null) { - textView.text = null - textView.visibility = View.GONE - } else { - textView.text = title.toString(context) - textView.visibility = View.VISIBLE - } - } - } - - // message - val textView = TextView(context).apply { - layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - bottomMargin = 8.dp(context) - gravity = Gravity.CENTER_HORIZONTAL - } - gravity = Gravity.CENTER - TextViewCompat.setTextAppearance(this, android.R.style.TextAppearance_Material_Subhead) - } - - rowsContainer.addView(textView) - - widget.message.bind(lifecycleOwner) { msg -> - if (msg == null) { - textView.text = null - textView.visibility = View.GONE - } else { - textView.text = msg.toString(context) - textView.visibility = View.VISIBLE - } - } - - // button - val buttonLiveData = widget.buttonText - val buttonTap = widget.onTap - if (buttonLiveData != null && buttonTap != null) { - val button = AppCompatButton(context).apply { - layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - gravity = Gravity.CENTER_HORIZONTAL - } - setOnClickListener { - buttonTap() - } - } - - rowsContainer.addView(button) - - buttonLiveData.bind(lifecycleOwner) { buttonText -> - if (buttonText == null) { - button.text = null - button.visibility = View.GONE - } else { - button.text = buttonText.toString(context) - button.visibility = View.VISIBLE - } - } - } - - return ViewBundle( - view = rowsContainer, - size = size, - margins = margins - ) - } -} diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt index 3f0c6e67..8cd04f03 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt @@ -26,6 +26,7 @@ import dev.icerock.moko.widgets.style.applyInputType import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.getGravity import dev.icerock.moko.widgets.style.view.FontStyle import dev.icerock.moko.widgets.style.view.MarginValues @@ -39,12 +40,12 @@ import dev.icerock.moko.widgets.utils.dp import dev.icerock.moko.widgets.utils.sp actual class FloatingLabelInputViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val margins: MarginValues?, private val padding: PaddingValues?, - private val textStyle: TextStyle?, - private val labelTextStyle: TextStyle?, - private val errorTextStyle: TextStyle?, + private val textStyle: TextStyle?, + private val labelTextStyle: TextStyle?, + private val errorTextStyle: TextStyle?, private val underLineColor: Color?, private val underLineFocusedColor: Color?, private val textHorizontalAlignment: TextHorizontalAlignment? diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt index a79a6652..e5ba1f11 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt @@ -15,6 +15,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.applyMargin import dev.icerock.moko.widgets.style.ext.toLinearLayoutOrientation import dev.icerock.moko.widgets.style.ext.toPlatformSize @@ -25,9 +26,9 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.view.AspectRatioFrameLayout actual class LinearViewFactory actual constructor( - private val background: Background?, private val padding: PaddingValues?, - private val margins: MarginValues? + private val margins: MarginValues?, + private val background: Background? ) : ViewFactory> { override fun build( widget: LinearWidget, diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt index ba455915..ab48c4b2 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt @@ -14,6 +14,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.applyMargin import dev.icerock.moko.widgets.style.ext.toPlatformSize import dev.icerock.moko.widgets.style.view.MarginValues @@ -22,9 +23,9 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bindNotNull actual class StatefulViewFactory actual constructor( - private val background: Background?, private val margins: MarginValues?, - private val padding: PaddingValues? + private val padding: PaddingValues?, + private val background: Background? ) : ViewFactory> { override fun build( diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt index 3f166cd9..2388321c 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt @@ -8,6 +8,7 @@ import android.os.Build import android.view.View import android.widget.Button import android.widget.ImageButton +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.ButtonWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory @@ -16,7 +17,9 @@ import dev.icerock.moko.widgets.core.bind import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.applyStateBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded -import dev.icerock.moko.widgets.style.background.StateBackground +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle @@ -24,8 +27,8 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bind actual class SystemButtonViewFactory actual constructor( - private val background: StateBackground?, - private val textStyle: TextStyle?, + private val background: PressableState>?, + private val textStyle: TextStyle>?, private val isAllCaps: Boolean?, private val padding: PaddingValues?, private val margins: MarginValues?, diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt index 6bf1f649..8b7718b7 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt @@ -16,6 +16,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.background.Orientation import dev.icerock.moko.widgets.style.ext.toStaggeredGridLayoutManager import dev.icerock.moko.widgets.style.view.MarginValues @@ -28,9 +29,9 @@ import dev.icerock.moko.widgets.view.UnitItemDecorator actual class SystemCollectionViewFactory actual constructor( private val orientation: Orientation, private val spanCount: Int, - private val background: Background?, private val padding: PaddingValues?, - private val margins: MarginValues? + private val margins: MarginValues?, + private val background: Background? ) : ViewFactory> { override fun build( diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt index f4da6468..f7a55bb4 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt @@ -10,7 +10,6 @@ import dev.icerock.moko.widgets.ImageWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.style.view.CornerRadiusValue import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bind @@ -19,7 +18,7 @@ import dev.icerock.moko.widgets.utils.dp actual class SystemImageViewFactory actual constructor( private val margins: MarginValues?, - private val cornerRadiusValue: CornerRadiusValue? + private val cornerRadius: Float? ) : ViewFactory> { override fun build( @@ -45,8 +44,8 @@ actual class SystemImageViewFactory actual constructor( image.loadIn(imageView) - if (cornerRadiusValue != null) { - imageView.cornerRadius = cornerRadiusValue.radius.dp(context) + cornerRadius?.also { + imageView.cornerRadius = cornerRadius.dp(context) } } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt index 04fbf282..bd2ad05c 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt @@ -22,17 +22,24 @@ import dev.icerock.moko.widgets.style.applyInputType import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.getGravityForTextAlignment -import dev.icerock.moko.widgets.style.view.* +import dev.icerock.moko.widgets.style.view.IOSFieldBorderStyle +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.TextVerticalAlignment +import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.androidId import dev.icerock.moko.widgets.utils.bind import dev.icerock.moko.widgets.utils.dp actual class SystemInputViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val margins: MarginValues?, private val padding: PaddingValues?, - private val textStyle: TextStyle?, + private val textStyle: TextStyle?, private val labelTextColor: Color?, private val textHorizontalAlignment: TextHorizontalAlignment?, private val textVerticalAlignment: TextVerticalAlignment?, @@ -70,7 +77,7 @@ actual class SystemInputViewFactory actual constructor( // If there is any nonnull text alignment argument, then set it to gravity // otherwise gravity will be with default value. - if(textHorizontalAlignment != null || textVerticalAlignment != null) { + if (textHorizontalAlignment != null || textVerticalAlignment != null) { gravity = getGravityForTextAlignment( textHorizontalAlignment = textHorizontalAlignment, textVerticalAlignment = textVerticalAlignment @@ -88,7 +95,8 @@ actual class SystemInputViewFactory actual constructor( start: Int, count: Int, after: Int - ) {} + ) { + } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { if (s == null) return diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt index c3c0978a..09994906 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt @@ -18,6 +18,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -25,7 +26,7 @@ import dev.icerock.moko.widgets.utils.androidId import dev.icerock.moko.widgets.utils.bind actual class SystemListViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val dividerEnabled: Boolean?, private val reversed: Boolean, private val padding: PaddingValues?, diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt index 7b39fb37..0d61ca7b 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt @@ -13,6 +13,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.applyMargin import dev.icerock.moko.widgets.style.ext.toPlatformSize import dev.icerock.moko.widgets.style.view.MarginValues @@ -21,7 +22,7 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.androidId actual class SystemScrollViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val padding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt index e96b5df7..372160af 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt @@ -26,6 +26,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.background.buildBackground import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues @@ -36,11 +37,11 @@ import dev.icerock.moko.widgets.utils.bind import dev.icerock.moko.widgets.utils.dp actual class SystemSingleChoiceViewFactory actual constructor( - private val textStyle: TextStyle?, - private val labelTextStyle: TextStyle?, + private val textStyle: TextStyle?, + private val labelTextStyle: TextStyle?, private val dropDownTextColor: Color?, private val underlineColor: Color?, - private val dropDownBackground: Background?, + private val dropDownBackground: Background?, private val padding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt index b74ca8c3..d63db7dc 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt @@ -4,15 +4,15 @@ package dev.icerock.moko.widgets.factory -import android.content.res.ColorStateList import android.widget.Switch import androidx.core.graphics.drawable.DrawableCompat +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.SwitchWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.style.ColorStyle import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.background.buildBackground import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -20,8 +20,8 @@ import dev.icerock.moko.widgets.utils.androidId import dev.icerock.moko.widgets.utils.bindNotNull actual class SystemSwitchViewFactory actual constructor( - private val background: Background?, - private val switchColor: ColorStyle?, + private val background: Background?, + private val tintColor: Color?, private val margins: MarginValues? ) : ViewFactory> { @@ -35,29 +35,9 @@ actual class SystemSwitchViewFactory actual constructor( val switch = Switch(context).apply { id = widget.id.androidId - switchColor?.also { colorStyle -> - val thumbStates = ColorStateList( - arrayOf( - intArrayOf(-android.R.attr.state_checked), - intArrayOf(android.R.attr.state_checked) - ), - colorStyle.colors.let { - intArrayOf(it[0], it[1]) - } - ) - - val trackStates = ColorStateList( - arrayOf( - intArrayOf(-android.R.attr.state_checked), - intArrayOf(android.R.attr.state_checked) - ), - colorStyle.colors.let { - intArrayOf(it[2], it[3]) - } - ) - - DrawableCompat.setTintList(thumbDrawable, thumbStates) - DrawableCompat.setTintList(trackDrawable, trackStates) + tintColor?.also { color -> + DrawableCompat.setTint(thumbDrawable, color.argb.toInt()) + DrawableCompat.setTint(trackDrawable, color.argb.toInt()) } this@SystemSwitchViewFactory.background?.also { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index aa962644..dd315d30 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -24,6 +24,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -33,8 +34,8 @@ actual class SystemTabsViewFactory actual constructor( private val tabsTintColor: Color?, private val selectedTitleColor: Color?, private val normalTitleColor: Color?, - private val tabsBackground: Background?, - private val contentBackground: Background?, + private val tabsBackground: Background?, + private val contentBackground: Background?, private val tabsPadding: PaddingValues?, private val contentPadding: PaddingValues?, private val margins: MarginValues? diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt index ef494506..25b81ab4 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt @@ -9,6 +9,7 @@ import android.text.Html import android.text.method.LinkMovementMethod import android.view.Gravity import android.widget.TextView +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.TextWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory @@ -16,6 +17,7 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment import dev.icerock.moko.widgets.style.view.TextStyle @@ -23,8 +25,8 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bind actual class SystemTextViewFactory actual constructor( - private val background: Background?, - private val textStyle: TextStyle?, + private val background: Background?, + private val textStyle: TextStyle?, private val textHorizontalAlignment: TextHorizontalAlignment?, private val margins: MarginValues?, private val isHtmlConverted: Boolean diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt index cde5aff1..c596856a 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt @@ -18,13 +18,14 @@ import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.WebViewRedirectUrlHandler actual class WebViewFactory actual constructor( private val margins: MarginValues?, - private val background: Background? + private val background: Background? ) : ViewFactory> { override fun build( @@ -88,7 +89,5 @@ actual class WebViewFactory actual constructor( val requestedUrl = Uri.parse(request.url.toString()).toString() return redirectUrlHandler.handleUrl(requestedUrl) } - } - } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListColorExt.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListColorExt.kt new file mode 100644 index 00000000..0c36adf2 --- /dev/null +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListColorExt.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style + +import android.content.res.ColorStateList +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.widgets.style.state.PressableState + +fun PressableState.toStateList() = ColorStateList( + arrayOf( + intArrayOf(-android.R.attr.state_enabled), + intArrayOf(android.R.attr.state_pressed), + intArrayOf() + ), + intArrayOf( + disabled.argb.toInt(), + pressed.argb.toInt(), + normal.argb.toInt() + ) +) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListDrawableExt.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListDrawableExt.kt new file mode 100644 index 00000000..4523d599 --- /dev/null +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/StateListDrawableExt.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style + +import android.content.Context +import android.graphics.drawable.StateListDrawable +import androidx.core.content.ContextCompat +import dev.icerock.moko.resources.ImageResource +import dev.icerock.moko.widgets.style.state.PressableState + +fun PressableState.toStateList(context: Context) = StateListDrawable().also { selector -> + selector.addState( + intArrayOf(-android.R.attr.state_enabled), + ContextCompat.getDrawable(context, disabled.drawableResId) + ) + selector.addState( + intArrayOf(android.R.attr.state_pressed), + ContextCompat.getDrawable(context, pressed.drawableResId) + ) + selector.addState( + intArrayOf(), + ContextCompat.getDrawable(context, normal.drawableResId) + ) +} diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/TextViewExt.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/TextViewExt.kt index bf546e3d..13f4e873 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/TextViewExt.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/TextViewExt.kt @@ -4,31 +4,31 @@ package dev.icerock.moko.widgets.style +import android.widget.Button import android.widget.TextView +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.TextStyle -fun TextView.applyTextStyle(textStyle: TextStyle) { - textStyle.color?.also { - setTextColor(it.argb.toInt()) - } - textStyle.size?.also { - textSize = it.toFloat() - } - textStyle.fontStyle?.also { - applyFontStyle(it) - } +fun Button.applyTextStyleIfNeeded(textStyle: TextStyle>?) { + applyCommonTextStyleIfNeeded(textStyle) + + if (textStyle == null) return + + textStyle.color?.also { setTextColor(it.toStateList()) } } -fun TextView.applyTextStyleIfNeeded(textStyle: TextStyle?) { - if(textStyle == null) return - - textStyle.color?.also { - setTextColor(it.argb.toInt()) - } - textStyle.size?.also { - textSize = it.toFloat() - } - textStyle.fontStyle?.also { - applyFontStyle(it) - } +fun TextView.applyTextStyleIfNeeded(textStyle: TextStyle?) { + applyCommonTextStyleIfNeeded(textStyle) + + if (textStyle == null) return + + textStyle.color?.also { setTextColor(it.argb.toInt()) } +} + +fun TextView.applyCommonTextStyleIfNeeded(textStyle: TextStyle<*>?) { + if (textStyle == null) return + + textStyle.size?.also { textSize = it.toFloat() } + textStyle.fontStyle?.also { applyFontStyle(it) } } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/ViewExt.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/ViewExt.kt index 5c5c2697..67dc572e 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/ViewExt.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/ViewExt.kt @@ -7,58 +7,34 @@ package dev.icerock.moko.widgets.style import android.view.View import android.view.ViewGroup import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.background.StateBackground +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.background.buildBackground -import dev.icerock.moko.widgets.style.ext.applyMargin import dev.icerock.moko.widgets.style.ext.applyPadding import dev.icerock.moko.widgets.style.ext.toPlatformSize -import dev.icerock.moko.widgets.style.view.Backgrounded -import dev.icerock.moko.widgets.style.view.Margined -import dev.icerock.moko.widgets.style.view.Padded +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.SizeSpec -import dev.icerock.moko.widgets.style.view.StateBackgrounded import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.view.AspectRatioFrameLayout -fun View.applyBackgroundIfNeeded(background: Background?) { - if(background == null) return +fun View.applyBackgroundIfNeeded(background: Background?) { + if (background == null) return this.background = background.buildBackground(context) } -fun View.applyStateBackgroundIfNeeded(stateBackground: StateBackground?) { - if(stateBackground == null) return +fun View.applyStateBackgroundIfNeeded(stateBackground: PressableState>?) { + if (stateBackground == null) return this.background = stateBackground.buildBackground(context) } fun View.applyPaddingIfNeeded(padding: PaddingValues?) { - if(padding == null) return + if (padding == null) return applyPadding(padding) } -fun View.applyStyle(style: Any) { - if (style is Margined) { - style.margins?.also { - (layoutParams as? ViewGroup.MarginLayoutParams)?.applyMargin(context, it) - } - } - - if (style is Padded) { - style.padding?.also { applyPadding(it) } - } - - if (style is Backgrounded) { - style.background?.also { background = it.buildBackground(context) } - } - - if (style is StateBackgrounded) { - style.background?.also { background = it.buildBackground(context) } - } -} - fun View.withSize(size: WidgetSize): View { val dm = context.resources.displayMetrics diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/background/BackgroundExt.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/background/BackgroundExt.kt index 662363e5..96694c8e 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/background/BackgroundExt.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/background/BackgroundExt.kt @@ -13,9 +13,10 @@ import android.graphics.drawable.RippleDrawable import android.graphics.drawable.StateListDrawable import android.os.Build import dev.icerock.moko.widgets.style.ext.toPlatformOrientation +import dev.icerock.moko.widgets.style.state.PressableState import kotlin.math.ceil -fun StateBackground.buildBackground(context: Context) = StateListDrawable().also { selector -> +fun PressableState>.buildBackground(context: Context) = StateListDrawable().also { selector -> selector.addState( intArrayOf(-android.R.attr.state_enabled), disabled.buildBackground(context) @@ -41,7 +42,7 @@ fun StateBackground.buildBackground(context: Context) = StateListDrawable().also ) } -fun Background.buildBackground(context: Context): Drawable { +fun Background.buildBackground(context: Context): Drawable { val gradientDrawable = GradientDrawable() val scale = context.resources.displayMetrics.density @@ -53,16 +54,8 @@ fun Background.buildBackground(context: Context): Drawable { } } - when (shape) { - is Shape.Rectangle -> { - gradientDrawable.shape = GradientDrawable.RECTANGLE - if (shape.cornerRadius != null) { - gradientDrawable.cornerRadius = shape.cornerRadius * scale - } - } - is Shape.Oval -> { - gradientDrawable.shape = GradientDrawable.OVAL - } + if (cornerRadius != null) { + gradientDrawable.cornerRadius = cornerRadius * scale } if (border != null) { diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt deleted file mode 100644 index c5c547c2..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets - -import dev.icerock.moko.mvvm.livedata.LiveData -import dev.icerock.moko.resources.ImageResource -import dev.icerock.moko.resources.desc.StringDesc -import dev.icerock.moko.widgets.core.OptionalId -import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.core.ViewBundle -import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.core.Widget -import dev.icerock.moko.widgets.core.WidgetDef -import dev.icerock.moko.widgets.factory.FlatAlertViewFactory -import dev.icerock.moko.widgets.style.view.WidgetSize - -// TODO replace to combination of linear, text, button? -@WidgetDef(FlatAlertViewFactory::class) -class FlatAlertWidget( - private val factory: ViewFactory>, - override val size: WS, - override val id: Id?, - val title: LiveData?, - val message: LiveData, - val drawable: LiveData?, - val buttonText: LiveData?, - val onTap: (() -> Unit)? -) : Widget(), OptionalId { - - override fun buildView(viewFactoryContext: ViewFactoryContext): ViewBundle { - return factory.build(this, size, viewFactoryContext) - } - - interface Id : Theme.Id> - interface Category : Theme.Category> - - object DefaultCategory : Category -} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt index 8d0d5fc9..74402cac 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt @@ -4,27 +4,28 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.widgets.ButtonWidget -import dev.icerock.moko.widgets.core.Image -import dev.icerock.moko.widgets.core.Value import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.style.background.StateBackground -import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.WidgetSize expect class ButtonWithIconViewFactory( - background: StateBackground? = null, - textStyle: TextStyle? = null, + background: PressableState>? = null, + textStyle: TextStyle>? = null, isAllCaps: Boolean? = null, padding: PaddingValues? = null, margins: MarginValues? = null, androidElevationEnabled: Boolean? = null, iconGravity: IconGravity? = null, iconPadding: Float? = null, - icon: ImageResource + icon: PressableState ) : ViewFactory> enum class IconGravity { diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt index bc75c390..42182a7a 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt @@ -7,7 +7,7 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.CardWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.CornerRadiusValue +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -15,6 +15,5 @@ import dev.icerock.moko.widgets.style.view.WidgetSize expect class CardViewFactory( padding: PaddingValues? = null, margins: MarginValues? = null, - background: Background? = null, - cornerRadius: CornerRadiusValue? = null + background: Background? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt index c1554b1e..d6e72070 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt @@ -7,9 +7,12 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.widgets.SwitchWidget import dev.icerock.moko.widgets.core.ViewFactory +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.WidgetSize expect class CheckboxSwitchViewFactory( + background: Background? = null, checkedImage: ImageResource, uncheckedImage: ImageResource ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt index 83c72984..fa662f2b 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt @@ -7,12 +7,13 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.ConstraintWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class ConstraintViewFactory( - background: Background? = null, + background: Background? = null, padding: PaddingValues? = null, margins: MarginValues? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt index 4ae59009..2962e8d2 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt @@ -7,6 +7,7 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.ContainerWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -14,5 +15,5 @@ import dev.icerock.moko.widgets.style.view.WidgetSize expect class ContainerViewFactory( padding: PaddingValues? = null, margins: MarginValues? = null, - background: Background? = null + background: Background? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt deleted file mode 100644 index 85a9d965..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.factory - -import dev.icerock.moko.widgets.FlatAlertWidget -import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.MarginValues -import dev.icerock.moko.widgets.style.view.WidgetSize - -expect class FlatAlertViewFactory( - background: Background? = null, - margins: MarginValues? = null -) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt index 414fd356..b7f52efb 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt @@ -8,15 +8,20 @@ import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.InputWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.* +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.WidgetSize expect class FloatingLabelInputViewFactory( - background: Background? = null, + background: Background? = null, margins: MarginValues? = null, padding: PaddingValues? = null, - textStyle: TextStyle? = null, - labelTextStyle: TextStyle? = null, - errorTextStyle: TextStyle? = null, + textStyle: TextStyle? = null, + labelTextStyle: TextStyle? = null, + errorTextStyle: TextStyle? = null, underLineColor: Color? = null, underLineFocusedColor: Color? = null, textHorizontalAlignment: TextHorizontalAlignment? = null diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt index bc1b99c4..37b847a1 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt @@ -7,16 +7,13 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.LinearWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.background.Orientation -import dev.icerock.moko.widgets.style.view.Backgrounded +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues -import dev.icerock.moko.widgets.style.view.Margined -import dev.icerock.moko.widgets.style.view.Padded import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class LinearViewFactory( - background: Background? = null, padding: PaddingValues? = null, - margins: MarginValues? = null + margins: MarginValues? = null, + background: Background? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt index 02620d21..707d2c19 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt @@ -7,12 +7,13 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.StatefulWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class StatefulViewFactory( - background: Background? = null, margins: MarginValues? = null, - padding: PaddingValues? = null + padding: PaddingValues? = null, + background: Background? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt index 19444c3b..d998bd64 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt @@ -4,17 +4,20 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.ButtonWidget import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.style.background.StateBackground +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemButtonViewFactory( - background: StateBackground? = null, - textStyle: TextStyle? = null, + background: PressableState>? = null, + textStyle: TextStyle>? = null, isAllCaps: Boolean? = null, padding: PaddingValues? = null, margins: MarginValues? = null, diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt index 0df9fccc..1f7595ab 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt @@ -7,6 +7,7 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.CollectionWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.background.Orientation import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues @@ -15,7 +16,7 @@ import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemCollectionViewFactory( orientation: Orientation = Orientation.VERTICAL, spanCount: Int = 2, - background: Background? = null, padding: PaddingValues? = null, - margins: MarginValues? = null + margins: MarginValues? = null, + background: Background? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt index fb0c4a98..bf885534 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt @@ -6,11 +6,10 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.ImageWidget import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.style.view.CornerRadiusValue import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemImageViewFactory( margins: MarginValues? = null, - cornerRadiusValue: CornerRadiusValue? = null + cornerRadius: Float? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt index a1753460..8214f5c8 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt @@ -8,13 +8,20 @@ import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.InputWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.* +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.view.IOSFieldBorderStyle +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.TextVerticalAlignment +import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemInputViewFactory( - background: Background? = null, + background: Background? = null, margins: MarginValues? = null, padding: PaddingValues? = null, - textStyle: TextStyle? = null, + textStyle: TextStyle? = null, labelTextColor: Color? = null, textHorizontalAlignment: TextHorizontalAlignment? = null, textVerticalAlignment: TextVerticalAlignment? = null, diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt index c664d728..cef439b1 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt @@ -7,12 +7,13 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.ListWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemListViewFactory( - background: Background? = null, + background: Background? = null, dividerEnabled: Boolean? = null, reversed: Boolean = false, padding: PaddingValues? = null, diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt index e5f82d5c..643aee2a 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt @@ -7,12 +7,13 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.ScrollWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemScrollViewFactory( - background: Background? = null, + background: Background? = null, padding: PaddingValues? = null, margins: MarginValues? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt index 71aada7a..43659b7e 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt @@ -8,17 +8,18 @@ import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.SingleChoiceWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemSingleChoiceViewFactory( - textStyle: TextStyle? = null, - labelTextStyle: TextStyle? = null, + textStyle: TextStyle? = null, + labelTextStyle: TextStyle? = null, dropDownTextColor: Color? = null, underlineColor: Color? = null, - dropDownBackground: Background? = null, + dropDownBackground: Background? = null, padding: PaddingValues? = null, margins: MarginValues? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt index 0fc76f44..3202f773 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt @@ -4,15 +4,16 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.SwitchWidget import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.style.ColorStyle import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemSwitchViewFactory( - background: Background? = null, - switchColor: ColorStyle? = null, + background: Background? = null, + tintColor: Color? = null, margins: MarginValues? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index ad196bde..0a7cadaf 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -8,6 +8,8 @@ import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.TabsWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Border +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -16,8 +18,8 @@ expect class SystemTabsViewFactory( tabsTintColor: Color? = null, selectedTitleColor: Color? = null, normalTitleColor: Color? = null, - tabsBackground: Background? = null, - contentBackground: Background? = null, + tabsBackground: Background? = null, + contentBackground: Background? = null, tabsPadding: PaddingValues? = null, contentPadding: PaddingValues? = null, margins: MarginValues? = null diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt index 7222db81..92a6bf19 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt @@ -4,17 +4,19 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.TextWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment import dev.icerock.moko.widgets.style.view.TextStyle import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemTextViewFactory( - background: Background? = null, - textStyle: TextStyle? = null, + background: Background? = null, + textStyle: TextStyle? = null, textHorizontalAlignment: TextHorizontalAlignment? = null, margins: MarginValues? = null, isHtmlConverted: Boolean = false diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/VisibilityViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/VisibilityViewFactory.kt index a4d75262..a7ef485c 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/VisibilityViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/VisibilityViewFactory.kt @@ -4,7 +4,6 @@ package dev.icerock.moko.widgets.factory -import dev.icerock.moko.widgets.ClickableWidget import dev.icerock.moko.widgets.VisibilityWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.view.WidgetSize diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt index 6474ea08..492b00f6 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt @@ -7,10 +7,11 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.widgets.WebViewWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class WebViewFactory( margins: MarginValues? = null, - background: Background? = null + background: Background? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index b1a9955a..15b99162 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -10,7 +10,6 @@ import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.widgets.screen.Args import dev.icerock.moko.widgets.screen.Screen -import dev.icerock.moko.widgets.screen.ScreenFactory import dev.icerock.moko.widgets.screen.TypedScreenDesc import dev.icerock.moko.widgets.style.view.TextStyle @@ -111,7 +110,7 @@ sealed class NavigationBar { data class Styles( val backgroundColor: Color? = null, - val textStyle: TextStyle? = null, + val textStyle: TextStyle? = null, val tintColor: Color? = null ) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/ColorStyle.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/ColorStyle.kt deleted file mode 100644 index 027aaca8..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/ColorStyle.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.style - -import dev.icerock.moko.widgets.style.background.Direction - -class ColorStyle( - val colors: List, - val colorsDisabled: List = colors, - val direction: Direction = Direction.LEFT_RIGHT -) { - constructor( - color: Int, - colorDisabled: Int = color, - direction: Direction = Direction.LEFT_RIGHT - ) : this(listOf(color), listOf(colorDisabled), direction) -} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Background.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Background.kt index 735d255b..397824e0 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Background.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Background.kt @@ -4,8 +4,8 @@ package dev.icerock.moko.widgets.style.background -data class Background( - val fill: Fill? = null, +data class Background( + val fill: F? = null, val border: Border? = null, - val shape: Shape? = null + val cornerRadius: Float? = null ) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Shape.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Shape.kt deleted file mode 100644 index bd606fa2..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/Shape.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.style.background - -sealed class Shape { - data class Rectangle(val cornerRadius: Float? = null) : Shape() - object Oval : Shape() -} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/StateBackground.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/StateBackground.kt deleted file mode 100644 index fb08e0a2..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/background/StateBackground.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.style.background - -data class StateBackground( - val normal: Background, - val disabled: Background, - val pressed: Background -) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/input/InputType.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/input/InputType.kt index 5d83b6e1..f778a552 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/input/InputType.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/input/InputType.kt @@ -4,11 +4,11 @@ package dev.icerock.moko.widgets.style.input -sealed class InputType(open val mask: String?) { - class Email(override val mask: String? = null) : InputType(mask = mask) - class Phone(override val mask: String? = "+7 ([000]) [000] [00] [00]") : InputType(mask = mask) - class Plain(override val mask: String? = null) : InputType(mask = null) +sealed class InputType(val mask: String?) { + class Email(mask: String? = null) : InputType(mask = mask) + class Phone(mask: String? = "+7 ([000]) [000] [00] [00]") : InputType(mask = mask) + class Plain(mask: String? = null) : InputType(mask = mask) class Password : InputType(mask = null) - class Date(override val mask: String? = "[00]{.}[00]{.}[0000]") : InputType(mask = mask) - class Digits(override val mask: String? = null) : InputType(mask = mask) -} \ No newline at end of file + class Date(mask: String? = "[00]{.}[00]{.}[0000]") : InputType(mask = mask) + class Digits(mask: String? = null) : InputType(mask = mask) +} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/FocusableState.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/FocusableState.kt new file mode 100644 index 00000000..1b3275fb --- /dev/null +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/FocusableState.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style.state + +data class FocusableState( + val focused: T, + val unfocused: T +) { + constructor(all: T) : this(unfocused = all, focused = all) +} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/PressableState.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/PressableState.kt new file mode 100644 index 00000000..d366a9c8 --- /dev/null +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/PressableState.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style.state + +data class PressableState( + val normal: T, + val disabled: T, + val pressed: T +) { + constructor(all: T) : this(normal = all, disabled = all, pressed = all) +} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/SelectableState.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/SelectableState.kt new file mode 100644 index 00000000..fed14168 --- /dev/null +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/SelectableState.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style.state + +data class SelectableState( + val selected: T, + val unselected: T +) { + constructor(all: T) : this(selected = all, unselected = all) +} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Backgrounded.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Backgrounded.kt deleted file mode 100644 index 0b27d103..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Backgrounded.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.style.view - -import dev.icerock.moko.widgets.style.background.Background - -interface Backgrounded { - val background: Background? -} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/StateBackgrounded.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/StateBackgrounded.kt deleted file mode 100644 index 2cc09707..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/StateBackgrounded.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.style.view - -import dev.icerock.moko.widgets.style.background.StateBackground - -interface StateBackgrounded { - val background: StateBackground? -} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/TextStyle.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/TextStyle.kt index 04141ae8..e6e017f2 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/TextStyle.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/TextStyle.kt @@ -4,10 +4,8 @@ package dev.icerock.moko.widgets.style.view -import dev.icerock.moko.graphics.Color - -data class TextStyle( +data class TextStyle( val size: Int? = null, - val color: Color? = null, + val color: C? = null, val fontStyle: FontStyle? = null ) diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt index b2944462..db16ef79 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ButtonWithIconViewFactory.kt @@ -4,14 +4,16 @@ package dev.icerock.moko.widgets.factory -import dev.icerock.moko.graphics.toUIColor +import dev.icerock.moko.graphics.Color import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.widgets.ButtonWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.core.bind -import dev.icerock.moko.widgets.style.background.StateBackground +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle @@ -29,6 +31,8 @@ import platform.UIKit.UIControlContentHorizontalAlignment import platform.UIKit.UIControlContentHorizontalAlignmentCenter import platform.UIKit.UIControlContentHorizontalAlignmentLeft import platform.UIKit.UIControlEventTouchUpInside +import platform.UIKit.UIControlStateDisabled +import platform.UIKit.UIControlStateHighlighted import platform.UIKit.UIControlStateNormal import platform.UIKit.UIEdgeInsetsMake import platform.UIKit.UISemanticContentAttribute @@ -38,15 +42,15 @@ import platform.UIKit.bringSubviewToFront import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class ButtonWithIconViewFactory actual constructor( - private val background: StateBackground?, - private val textStyle: TextStyle?, + private val background: PressableState>?, + private val textStyle: TextStyle>?, private val isAllCaps: Boolean?, private val padding: PaddingValues?, private val margins: MarginValues?, androidElevationEnabled: Boolean?, private val iconGravity: IconGravity?, private val iconPadding: Float?, - private val icon: ImageResource + private val icon: PressableState ) : ViewFactory> { override fun build( @@ -60,10 +64,13 @@ actual class ButtonWithIconViewFactory actual constructor( translatesAutoresizingMaskIntoConstraints = false applyStateBackgroundIfNeeded(background) + applyTextStyleIfNeeded(textStyle) - titleLabel?.applyTextStyleIfNeeded(textStyle) - - textStyle?.color?.also { setTintColor(it.toUIColor()) } + icon.also { + setImage(it.normal.toUIImage(), forState = UIControlStateNormal) + setImage(it.pressed.toUIImage(), forState = UIControlStateHighlighted) + setImage(it.disabled.toUIImage(), forState = UIControlStateDisabled) + } } when (widget.content) { @@ -81,10 +88,6 @@ actual class ButtonWithIconViewFactory actual constructor( else -> throw Exception("Not supported content type") } - icon.toUIImage()?.also { - button.setImage(it, forState = UIControlStateNormal) - } - widget.enabled?.apply { bind { button.setEnabled(it) } } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt index d84eceee..1ee4c916 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CardViewFactory.kt @@ -9,18 +9,33 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.* -import dev.icerock.moko.widgets.utils.* +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.utils.Edges +import dev.icerock.moko.widgets.utils.UIViewWithIdentifier +import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded +import dev.icerock.moko.widgets.utils.applySizeToChild import dev.icerock.moko.widgets.utils.identifier -import kotlinx.cinterop.readValue -import platform.CoreGraphics.* -import platform.UIKit.* +import platform.CoreGraphics.CGFloat +import platform.CoreGraphics.CGSizeMake +import platform.UIKit.UIColor +import platform.UIKit.UIView +import platform.UIKit.UIViewController +import platform.UIKit.addSubview +import platform.UIKit.backgroundColor +import platform.UIKit.bottomAnchor +import platform.UIKit.clipsToBounds +import platform.UIKit.leadingAnchor +import platform.UIKit.topAnchor +import platform.UIKit.trailingAnchor +import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class CardViewFactory actual constructor( private val padding: PaddingValues?, private val margins: MarginValues?, - private val background: Background?, - private val cornerRadius: CornerRadiusValue? + private val background: Background? ) : ViewFactory> { override fun build( @@ -35,7 +50,7 @@ actual class CardViewFactory actual constructor( translatesAutoresizingMaskIntoConstraints = false applyBackgroundIfNeeded(background) - layer.cornerRadius = cornerRadius?.radius?.toDouble() ?: 0.0 + layer.cornerRadius = background?.cornerRadius?.toDouble() ?: 0.0 clipsToBounds = true backgroundColor = UIColor.whiteColor @@ -80,7 +95,7 @@ actual class CardViewFactory actual constructor( val shadowContainerView = UIView(frame = root.frame).apply { translatesAutoresizingMaskIntoConstraints = false - layer.cornerRadius = cornerRadius?.radius?.toDouble() ?: 0.0 + layer.cornerRadius = background?.cornerRadius?.toDouble() ?: 0.0 layer.shadowColor = UIColor.grayColor.CGColor layer.shadowOpacity = 0.7f diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt index 7cc5da5d..a9575fdc 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt @@ -9,7 +9,10 @@ import dev.icerock.moko.widgets.SwitchWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded import dev.icerock.moko.widgets.utils.bind import dev.icerock.moko.widgets.utils.setEventHandler import platform.UIKit.UIButton @@ -18,6 +21,7 @@ import platform.UIKit.UIControlStateNormal import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class CheckboxSwitchViewFactory actual constructor( + private val background: Background?, private val checkedImage: ImageResource, private val uncheckedImage: ImageResource ) : ViewFactory> { @@ -26,8 +30,11 @@ actual class CheckboxSwitchViewFactory actual constructor( size: WS, viewFactoryContext: ViewFactoryContext ): ViewBundle { - val btn = UIButton() - btn.translatesAutoresizingMaskIntoConstraints = false + val btn = UIButton().apply { + translatesAutoresizingMaskIntoConstraints = false + + applyBackgroundIfNeeded(background) + } widget.state.bind { state -> val imgRes = if (state) checkedImage else uncheckedImage diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt index 361d4ac3..afbad71a 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ConstraintViewFactory.kt @@ -13,6 +13,7 @@ import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.core.Widget import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -37,7 +38,7 @@ import platform.UIKit.topAnchor import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class ConstraintViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val padding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt index caf8f6aa..cdfec312 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/ContainerViewFactory.kt @@ -9,6 +9,7 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.Alignment import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues @@ -16,8 +17,8 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.Edges import dev.icerock.moko.widgets.utils.UIViewWithIdentifier import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded -import dev.icerock.moko.widgets.utils.identifier import dev.icerock.moko.widgets.utils.applySizeToChild +import dev.icerock.moko.widgets.utils.identifier import platform.CoreGraphics.CGFloat import platform.UIKit.UIViewController import platform.UIKit.addSubview @@ -32,7 +33,7 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class ContainerViewFactory actual constructor( private val padding: PaddingValues?, private val margins: MarginValues?, - private val background: Background? + private val background: Background? ) : ViewFactory> { override fun build( diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt deleted file mode 100644 index 2d1fe57e..00000000 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FlatAlertViewFactory.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.factory - -import dev.icerock.moko.widgets.FlatAlertWidget -import dev.icerock.moko.widgets.core.ViewBundle -import dev.icerock.moko.widgets.core.ViewFactory -import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.MarginValues -import dev.icerock.moko.widgets.style.view.WidgetSize -import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded -import dev.icerock.moko.widgets.utils.bind -import dev.icerock.moko.widgets.utils.setEventHandler -import kotlinx.cinterop.readValue -import platform.CoreGraphics.CGRectZero -import platform.UIKit.NSTextAlignmentCenter -import platform.UIKit.UIButton -import platform.UIKit.UIButtonTypeRoundedRect -import platform.UIKit.UIControlEventTouchUpInside -import platform.UIKit.UIControlStateNormal -import platform.UIKit.UILabel -import platform.UIKit.UIView -import platform.UIKit.addSubview -import platform.UIKit.bottomAnchor -import platform.UIKit.leadingAnchor -import platform.UIKit.topAnchor -import platform.UIKit.trailingAnchor -import platform.UIKit.translatesAutoresizingMaskIntoConstraints - -actual class FlatAlertViewFactory actual constructor( - private val background: Background?, - private val margins: MarginValues? -) : ViewFactory> { - - override fun build( - widget: FlatAlertWidget, - size: WS, - viewFactoryContext: ViewFactoryContext - ): ViewBundle { - val container = UIView(frame = CGRectZero.readValue()).apply { - translatesAutoresizingMaskIntoConstraints = false - applyBackgroundIfNeeded(background) - } - - val titleLabel = widget.title?.let { title -> - val titleLabel = UILabel(frame = CGRectZero.readValue()).apply { - translatesAutoresizingMaskIntoConstraints = false - textAlignment = NSTextAlignmentCenter - } - - title.bind { titleLabel.text = it?.localized() } - - titleLabel - } - - val messageLabel = UILabel(frame = CGRectZero.readValue()).apply { - translatesAutoresizingMaskIntoConstraints = false - textAlignment = NSTextAlignmentCenter - } - widget.message.bind { messageLabel.text = it?.localized() } - - val button = widget.buttonText?.let { text -> - val button = UIButton.buttonWithType(buttonType = UIButtonTypeRoundedRect).apply { - translatesAutoresizingMaskIntoConstraints = false - } - - text.bind { button.setTitle(it?.localized(), forState = UIControlStateNormal) } - - button.setEventHandler(UIControlEventTouchUpInside) { - widget.onTap?.invoke() - } - - button - } - - with(container) { - addSubview(messageLabel) - - messageLabel.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true - messageLabel.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true - - if (titleLabel != null) { - addSubview(titleLabel) - - titleLabel.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true - titleLabel.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true - - titleLabel.topAnchor.constraintEqualToAnchor(topAnchor).active = true - messageLabel.topAnchor.constraintEqualToAnchor(titleLabel.bottomAnchor).active = - true - } else { - messageLabel.topAnchor.constraintEqualToAnchor(topAnchor).active = true - } - - if (button != null) { - addSubview(button) - - button.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true - button.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true - button.topAnchor.constraintEqualToAnchor(messageLabel.bottomAnchor).active = true - button.bottomAnchor.constraintEqualToAnchor(bottomAnchor).active = true - } else { - messageLabel.bottomAnchor.constraintEqualToAnchor(bottomAnchor).active = true - } - } - - return ViewBundle( - view = container, - size = size, - margins = margins - ) - } -} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt index c1e0f537..84e50bee 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt @@ -13,26 +13,31 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.objc.setAssociatedObject import dev.icerock.moko.widgets.style.applyInputTypeIfNeeded import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.input.InputType -import dev.icerock.moko.widgets.style.view.* +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.utils.DefaultFormatterUITextFieldDelegate +import dev.icerock.moko.widgets.utils.DefaultTextFormatter import dev.icerock.moko.widgets.utils.Edges import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded +import dev.icerock.moko.widgets.utils.applyTextStyleIfNeeded import dev.icerock.moko.widgets.utils.bind import dev.icerock.moko.widgets.utils.identifier -import dev.icerock.moko.widgets.utils.DefaultTextFormatter -import dev.icerock.moko.widgets.utils.applyTextStyleIfNeeded import dev.icerock.moko.widgets.utils.toIosPattern -import dev.icerock.moko.widgets.utils.DefaultFormatterUITextFieldDelegate import kotlinx.cinterop.CValue import kotlinx.cinterop.ObjCAction import kotlinx.cinterop.readValue import kotlinx.cinterop.useContents -import platform.Foundation.NSSelectorFromString -import platform.Foundation.NSRange import platform.CoreGraphics.CGFloat -import platform.CoreGraphics.CGRectZero import platform.CoreGraphics.CGPointMake import platform.CoreGraphics.CGRectMake +import platform.CoreGraphics.CGRectZero +import platform.Foundation.NSRange +import platform.Foundation.NSSelectorFromString import platform.QuartzCore.CALayer import platform.QuartzCore.CAShapeLayer import platform.QuartzCore.CATextLayer @@ -62,12 +67,12 @@ import platform.UIKit.trailingAnchor import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class FloatingLabelInputViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val margins: MarginValues?, private val padding: PaddingValues?, - private val textStyle: TextStyle?, - private val labelTextStyle: TextStyle?, - private val errorTextStyle: TextStyle?, + private val textStyle: TextStyle?, + private val labelTextStyle: TextStyle?, + private val errorTextStyle: TextStyle?, private val underLineColor: Color?, private val underLineFocusedColor: Color?, private val textHorizontalAlignment: TextHorizontalAlignment? @@ -376,7 +381,7 @@ actual class FloatingLabelInputViewFactory actual constructor( textChanged?.invoke(textField.text.orEmpty()) } - fun applyTextStyleIfNeeded(textStyle: TextStyle?) { + fun applyTextStyleIfNeeded(textStyle: TextStyle?) { textField.applyTextStyleIfNeeded(textStyle) } @@ -395,11 +400,11 @@ actual class FloatingLabelInputViewFactory actual constructor( } } - fun applyLabelStyleIfNeeded(textStyle: TextStyle?) { + fun applyLabelStyleIfNeeded(textStyle: TextStyle?) { placeholderTextLayer.applyTextStyleIfNeeded(textStyle) } - fun applyErrorStyleIfNeeded(textStyle: TextStyle?) { + fun applyErrorStyleIfNeeded(textStyle: TextStyle?) { errorLabel.applyTextStyleIfNeeded(textStyle) } @@ -418,5 +423,4 @@ actual class FloatingLabelInputViewFactory actual constructor( CATransaction.commit() } } - } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt index ea4297a4..0b6d1b2d 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/LinearViewFactory.kt @@ -10,6 +10,7 @@ import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.core.Widget import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.background.Orientation import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues @@ -36,9 +37,9 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints import platform.UIKit.widthAnchor actual class LinearViewFactory actual constructor( - private val background: Background?, private val padding: PaddingValues?, - private val margins: MarginValues? + private val margins: MarginValues?, + private val background: Background? ) : ViewFactory> { override fun build( diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt index 6057c571..d6d8cf25 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/StatefulViewFactory.kt @@ -10,6 +10,7 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -27,9 +28,9 @@ import platform.UIKit.hidden import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class StatefulViewFactory actual constructor( - private val background: Background?, private val margins: MarginValues?, - private val padding: PaddingValues? + private val padding: PaddingValues?, + private val background: Background? ) : ViewFactory> { override fun build( diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt index e260ea18..ccec4f7e 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt @@ -4,13 +4,15 @@ package dev.icerock.moko.widgets.factory -import dev.icerock.moko.graphics.toUIColor +import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.ButtonWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.core.bind -import dev.icerock.moko.widgets.style.background.StateBackground +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle @@ -20,16 +22,16 @@ import dev.icerock.moko.widgets.utils.applyTextStyleIfNeeded import dev.icerock.moko.widgets.utils.bind import dev.icerock.moko.widgets.utils.setEventHandler import platform.UIKit.UIButton -import platform.UIKit.UIButtonTypeSystem import platform.UIKit.UIButtonTypeCustom +import platform.UIKit.UIButtonTypeSystem import platform.UIKit.UIControlEventTouchUpInside import platform.UIKit.UIControlStateNormal import platform.UIKit.UIEdgeInsetsMake import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemButtonViewFactory actual constructor( - private val background: StateBackground?, - private val textStyle: TextStyle?, + private val background: PressableState>?, + private val textStyle: TextStyle>?, private val isAllCaps: Boolean?, private val padding: PaddingValues?, private val margins: MarginValues?, @@ -53,9 +55,7 @@ actual class SystemButtonViewFactory actual constructor( applyStateBackgroundIfNeeded(background) - titleLabel?.applyTextStyleIfNeeded(textStyle) - - textStyle?.color?.also { setTintColor(it.toUIColor()) } + applyTextStyleIfNeeded(textStyle) padding?.let { contentEdgeInsets = UIEdgeInsetsMake( diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt index f0aa77b3..c51e1fae 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemCollectionViewFactory.kt @@ -11,6 +11,7 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.background.Orientation import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues @@ -46,9 +47,9 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemCollectionViewFactory actual constructor( private val orientation: Orientation, private val spanCount: Int, - private val background: Background?, private val padding: PaddingValues?, - private val margins: MarginValues? + private val margins: MarginValues?, + private val background: Background? ) : ViewFactory> { override fun build( @@ -113,6 +114,12 @@ actual class SystemCollectionViewFactory actual constructor( ) } + @Suppress( + "CONFLICTING_OVERLOADS", + "RETURN_TYPE_MISMATCH_ON_INHERITANCE", + "MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED", + "DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES" + ) private class SpanCollectionViewLayout( private val spanCount: Int ) : UICollectionViewFlowLayout(), UICollectionViewDelegateFlowLayoutProtocol { diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt index 2defcabb..c3005e3b 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemImageViewFactory.kt @@ -8,7 +8,6 @@ import dev.icerock.moko.widgets.ImageWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.style.view.CornerRadiusValue import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.bind @@ -20,7 +19,7 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemImageViewFactory actual constructor( private val margins: MarginValues?, - private val cornerRadiusValue: CornerRadiusValue? + private val cornerRadius: Float? ) : ViewFactory> { override fun build( @@ -43,7 +42,7 @@ actual class SystemImageViewFactory actual constructor( UIViewContentMode.UIViewContentModeScaleAspectFit } - layer.cornerRadius = cornerRadiusValue?.radius?.toDouble() ?: 0.0 + layer.cornerRadius = cornerRadius?.toDouble() ?: 0.0 layer.masksToBounds = true clipsToBounds = true } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt index 2f506f69..e5ae7411 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt @@ -13,14 +13,21 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.objc.setAssociatedObject import dev.icerock.moko.widgets.style.applyInputTypeIfNeeded import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.* +import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.view.IOSFieldBorderStyle +import dev.icerock.moko.widgets.style.view.MarginValues +import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment +import dev.icerock.moko.widgets.style.view.TextStyle +import dev.icerock.moko.widgets.style.view.TextVerticalAlignment +import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.utils.DefaultFormatterUITextFieldDelegate +import dev.icerock.moko.widgets.utils.DefaultTextFormatter import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded import dev.icerock.moko.widgets.utils.applyTextStyleIfNeeded import dev.icerock.moko.widgets.utils.bind import dev.icerock.moko.widgets.utils.setEventHandler -import dev.icerock.moko.widgets.utils.DefaultTextFormatter import dev.icerock.moko.widgets.utils.toIosPattern -import dev.icerock.moko.widgets.utils.DefaultFormatterUITextFieldDelegate import kotlinx.cinterop.readValue import platform.CoreGraphics.CGRectZero import platform.Foundation.NSMutableAttributedString @@ -37,15 +44,12 @@ import platform.UIKit.UITextBorderStyle import platform.UIKit.UITextField import platform.UIKit.clipsToBounds import platform.UIKit.translatesAutoresizingMaskIntoConstraints -import platform.UIKit.addSubview -import platform.UIKit.UIView -import platform.UIKit.UITextFieldDelegateProtocol actual class SystemInputViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val margins: MarginValues?, private val padding: PaddingValues?, - private val textStyle: TextStyle?, + private val textStyle: TextStyle?, private val labelTextColor: Color?, private val textHorizontalAlignment: TextHorizontalAlignment?, private val textVerticalAlignment: TextVerticalAlignment?, diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt index c79d4c63..cd14f9dc 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemListViewFactory.kt @@ -11,6 +11,7 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -34,7 +35,7 @@ import platform.UIKit.layoutMargins import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemListViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val dividerEnabled: Boolean?, private val reversed: Boolean, private val padding: PaddingValues?, diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt index 8b05772f..c606f6cf 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemScrollViewFactory.kt @@ -9,6 +9,7 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -29,7 +30,7 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints import platform.UIKit.widthAnchor actual class SystemScrollViewFactory actual constructor( - private val background: Background?, + private val background: Background?, private val padding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt index 28637994..fbd5ec2b 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSingleChoiceViewFactory.kt @@ -10,6 +10,7 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle @@ -17,11 +18,11 @@ import dev.icerock.moko.widgets.style.view.WidgetSize import platform.UIKit.UIView actual class SystemSingleChoiceViewFactory actual constructor( - private val textStyle: TextStyle?, - private val labelTextStyle: TextStyle?, + private val textStyle: TextStyle?, + private val labelTextStyle: TextStyle?, private val dropDownTextColor: Color?, private val underlineColor: Color?, - private val dropDownBackground: Background?, + private val dropDownBackground: Background?, private val padding: PaddingValues?, private val margins: MarginValues? ) : ViewFactory> { diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt index bcc33b67..1089124f 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemSwitchViewFactory.kt @@ -4,12 +4,14 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.graphics.toUIColor import dev.icerock.moko.widgets.SwitchWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.style.ColorStyle import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded @@ -22,8 +24,8 @@ import platform.UIKit.UISwitch import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemSwitchViewFactory actual constructor( - private val background: Background?, - private val switchColor: ColorStyle?, + private val background: Background?, + private val tintColor: Color?, private val margins: MarginValues? ) : ViewFactory> { @@ -36,7 +38,7 @@ actual class SystemSwitchViewFactory actual constructor( translatesAutoresizingMaskIntoConstraints = false applyBackgroundIfNeeded(background) - // TODO add color style support + tintColor?.also { onTintColor = it.toUIColor() } } widget.state.bind { switch.on = it } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index 796f1ddd..dc73db0d 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -11,6 +11,7 @@ import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -50,8 +51,8 @@ actual class SystemTabsViewFactory actual constructor( private val tabsTintColor: Color?, private val selectedTitleColor: Color?, private val normalTitleColor: Color?, - private val tabsBackground: Background?, - private val contentBackground: Background?, + private val tabsBackground: Background?, + private val contentBackground: Background?, private val tabsPadding: PaddingValues?, private val contentPadding: PaddingValues?, private val margins: MarginValues? diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt index 834276de..ff45622e 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt @@ -4,17 +4,18 @@ package dev.icerock.moko.widgets.factory +import dev.icerock.moko.graphics.Color import dev.icerock.moko.graphics.toUIColor import dev.icerock.moko.widgets.TextWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment import dev.icerock.moko.widgets.style.view.TextStyle import dev.icerock.moko.widgets.style.view.WidgetSize -import dev.icerock.moko.widgets.style.view.SizeSpec import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded import dev.icerock.moko.widgets.utils.applyTextStyleIfNeeded import dev.icerock.moko.widgets.utils.bind @@ -47,26 +48,15 @@ import platform.UIKit.NSTextAlignmentLeft import platform.UIKit.NSTextAlignmentRight import platform.UIKit.NSUnderlineColorAttributeName import platform.UIKit.UIApplication -import platform.UIKit.UIColor import platform.UIKit.UILabel -import platform.UIKit.UILayoutConstraintAxisHorizontal -import platform.UIKit.UILayoutConstraintAxisVertical import platform.UIKit.UITapGestureRecognizer -import platform.UIKit.UIView import platform.UIKit.addGestureRecognizer -import platform.UIKit.addSubview -import platform.UIKit.backgroundColor -import platform.UIKit.bottomAnchor import platform.UIKit.create -import platform.UIKit.leadingAnchor -import platform.UIKit.setContentCompressionResistancePriority -import platform.UIKit.topAnchor -import platform.UIKit.trailingAnchor import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemTextViewFactory actual constructor( - private val background: Background?, - private val textStyle: TextStyle?, + private val background: Background?, + private val textStyle: TextStyle?, private val textHorizontalAlignment: TextHorizontalAlignment?, private val margins: MarginValues?, private val isHtmlConverted: Boolean @@ -80,12 +70,10 @@ actual class SystemTextViewFactory actual constructor( val label = UILabel(frame = CGRectZero.readValue()).apply { translatesAutoresizingMaskIntoConstraints = false applyTextStyleIfNeeded(textStyle) + applyBackgroundIfNeeded(background) numberOfLines = 0 - setContentCompressionResistancePriority(749f, UILayoutConstraintAxisHorizontal) - setContentCompressionResistancePriority(749f, UILayoutConstraintAxisVertical) - when (this@SystemTextViewFactory.textHorizontalAlignment) { TextHorizontalAlignment.LEFT -> textAlignment = NSTextAlignmentLeft TextHorizontalAlignment.CENTER -> textAlignment = NSTextAlignmentCenter @@ -110,36 +98,15 @@ actual class SystemTextViewFactory actual constructor( widget.text.bind { label.text = it.localized() } } - val wrapper = UIView(frame = CGRectZero.readValue()).apply { - translatesAutoresizingMaskIntoConstraints = false - backgroundColor = UIColor.clearColor - applyBackgroundIfNeeded(background) - } - - if (size is WidgetSize.Const<*, *> ) { - if (size.width is SizeSpec.WrapContent) { - label.setContentCompressionResistancePriority(priority = 999f, forAxis = UILayoutConstraintAxisHorizontal) - } - if (size.height is SizeSpec.WrapContent) { - label.setContentCompressionResistancePriority(priority = 999f, forAxis = UILayoutConstraintAxisVertical) - } - } - - wrapper.addSubview(label) - label.topAnchor.constraintEqualToAnchor(wrapper.topAnchor).active = true - label.leadingAnchor.constraintEqualToAnchor(wrapper.leadingAnchor).active = true - wrapper.trailingAnchor.constraintEqualToAnchor(label.trailingAnchor).active = true - wrapper.bottomAnchor.constraintEqualToAnchor(label.bottomAnchor).active = true - return ViewBundle( - view = wrapper, + view = label, size = size, margins = margins ) } } -private fun String.stringFromHtml(textStyle: TextStyle?): NSAttributedString? { +private fun String.stringFromHtml(textStyle: TextStyle?): NSAttributedString? { val nsString = NSString.create(string = this) val data: NSData = nsString.dataUsingEncoding(NSUTF8StringEncoding) ?: return null @@ -156,7 +123,7 @@ private fun String.stringFromHtml(textStyle: TextStyle?): NSAttributedString? { } } -private fun NSMutableAttributedString.changeUrlColor(textStyle: TextStyle?) { +private fun NSMutableAttributedString.changeUrlColor(textStyle: TextStyle?) { if (textStyle?.color == null) return this.enumerateAttribute(attrName = NSLinkAttributeName, diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt index bb5cb0b1..2d021776 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/WebViewFactory.kt @@ -11,23 +11,24 @@ import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.objc.setAssociatedObject import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.WebViewRedirectUrlHandler import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded -import platform.UIKit.translatesAutoresizingMaskIntoConstraints -import platform.WebKit.WKWebView -import platform.WebKit.WKNavigationDelegateProtocol -import platform.Foundation.NSURLRequest import platform.Foundation.NSURL +import platform.Foundation.NSURLRequest +import platform.UIKit.translatesAutoresizingMaskIntoConstraints import platform.WebKit.WKNavigation import platform.WebKit.WKNavigationAction import platform.WebKit.WKNavigationActionPolicy +import platform.WebKit.WKNavigationDelegateProtocol +import platform.WebKit.WKWebView import platform.darwin.NSObject actual class WebViewFactory actual constructor( private val margins: MarginValues?, - private val background: Background? + private val background: Background? ) : ViewFactory> { override fun build( @@ -85,18 +86,18 @@ actual class WebViewFactory actual constructor( decisionHandler: (WKNavigationActionPolicy) -> Unit ) { val requestUrl = decidePolicyForNavigationAction.request.URL - if(requestUrl == null) { + if (requestUrl == null) { decisionHandler(WKNavigationActionPolicy.WKNavigationActionPolicyCancel) return } val strRequestUrl = requestUrl.absoluteString - if(strRequestUrl == null) { + if (strRequestUrl == null) { decisionHandler(WKNavigationActionPolicy.WKNavigationActionPolicyCancel) return } - if(redirectUrlHandler.handleUrl(strRequestUrl)) { + if (redirectUrlHandler.handleUrl(strRequestUrl)) { // If strRequestUrl contains success or failure token, then cancel navigation. decisionHandler(WKNavigationActionPolicy.WKNavigationActionPolicyCancel) } else { diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt index d7fc88f2..4578aa3c 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt @@ -9,8 +9,7 @@ import dev.icerock.moko.widgets.objc.cgColors import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Direction import dev.icerock.moko.widgets.style.background.Fill -import dev.icerock.moko.widgets.style.background.Shape -import dev.icerock.moko.widgets.style.background.StateBackground +import dev.icerock.moko.widgets.style.state.PressableState import kotlinx.cinterop.useContents import platform.CoreGraphics.CGPointMake import platform.CoreGraphics.CGRectMake @@ -19,12 +18,10 @@ import platform.QuartzCore.CALayer import platform.QuartzCore.CATransaction import platform.UIKit.UIButton import platform.UIKit.UIColor -import platform.UIKit.UIControl import platform.UIKit.UIView import platform.UIKit.backgroundColor -import kotlin.math.min -fun Background.caLayer(): CALayer { +fun Background.caLayer(): CALayer { val backgroundLayer: CALayer @@ -60,38 +57,18 @@ fun Background.caLayer(): CALayer { } } - val border = border - if (border != null) { - backgroundLayer.borderWidth = border.width.toDouble() - backgroundLayer.borderColor = border.color.toUIColor().CGColor + border?.also { + backgroundLayer.borderWidth = it.width.toDouble() + backgroundLayer.borderColor = it.color.toUIColor().CGColor } - - when (val shape = shape) { - is Shape.Rectangle -> { - val cornerRadius = shape.cornerRadius - if (cornerRadius != null) { - backgroundLayer.masksToBounds = true - - // FIXME memoryleak. - backgroundLayer.displayLink { - CATransaction.begin() - CATransaction.setDisableActions(true) - - val minEdge = backgroundLayer.bounds.useContents { min(size.width, size.height) } - backgroundLayer.cornerRadius = min(minEdge / 2, cornerRadius.toDouble()) - - CATransaction.commit() - } - } - } - is Shape.Oval -> { - TODO() - } + cornerRadius?.also { + backgroundLayer.cornerRadius = it.toDouble() } + return backgroundLayer } -fun UIButton.applyStateBackgroundIfNeeded(background: StateBackground?) { +fun UIButton.applyStateBackgroundIfNeeded(background: PressableState>?) { if (background == null) return adjustsImageWhenDisabled = false @@ -144,7 +121,18 @@ fun UIButton.applyStateBackgroundIfNeeded(background: StateBackground?) { } } -fun UIView.applyBackgroundIfNeeded(background: Background?) { +fun UIView.applyBackgroundIfNeeded(background: Background?) { + if (background == null) return + + background.fill?.also { backgroundColor = it.color.toUIColor() } + background.border?.also { + layer.borderWidth = it.width.toDouble() + layer.borderColor = it.color.toUIColor().CGColor + } + background.cornerRadius?.also { layer.cornerRadius = it.toDouble() } +} + +fun UIView.applyBackgroundIfNeeded(background: Background?) { if (background == null) return this.backgroundColor = UIColor.clearColor @@ -165,10 +153,10 @@ fun UIView.applyBackgroundIfNeeded(background: Background?) { } } -fun UIControl.applyStateBackgroundIfNeeded(stateBackground: StateBackground?) { - if (stateBackground == null) return - - // TODO complete it - applyBackgroundIfNeeded(stateBackground.normal) -} +//fun UIControl.applyStateBackgroundIfNeeded(stateBackground: PressableState>?) { +// if (stateBackground == null) return +// +// // TODO complete it +// applyBackgroundIfNeeded(stateBackground.normal) +//} \ No newline at end of file diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt index 5d9e1214..943272f8 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt @@ -4,7 +4,9 @@ package dev.icerock.moko.widgets.utils +import dev.icerock.moko.graphics.Color import dev.icerock.moko.graphics.toUIColor +import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.FontStyle import dev.icerock.moko.widgets.style.view.TextStyle import platform.CoreText.CTFontCreateCopyWithSymbolicTraits @@ -12,17 +14,21 @@ import platform.CoreText.CTFontCreateUIFontForLanguage import platform.CoreText.kCTFontBoldTrait import platform.CoreText.kCTFontUIFontSystem import platform.QuartzCore.CATextLayer +import platform.UIKit.UIButton +import platform.UIKit.UIControlStateDisabled +import platform.UIKit.UIControlStateHighlighted +import platform.UIKit.UIControlStateNormal import platform.UIKit.UIFont +import platform.UIKit.UIFontWeightMedium import platform.UIKit.UILabel import platform.UIKit.UITextField import platform.UIKit.systemFontSize -import platform.UIKit.UIFontWeightMedium -fun TextStyle.toUIFont(defautlFontSize: Double = 17.0): UIFont? { // If this is ok, can be applied to other methods +fun TextStyle<*>.toUIFont(defaultFontSize: Double = 17.0): UIFont? { // If this is ok, can be applied to other methods val styleSize = size?.toDouble() val styleStyle = fontStyle if (styleStyle != null || styleSize != null) { - val fontSize = styleSize ?: defautlFontSize + val fontSize = styleSize ?: defaultFontSize return when (styleStyle) { FontStyle.BOLD -> UIFont.boldSystemFontOfSize(fontSize = fontSize) FontStyle.MEDIUM -> UIFont.systemFontOfSize(fontSize = fontSize, weight = UIFontWeightMedium) @@ -32,7 +38,28 @@ fun TextStyle.toUIFont(defautlFontSize: Double = 17.0): UIFont? { // If this is return null } -fun UILabel.applyTextStyleIfNeeded(textStyle: TextStyle?) { +fun UIButton.applyTextStyleIfNeeded(textStyle: TextStyle>?) { + if (textStyle == null) return + + val currentFontSize = titleLabel?.font?.pointSize ?: 14.0 + val styleSize = textStyle.size?.toDouble() + val styleStyle = textStyle.fontStyle + if (styleStyle != null || styleSize != null) { + val fontSize = styleSize ?: currentFontSize + titleLabel?.font = when (styleStyle) { + FontStyle.BOLD -> UIFont.boldSystemFontOfSize(fontSize = fontSize) + else -> UIFont.systemFontOfSize(fontSize = fontSize) + } + } + + textStyle.color?.also { + setTitleColor(color = it.normal.toUIColor(), forState = UIControlStateNormal) + setTitleColor(color = it.pressed.toUIColor(), forState = UIControlStateHighlighted) + setTitleColor(color = it.disabled.toUIColor(), forState = UIControlStateDisabled) + } +} + +fun UILabel.applyTextStyleIfNeeded(textStyle: TextStyle?) { if (textStyle == null) return val currentFontSize = font.pointSize @@ -48,7 +75,7 @@ fun UILabel.applyTextStyleIfNeeded(textStyle: TextStyle?) { textStyle.color?.also { textColor = it.toUIColor() } } -fun UITextField.applyTextStyleIfNeeded(textStyle: TextStyle?) { +fun UITextField.applyTextStyleIfNeeded(textStyle: TextStyle?) { if (textStyle == null) return val currentFontSize = font?.pointSize ?: UIFont.systemFontSize @@ -64,7 +91,7 @@ fun UITextField.applyTextStyleIfNeeded(textStyle: TextStyle?) { textStyle.color?.also { textColor = it.toUIColor() } } -fun CATextLayer.applyTextStyleIfNeeded(textStyle: TextStyle?) { +fun CATextLayer.applyTextStyleIfNeeded(textStyle: TextStyle?) { if (textStyle == null) return textStyle.size?.let { From 1bf23b91f1528b3237a54392bc51bbe1f9f9af8f Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 13:36:33 +0700 Subject: [PATCH 17/48] #138 add stateful styles, move tabs to TabLayout (recommended way from google) --- .../mpp-library/src/commonMain/kotlin/App.kt | 18 ++- .../kotlin/com/icerockdev/library/AppTheme.kt | 7 +- .../factory/CheckboxSwitchViewFactory.kt | 8 +- .../factory/FloatingLabelInputViewFactory.kt | 25 +-- .../widgets/factory/SystemTabsViewFactory.kt | 147 +++++++----------- .../navigation/BottomNavigationScreen.kt | 3 +- .../icerock/moko/widgets/utils/ThemeAttrs.kt | 88 +++++++---- .../factory/CheckboxSwitchViewFactory.kt | 4 +- .../factory/FloatingLabelInputViewFactory.kt | 4 +- .../widgets/factory/SystemTabsViewFactory.kt | 4 +- .../navigation/BottomNavigationScreen.kt | 16 +- .../widgets/style/state/CheckableState.kt | 12 ++ .../factory/CheckboxSwitchViewFactory.kt | 6 +- .../factory/FloatingLabelInputViewFactory.kt | 12 +- .../widgets/factory/SystemTabsViewFactory.kt | 37 ++--- .../navigation/BottomNavigationScreen.kt | 3 +- 16 files changed, 193 insertions(+), 201 deletions(-) create mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/CheckableState.kt diff --git a/sample/mpp-library/src/commonMain/kotlin/App.kt b/sample/mpp-library/src/commonMain/kotlin/App.kt index 203fd56f..36098649 100644 --- a/sample/mpp-library/src/commonMain/kotlin/App.kt +++ b/sample/mpp-library/src/commonMain/kotlin/App.kt @@ -50,7 +50,6 @@ import dev.icerock.moko.widgets.screen.navigation.NavigationItem import dev.icerock.moko.widgets.screen.navigation.NavigationScreen import dev.icerock.moko.widgets.screen.navigation.Resultable import dev.icerock.moko.widgets.screen.navigation.Route -import dev.icerock.moko.widgets.screen.navigation.SelectStates import dev.icerock.moko.widgets.screen.navigation.createPushResultRoute import dev.icerock.moko.widgets.screen.navigation.createPushRoute import dev.icerock.moko.widgets.screen.navigation.createRouter @@ -58,6 +57,7 @@ import dev.icerock.moko.widgets.screen.navigation.route import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.state.PressableState +import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextStyle @@ -147,10 +147,10 @@ class App() : BaseApplication() { val loginTheme = Theme(AppTheme.loginScreen) { factory[LoginScreen.Id.EmailInputId] = FlatInputViewFactory( -// textStyle = TextStyle( -// size = 16, -// color = Color(0x16171AFF) -// ), + textStyle = TextStyle( + size = 16, + color = Color(0x16171AFF) + ), backgroundColor = Color(0xF5F5F5FF) ) factory[LoginScreen.Id.RegistrationButtonId] = ButtonWithIconViewFactory( @@ -179,8 +179,10 @@ class App() : BaseApplication() { factory[TabsWidget.DefaultCategory] = SystemTabsViewFactory( tabsTintColor = Color(0xD20C0AFF), tabsPadding = platformSpecific(android = null, ios = PaddingValues(padding = 16f)), - selectedTitleColor = Color(platformSpecific(android = 0x151515FF, ios = 0xFFFFFFFF)), - normalTitleColor = platformSpecific(android = Color(0x15151599), ios = null) + titleColor = SelectableState( + selected = Color(platformSpecific(android = 0x151515FF, ios = 0xFFFFFFFF)), + unselected = platformSpecific(android = Color(0x15151599), ios = null) + ) ) } @@ -341,7 +343,7 @@ class MainBottomNavigationScreen( init { bottomNavigationColor = Color(0x6518f4FF) - itemStateColors = SelectStates( + itemStateColors = SelectableState( selected = Color(0xfdfffdFF), unselected = Color(0xc0a3f9FF) ) diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt index 3f11c9d5..d8b76d4b 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/AppTheme.kt @@ -24,6 +24,7 @@ import dev.icerock.moko.widgets.factory.SystemTextViewFactory import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Border import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.FocusableState import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.view.Colors import dev.icerock.moko.widgets.style.view.FontStyle @@ -124,8 +125,10 @@ object AppTheme { factory[InputWidget.DefaultCategory] = FloatingLabelInputViewFactory( margins = MarginValues(bottom = 8f), - underLineColor = Color(0x000000DD), - underLineFocusedColor = Color(0x3949ABFF), + underLineColor = FocusableState( + focused = Color(0x3949ABFF), + unfocused = Color(0x000000DD) + ), labelTextStyle = TextStyle( size = 12, color = Color(0x3949ABFF), diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt index dcf5c206..31d24525 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt @@ -15,14 +15,14 @@ import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.CheckableState import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.androidId import dev.icerock.moko.widgets.utils.bindNotNull actual class CheckboxSwitchViewFactory actual constructor( private val background: Background?, - private val checkedImage: ImageResource, - private val uncheckedImage: ImageResource + private val image: CheckableState ) : ViewFactory> { override fun build( widget: SwitchWidget, @@ -41,11 +41,11 @@ actual class CheckboxSwitchViewFactory actual constructor( val drawable = StateListDrawable().apply { addState( intArrayOf(android.R.attr.state_checked), - ContextCompat.getDrawable(context, checkedImage.drawableResId) + ContextCompat.getDrawable(context, image.checked.drawableResId) ) addState( intArrayOf(-android.R.attr.state_checked), - ContextCompat.getDrawable(context, uncheckedImage.drawableResId) + ContextCompat.getDrawable(context, image.unchecked.drawableResId) ) } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt index 8cd04f03..36d37550 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt @@ -28,6 +28,7 @@ import dev.icerock.moko.widgets.style.applyTextStyleIfNeeded import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.ext.getGravity +import dev.icerock.moko.widgets.style.state.FocusableState import dev.icerock.moko.widgets.style.view.FontStyle import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues @@ -46,8 +47,7 @@ actual class FloatingLabelInputViewFactory actual constructor( private val textStyle: TextStyle?, private val labelTextStyle: TextStyle?, private val errorTextStyle: TextStyle?, - private val underLineColor: Color?, - private val underLineFocusedColor: Color?, + private val underLineColor: FocusableState?, private val textHorizontalAlignment: TextHorizontalAlignment? ) : ViewFactory> { @@ -87,34 +87,19 @@ actual class FloatingLabelInputViewFactory actual constructor( gravity = it.getGravity() } - val focusedColor = underLineFocusedColor?.argb?.toInt() - val defaultColor = underLineColor?.argb?.toInt() - - if (focusedColor != null && defaultColor != null) { + underLineColor?.also { stateColor -> supportBackgroundTintList = ColorStateList( arrayOf( intArrayOf(-android.R.attr.state_focused, -android.R.attr.state_pressed), intArrayOf() ), intArrayOf( - defaultColor, - focusedColor - ) - ) - } else if (defaultColor != null) { - supportBackgroundTintList = ColorStateList.valueOf(defaultColor) - } else if (focusedColor != null) { - supportBackgroundTintList = ColorStateList( - arrayOf( - intArrayOf(android.R.attr.state_focused, android.R.attr.state_activated) - ), - intArrayOf( - focusedColor + stateColor.unfocused.argb.toInt(), + stateColor.focused.argb.toInt() ) ) } - setOnFocusChangeListener { _, hasFocus -> if (!hasFocus) widget.field.validate() } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index dd315d30..44a6b2c5 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -5,18 +5,13 @@ package dev.icerock.moko.widgets.factory import android.content.res.ColorStateList -import android.view.ContextThemeWrapper -import android.view.Gravity import android.view.View import android.view.ViewGroup -import android.widget.FrameLayout import android.widget.LinearLayout -import android.widget.TabHost -import android.widget.TabWidget -import android.widget.TextView -import androidx.core.view.ViewCompat +import androidx.viewpager.widget.PagerAdapter +import androidx.viewpager.widget.ViewPager +import com.google.android.material.tabs.TabLayout import dev.icerock.moko.graphics.Color -import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.widgets.TabsWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory @@ -25,15 +20,15 @@ import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded import dev.icerock.moko.widgets.style.applyPaddingIfNeeded import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize -import dev.icerock.moko.widgets.utils.bindNotNull +import dev.icerock.moko.widgets.utils.ThemeAttrs actual class SystemTabsViewFactory actual constructor( private val tabsTintColor: Color?, - private val selectedTitleColor: Color?, - private val normalTitleColor: Color?, + private val titleColor: SelectableState?, private val tabsBackground: Background?, private val contentBackground: Background?, private val tabsPadding: PaddingValues?, @@ -49,118 +44,96 @@ actual class SystemTabsViewFactory actual constructor( val context = viewFactoryContext.context val lifecycleOwner = viewFactoryContext.lifecycleOwner - val tabHost = TabHost(context).apply { - id = android.R.id.tabhost - } - val container = LinearLayout(context).apply { orientation = LinearLayout.VERTICAL applyBackgroundIfNeeded(this@SystemTabsViewFactory.contentBackground) } - tabHost.addView( - container, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - - val tabWidget = TabWidget(context).apply { + val tabLayout = TabLayout(context).apply { id = android.R.id.tabs applyBackgroundIfNeeded(this@SystemTabsViewFactory.tabsBackground) } container.addView( - tabWidget, + tabLayout, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ) tabsPadding?.also { - val mlp = tabWidget.layoutParams as ViewGroup.MarginLayoutParams + val mlp = tabLayout.layoutParams as ViewGroup.MarginLayoutParams mlp.topMargin = it.top.toInt() mlp.bottomMargin = it.bottom.toInt() mlp.leftMargin = it.start.toInt() mlp.rightMargin = it.end.toInt() } - val content = FrameLayout(context).apply { + val viewPagerAdapter = object : PagerAdapter() { + override fun isViewFromObject(view: View, `object`: Any): Boolean { + return view == `object` + } + + override fun getCount(): Int { + return widget.tabs.size + } + + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val viewBundle = widget.tabs[position].body.buildView( + ViewFactoryContext( + context = context, + lifecycleOwner = lifecycleOwner, + parent = container + ) + ) + val view = viewBundle.view + container.addView(view) + return view + } + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + container.removeView(`object` as View?) + } + + override fun getPageTitle(position: Int): CharSequence? { + return widget.tabs[position].title.value.toString(context) + } + } + val viewPager = ViewPager(context).apply { id = android.R.id.tabcontent applyPaddingIfNeeded(contentPadding) + + adapter = viewPagerAdapter } + container.addView( - content, + viewPager, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ) - tabHost.setup() - - widget.tabs.forEachIndexed { index, tab -> - fun createIndicator(stringDesc: StringDesc): View { - val tabContainer = FrameLayout( - ContextThemeWrapper( - context, - android.R.style.Widget_DeviceDefault_Tab - ) - ) - val text = TextView( - ContextThemeWrapper( - context, - android.R.style.Widget_DeviceDefault_ActionBar_TabText - ) - ).apply { - text = stringDesc.toString(context) - } - tabsTintColor?.also { - ViewCompat.setBackgroundTintList(tabContainer, ColorStateList.valueOf(it.argb.toInt())) - } - val selected = selectedTitleColor?.argb?.toInt() - val normal = normalTitleColor?.argb?.toInt() - if (selected != null && normal != null) { - text.setTextColor( - ColorStateList( - arrayOf( - intArrayOf(android.R.attr.state_selected), - intArrayOf(-android.R.attr.state_selected) - ), - intArrayOf( - selected, - normal - ) - ) - ) - } - tabContainer.addView( - text, FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT, - Gravity.CENTER - ) + tabsTintColor?.also { + tabLayout.setSelectedTabIndicatorColor(it.argb.toInt()) + } + titleColor?.also { stateColor -> + tabLayout.tabTextColors = ColorStateList( + arrayOf( + intArrayOf(android.R.attr.state_selected), + intArrayOf(-android.R.attr.state_selected) + ), + intArrayOf( + stateColor.selected?.argb?.toInt() ?: ThemeAttrs.getSelectedTabColor(context), + stateColor.unselected?.argb?.toInt() ?: ThemeAttrs.getNormalTabColor(context) ) - return tabContainer - } - - val tabSpec = tabHost.newTabSpec("tab$index").apply { - setContent { - tab.body.buildView( - ViewFactoryContext( - context = context, - parent = content, - lifecycleOwner = lifecycleOwner - ) - ).view // TODO apply margins? - } - setIndicator(createIndicator(tab.title.value)) - } - tab.title.bindNotNull(lifecycleOwner) { tabSpec.setIndicator(createIndicator(it)) } - tabHost.addTab(tabSpec) + ) } + tabLayout.setupWithViewPager(viewPager) + return ViewBundle( - view = tabHost, + view = container, size = size, margins = margins ) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt index 11ad0b20..3a39f9d5 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt @@ -25,6 +25,7 @@ import dev.icerock.moko.graphics.colorInt import dev.icerock.moko.widgets.screen.Args import dev.icerock.moko.widgets.screen.FragmentNavigation import dev.icerock.moko.widgets.screen.Screen +import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.utils.ThemeAttrs import dev.icerock.moko.widgets.utils.dp import dev.icerock.moko.widgets.utils.getIntNullable @@ -39,7 +40,7 @@ actual abstract class BottomNavigationScreen actual constructor( private var bottomNavigationView: BottomNavigationView? = null - actual var itemStateColors: SelectStates? = null + actual var itemStateColors: SelectableState? = null set(value) { field = value updateItemColors() diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt index 859f118b..da39cadd 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt @@ -5,66 +5,86 @@ package dev.icerock.moko.widgets.utils import android.content.Context +import android.content.res.TypedArray import android.graphics.drawable.Drawable import android.os.Build +import androidx.annotation.AttrRes import dev.icerock.moko.widgets.R object ThemeAttrs { fun getContentBackgroundColor(context: Context): Int { - val attrs = intArrayOf(android.R.attr.colorBackground) - val ta = context.obtainStyledAttributes(attrs) - val result = ta.getColor(0, -1) - ta.recycle() - return result + return getAttribute(context, android.R.attr.colorBackground) { + getColor(0, -1) + } } fun getPrimaryColor(context: Context): Int { - val attrs = intArrayOf(R.attr.colorPrimary) - val ta = context.obtainStyledAttributes(attrs) - val result = ta.getColor(0, -1) - ta.recycle() - return result + return getAttribute(context, R.attr.colorPrimary) { + getColor(0, -1) + } } fun getControlNormalColor(context: Context): Int { - val attrs = intArrayOf(R.attr.colorControlNormal) - val ta = context.obtainStyledAttributes(attrs) - val result = ta.getColor(0, -1) - ta.recycle() - return result + return getAttribute(context, R.attr.colorControlNormal) { + getColor(0, -1) + } } fun getPrimaryDarkColor(context: Context): Int { - val attrs = intArrayOf(R.attr.colorPrimaryDark) - val ta = context.obtainStyledAttributes(attrs) - val result = ta.getColor(0, -1) - ta.recycle() - return result + return getAttribute(context, R.attr.colorPrimaryDark) { + getColor(0, -1) + } } - fun getLightStatusBar(context: Context): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false - val attrs = intArrayOf(android.R.attr.windowLightStatusBar) - val ta = context.obtainStyledAttributes(attrs) - val result = ta.getBoolean(0, false) - ta.recycle() - return result + + return getAttribute(context, android.R.attr.windowLightStatusBar) { + getBoolean(0, false) + } } fun getToolBarHeight(context: Context): Int { - val attrs = intArrayOf(android.R.attr.actionBarSize) - val ta = context.obtainStyledAttributes(attrs) - val toolBarHeight = ta.getDimensionPixelSize(0, -1) - ta.recycle() - return toolBarHeight + return getAttribute(context, android.R.attr.actionBarSize) { + getDimensionPixelSize(0, -1) + } } fun getToolBarUpIndicator(context: Context): Drawable { - val attrs = intArrayOf(android.R.attr.homeAsUpIndicator) + return getAttribute(context, android.R.attr.homeAsUpIndicator) { + getDrawable(0) + } + } + + fun getSelectedTabColor(context: Context): Int { + return getAttribute(context, R.attr.tabTextAppearance) { + val resId = getResourceId(0, R.style.TextAppearance_Design_Tab) + + val stateList = getAttribute(context, resId) { + getColorStateList(androidx.appcompat.R.styleable.TextAppearance_android_textColor) + } + + stateList.getColorForState(intArrayOf(android.R.attr.state_selected), stateList.defaultColor) + } + } + + fun getNormalTabColor(context: Context): Int { + return getAttribute(context, R.attr.tabTextAppearance) { + val resId = getResourceId(0, R.style.TextAppearance_Design_Tab) + + val stateList = getAttribute(context, resId) { + getColorStateList(androidx.appcompat.R.styleable.TextAppearance_android_textColor) + } + + stateList.getColorForState(intArrayOf(), stateList.defaultColor) + } + } + + private fun getAttribute(context: Context, @AttrRes id: Int, getter: TypedArray.() -> T?): T { + val attrs = intArrayOf(id) val ta = context.obtainStyledAttributes(attrs) - val indicator = ta.getDrawable(0) + val result = ta.getter() ta.recycle() - return indicator!! + return result!! } } diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt index d6e72070..4864d2ff 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt @@ -9,10 +9,10 @@ import dev.icerock.moko.widgets.SwitchWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.CheckableState import dev.icerock.moko.widgets.style.view.WidgetSize expect class CheckboxSwitchViewFactory( background: Background? = null, - checkedImage: ImageResource, - uncheckedImage: ImageResource + image: CheckableState ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt index b7f52efb..3cde8818 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt @@ -9,6 +9,7 @@ import dev.icerock.moko.widgets.InputWidget import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.FocusableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment @@ -22,7 +23,6 @@ expect class FloatingLabelInputViewFactory( textStyle: TextStyle? = null, labelTextStyle: TextStyle? = null, errorTextStyle: TextStyle? = null, - underLineColor: Color? = null, - underLineFocusedColor: Color? = null, + underLineColor: FocusableState? = null, textHorizontalAlignment: TextHorizontalAlignment? = null ) : ViewFactory> diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index 0a7cadaf..a0108a5e 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -10,14 +10,14 @@ import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Border import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize expect class SystemTabsViewFactory( tabsTintColor: Color? = null, - selectedTitleColor: Color? = null, - normalTitleColor: Color? = null, + titleColor: SelectableState? = null, tabsBackground: Background? = null, contentBackground: Background? = null, tabsPadding: PaddingValues? = null, diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt index 369d8bc9..8fec7cc4 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt @@ -10,6 +10,7 @@ import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.widgets.screen.Args import dev.icerock.moko.widgets.screen.Screen import dev.icerock.moko.widgets.screen.ScreenDesc +import dev.icerock.moko.widgets.style.state.SelectableState expect abstract class BottomNavigationScreen( router: Router, @@ -20,7 +21,7 @@ expect abstract class BottomNavigationScreen( var selectedItemId: Int var bottomNavigationColor: Color? var isTitleVisible: Boolean - var itemStateColors: SelectStates? + var itemStateColors: SelectableState? class Router { fun createChangeTabRoute(itemId: Int): Route @@ -30,7 +31,7 @@ expect abstract class BottomNavigationScreen( data class BottomNavigationItem( val id: Int, val title: StringDesc, - val stateIcons: SelectStates? = null, + val stateIcons: SelectableState? = null, val screenDesc: ScreenDesc ) { class Builder() { @@ -39,7 +40,7 @@ data class BottomNavigationItem( private fun tab( id: Int, title: StringDesc, - stateIcons: SelectStates? = null, + stateIcons: SelectableState? = null, screenDesc: ScreenDesc ) { tabs.add( @@ -62,7 +63,7 @@ data class BottomNavigationItem( tab( id = id, title = title, - stateIcons = SelectStates( + stateIcons = SelectableState( selected = selectedIcon, unselected = unselectedIcon ), @@ -79,7 +80,7 @@ data class BottomNavigationItem( tab( id = id, title = title, - stateIcons = icon?.let { SelectStates(selected = it, unselected = it) }, + stateIcons = icon?.let { SelectableState(all = it) }, screenDesc = screenDesc ) } @@ -87,8 +88,3 @@ data class BottomNavigationItem( fun build(): List = tabs } } - -data class SelectStates( - val selected: T, - val unselected: T -) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/CheckableState.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/CheckableState.kt new file mode 100644 index 00000000..ee436569 --- /dev/null +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/state/CheckableState.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style.state + +data class CheckableState( + val checked: T, + val unchecked: T +) { + constructor(all: T) : this(unchecked = all, checked = all) +} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt index a9575fdc..8d9d9919 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt @@ -11,6 +11,7 @@ import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.CheckableState import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.applyBackgroundIfNeeded import dev.icerock.moko.widgets.utils.bind @@ -22,8 +23,7 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class CheckboxSwitchViewFactory actual constructor( private val background: Background?, - private val checkedImage: ImageResource, - private val uncheckedImage: ImageResource + private val image: CheckableState ) : ViewFactory> { override fun build( widget: SwitchWidget, @@ -37,7 +37,7 @@ actual class CheckboxSwitchViewFactory actual constructor( } widget.state.bind { state -> - val imgRes = if (state) checkedImage else uncheckedImage + val imgRes = if (state) image.checked else image.unchecked btn.setImage(image = imgRes.toUIImage(), forState = UIControlStateNormal) } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt index 84e50bee..bbc5e2b9 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/FloatingLabelInputViewFactory.kt @@ -15,6 +15,7 @@ import dev.icerock.moko.widgets.style.applyInputTypeIfNeeded import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.input.InputType +import dev.icerock.moko.widgets.style.state.FocusableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment @@ -73,8 +74,7 @@ actual class FloatingLabelInputViewFactory actual constructor( private val textStyle: TextStyle?, private val labelTextStyle: TextStyle?, private val errorTextStyle: TextStyle?, - private val underLineColor: Color?, - private val underLineFocusedColor: Color?, + private val underLineColor: FocusableState?, private val textHorizontalAlignment: TextHorizontalAlignment? ) : ViewFactory> { @@ -102,11 +102,9 @@ actual class FloatingLabelInputViewFactory actual constructor( applyLabelStyleIfNeeded(labelTextStyle) applyInputTypeIfNeeded(widget.inputType) - underLineColor?.let { - deselectedColor = it.toUIColor() - } - underLineFocusedColor?.let { - selectedColor = it.toUIColor() + underLineColor?.also { + deselectedColor = it.unfocused.toUIColor() + selectedColor = it.focused.toUIColor() } textChanged = { newValue -> diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index dc73db0d..1e7fa6a4 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -12,6 +12,7 @@ import dev.icerock.moko.widgets.core.ViewFactory import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.background.Fill +import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues import dev.icerock.moko.widgets.style.view.WidgetSize @@ -49,8 +50,7 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints actual class SystemTabsViewFactory actual constructor( private val tabsTintColor: Color?, - private val selectedTitleColor: Color?, - private val normalTitleColor: Color?, + private val titleColor: SelectableState?, private val tabsBackground: Background?, private val contentBackground: Background?, private val tabsPadding: PaddingValues?, @@ -95,22 +95,23 @@ actual class SystemTabsViewFactory actual constructor( applyBackgroundIfNeeded(contentBackground) } - - selectedTitleColor?.also { - segmentedControl.setTitleTextAttributes( - attributes = mapOf( - NSForegroundColorAttributeName to it.toUIColor() - ), - forState = UIControlStateSelected - ) - } - normalTitleColor?.also { - segmentedControl.setTitleTextAttributes( - attributes = mapOf( - NSForegroundColorAttributeName to it.toUIColor() - ), - forState = UIControlStateNormal - ) + titleColor?.also { stateColor -> + stateColor.selected?.also { + segmentedControl.setTitleTextAttributes( + attributes = mapOf( + NSForegroundColorAttributeName to it.toUIColor() + ), + forState = UIControlStateSelected + ) + } + stateColor.unselected?.also { + segmentedControl.setTitleTextAttributes( + attributes = mapOf( + NSForegroundColorAttributeName to it.toUIColor() + ), + forState = UIControlStateNormal + ) + } } widget.tabs.forEachIndexed { index, tabWidget -> diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt index cd284a2b..7d9f4f8b 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt @@ -9,6 +9,7 @@ import dev.icerock.moko.graphics.toUIColor import dev.icerock.moko.widgets.screen.Args import dev.icerock.moko.widgets.screen.Screen import dev.icerock.moko.widgets.screen.application +import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.utils.getStatusBarStyle import platform.UIKit.UIStatusBarStyle import platform.UIKit.UITabBarController @@ -27,7 +28,7 @@ actual abstract class BottomNavigationScreen actual constructor( private var tabBarController: UITabBarController? = null - actual var itemStateColors: SelectStates? = null + actual var itemStateColors: SelectableState? = null set(value) { field = value From 050a5e2e1f73cbb2e64d1833c09cc824601e1b78 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 13:36:49 +0700 Subject: [PATCH 18/48] #138 remove unused code --- .../icerock/moko/widgets/style/view/Margined.kt | 14 -------------- .../dev/icerock/moko/widgets/style/view/Padded.kt | 12 ------------ .../icerock/moko/widgets/utils/BackgroundExt.kt | 8 -------- 3 files changed, 34 deletions(-) delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Margined.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Padded.kt diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Margined.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Margined.kt deleted file mode 100644 index 8990df7c..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Margined.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.style.view - -/** - * Defines a widget that has margins. - * - * @property margins margins for four sides - */ -interface Margined { - val margins: MarginValues? -} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Padded.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Padded.kt deleted file mode 100644 index fe140839..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/style/view/Padded.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.style.view - -/** - * Defines a widget that has inner paddings - */ -interface Padded { - val padding: PaddingValues? -} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt index 4578aa3c..1c7d09da 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/BackgroundExt.kt @@ -152,11 +152,3 @@ fun UIView.applyBackgroundIfNeeded(background: Background?) { CATransaction.commit() } } - -//fun UIControl.applyStateBackgroundIfNeeded(stateBackground: PressableState>?) { -// if (stateBackground == null) return -// -// // TODO complete it -// applyBackgroundIfNeeded(stateBackground.normal) -//} - \ No newline at end of file From da57819ae46434483c5705104c4b4b3ba69a7488 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 20:12:19 +0700 Subject: [PATCH 19/48] #138 tabs old android support fix --- .../widgets/factory/SystemTabsViewFactory.kt | 4 ++-- .../icerock/moko/widgets/utils/ThemeAttrs.kt | 24 +++++-------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt index 44a6b2c5..8c7d5f99 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTabsViewFactory.kt @@ -124,8 +124,8 @@ actual class SystemTabsViewFactory actual constructor( intArrayOf(-android.R.attr.state_selected) ), intArrayOf( - stateColor.selected?.argb?.toInt() ?: ThemeAttrs.getSelectedTabColor(context), - stateColor.unselected?.argb?.toInt() ?: ThemeAttrs.getNormalTabColor(context) + stateColor.selected?.argb?.toInt() ?: ThemeAttrs.getTextColorPrimary(context), + stateColor.unselected?.argb?.toInt() ?: ThemeAttrs.getTextColorSecondary(context) ) ) } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt index da39cadd..c1e729bd 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/utils/ThemeAttrs.kt @@ -56,27 +56,15 @@ object ThemeAttrs { } } - fun getSelectedTabColor(context: Context): Int { - return getAttribute(context, R.attr.tabTextAppearance) { - val resId = getResourceId(0, R.style.TextAppearance_Design_Tab) - - val stateList = getAttribute(context, resId) { - getColorStateList(androidx.appcompat.R.styleable.TextAppearance_android_textColor) - } - - stateList.getColorForState(intArrayOf(android.R.attr.state_selected), stateList.defaultColor) + fun getTextColorPrimary(context: Context): Int { + return getAttribute(context, android.R.attr.textColorPrimary) { + getColor(0, -1) } } - fun getNormalTabColor(context: Context): Int { - return getAttribute(context, R.attr.tabTextAppearance) { - val resId = getResourceId(0, R.style.TextAppearance_Design_Tab) - - val stateList = getAttribute(context, resId) { - getColorStateList(androidx.appcompat.R.styleable.TextAppearance_android_textColor) - } - - stateList.getColorForState(intArrayOf(), stateList.defaultColor) + fun getTextColorSecondary(context: Context): Int { + return getAttribute(context, android.R.attr.textColorSecondary) { + getColor(0, -1) } } From c3959d4b4a1f06db225f59d0b4aef7fdcf6df0e1 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 20:57:05 +0700 Subject: [PATCH 20/48] #138 flatAlert composition version --- .../moko/widgets/CompositionWidgets.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/CompositionWidgets.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/CompositionWidgets.kt index 99d7580e..13524f93 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/CompositionWidgets.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/CompositionWidgets.kt @@ -6,8 +6,11 @@ package dev.icerock.moko.widgets import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.mvvm.livedata.map import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.core.Value import dev.icerock.moko.widgets.core.Widget import dev.icerock.moko.widgets.style.view.SizeSpec import dev.icerock.moko.widgets.style.view.WidgetSize @@ -35,3 +38,29 @@ fun Theme.switchLabeled( ) } } + +fun Theme.flatAlert( + size: WS, + message: LiveData, + buttonText: LiveData, + onTap: () -> Unit +): Widget = constraint(size = size) { + val msg = +text( + size = WidgetSize.Const(width = SizeSpec.MatchConstraint, height = SizeSpec.WrapContent), + text = message.map { it ?: "".desc() } + ) + val submitBtn = +button( + size = WidgetSize.Const(width = SizeSpec.MatchConstraint, height = SizeSpec.WrapContent), + content = ButtonWidget.Content.Text(Value.liveData(buttonText)), + onTap = onTap + ) + + constraints { + msg topToTop root + msg leftRightToLeftRight root + + submitBtn topToBottom msg offset 8 + submitBtn leftRightToLeftRight root + submitBtn bottomToBottom root + } +} From 2f8a1830f056654b31547529bb5377c6a9edf228 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 22:36:42 +0700 Subject: [PATCH 21/48] move android to appcompat views --- .../moko/widgets/factory/CheckboxSwitchViewFactory.kt | 3 ++- .../icerock/moko/widgets/factory/SystemButtonViewFactory.kt | 6 ++++-- .../icerock/moko/widgets/factory/SystemInputViewFactory.kt | 3 ++- .../icerock/moko/widgets/factory/SystemTextViewFactory.kt | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt index 31d24525..8e851ac3 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/CheckboxSwitchViewFactory.kt @@ -6,6 +6,7 @@ package dev.icerock.moko.widgets.factory import android.graphics.drawable.StateListDrawable import android.widget.CheckBox +import androidx.appcompat.widget.AppCompatCheckBox import androidx.core.content.ContextCompat import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.widgets.SwitchWidget @@ -32,7 +33,7 @@ actual class CheckboxSwitchViewFactory actual constructor( val context = viewFactoryContext.context val lifecycleOwner = viewFactoryContext.lifecycleOwner - val checkbox = CheckBox(context).apply { + val checkbox = AppCompatCheckBox(context).apply { id = widget.id.androidId applyBackgroundIfNeeded(this@CheckboxSwitchViewFactory.background) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt index 2388321c..7e59bcdf 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemButtonViewFactory.kt @@ -8,6 +8,8 @@ import android.os.Build import android.view.View import android.widget.Button import android.widget.ImageButton +import androidx.appcompat.widget.AppCompatButton +import androidx.appcompat.widget.AppCompatImageButton import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.ButtonWidget import dev.icerock.moko.widgets.core.ViewBundle @@ -45,7 +47,7 @@ actual class SystemButtonViewFactory actual constructor( // it is hell. Compose save us! ImageButton is ImageView, not Button! val button: View = when (widget.content) { is ButtonWidget.Content.Text -> { - Button(ctx).apply { + AppCompatButton(ctx).apply { widget.content.text.bind(viewFactoryContext.lifecycleOwner) { text -> this.text = text?.toString(ctx) } @@ -54,7 +56,7 @@ actual class SystemButtonViewFactory actual constructor( } } is ButtonWidget.Content.Icon -> { - ImageButton(ctx).apply { + AppCompatImageButton(ctx).apply { widget.content.image.bind(viewFactoryContext.lifecycleOwner) { image -> image.loadIn(this) } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt index bd2ad05c..81ac56ef 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemInputViewFactory.kt @@ -10,6 +10,7 @@ import android.text.TextWatcher import android.view.ViewGroup import android.widget.EditText import android.widget.LinearLayout +import androidx.appcompat.widget.AppCompatEditText import androidx.core.view.MarginLayoutParamsCompat import dev.icerock.moko.graphics.Color import dev.icerock.moko.graphics.colorInt @@ -55,7 +56,7 @@ actual class SystemInputViewFactory actual constructor( val context = viewFactoryContext.androidContext val lifecycleOwner = viewFactoryContext.lifecycleOwner - val editText = EditText(context).apply { + val editText = AppCompatEditText(context).apply { applyBackgroundIfNeeded(this@SystemInputViewFactory.background) applyPaddingIfNeeded(padding) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt index 25b81ab4..0ee1c487 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/factory/SystemTextViewFactory.kt @@ -9,6 +9,7 @@ import android.text.Html import android.text.method.LinkMovementMethod import android.view.Gravity import android.widget.TextView +import androidx.appcompat.widget.AppCompatTextView import dev.icerock.moko.graphics.Color import dev.icerock.moko.widgets.TextWidget import dev.icerock.moko.widgets.core.ViewBundle @@ -40,7 +41,7 @@ actual class SystemTextViewFactory actual constructor( val context = viewFactoryContext.androidContext val lifecycleOwner = viewFactoryContext.lifecycleOwner - val textView = TextView(context).apply { + val textView = AppCompatTextView(context).apply { applyTextStyleIfNeeded(textStyle) applyBackgroundIfNeeded(this@SystemTextViewFactory.background) From d87cb1aaa2e53a50097f8fac3568ecac99b1a10f Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 22:37:05 +0700 Subject: [PATCH 22/48] #138 back flatAlert sample --- .../kotlin/com/icerockdev/library/sample/StateSample.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt index b2a1fa56..78e500b2 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt @@ -17,6 +17,7 @@ import dev.icerock.moko.widgets.container import dev.icerock.moko.widgets.core.Theme import dev.icerock.moko.widgets.core.Value import dev.icerock.moko.widgets.core.Widget +import dev.icerock.moko.widgets.flatAlert import dev.icerock.moko.widgets.linear import dev.icerock.moko.widgets.progressBar import dev.icerock.moko.widgets.stateful @@ -92,9 +93,11 @@ open class StateScreen( private fun Theme.flatAlertWrapped(message: LiveData) = container(size = WidgetSize.AsParent) { center { - text( - size = WidgetSize.WrapContent, - text = message.map { it ?: "".desc() } + flatAlert( + size = WidgetSize.Const(width = SizeSpec.Exact(300f), height = SizeSpec.WrapContent), + message = message.map { it ?: "".desc() as StringDesc? }, + buttonText = const("press me".desc() as StringDesc?), + onTap = { println("pressed") } ) } } From 9ee23b99587ec28f43c776dc68ff9b18fb43d243 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 22:37:13 +0700 Subject: [PATCH 23/48] up version --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 2efe49e6..a371f32f 100755 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -10,7 +10,7 @@ object Versions { } const val kotlin = "1.3.61" - private const val mokoWidgets = "0.1.0-dev-12" + private const val mokoWidgets = "0.1.0-dev-13" private const val mokoResources = "0.8.0" object Plugins { From 17ed06bb92a78c20d62c7de2d8e39626f701eff7 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 22:37:31 +0700 Subject: [PATCH 24/48] add publish local script --- publishToMavenLocal.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 publishToMavenLocal.sh diff --git a/publishToMavenLocal.sh b/publishToMavenLocal.sh new file mode 100755 index 00000000..13637d78 --- /dev/null +++ b/publishToMavenLocal.sh @@ -0,0 +1,3 @@ +./gradlew -PpluginPublish publishPluginPublicationToMavenLocal +./gradlew -PlibraryPublish :widgets:publishToMavenLocal +./gradlew -PlibraryPublish :widgets-flat:publishToMavenLocal :widgets-bottomsheet:publishToMavenLocal :widgets-sms:publishToMavenLocal \ No newline at end of file From 0dc43a8bc4576378b6c2f9f7e7e2f5c385f60e73 Mon Sep 17 00:00:00 2001 From: Andrew Kovalev Date: Sat, 22 Feb 2020 22:37:51 +0700 Subject: [PATCH 25/48] #133 review fixes --- .../factory/MultilineInputViewFactory.kt | 8 +++---- .../moko/widgets/utils/TextStyleExt.kt | 24 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt index fdb72fbc..1b3c236c 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt @@ -19,10 +19,10 @@ import dev.icerock.moko.widgets.style.view.TextVerticalAlignment import dev.icerock.moko.widgets.style.view.WidgetSize expect class MultilineInputViewFactory( - cornerRadiusValue: CornerRadiusValue?, - borderColor: Color?, - borderWidth: Float?, - backgroundViewColor: Color?, + cornerRadiusValue: CornerRadiusValue? = null, + borderColor: Color? = null, + borderWidth: Float? = null, + backgroundViewColor: Color? = null, margins: MarginValues? = null, padding: PaddingValues? = null, textStyle: TextStyle? = null, diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt index b0b64db0..8e95a7e1 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/TextStyleExt.kt @@ -21,10 +21,10 @@ import platform.UIKit.UITextView fun TextStyle.toUIFont(defautlFontSize: Double = 17.0): UIFont? { // If this is ok, can be applied to other methods val styleSize = size?.toDouble() - val styleStyle = fontStyle - if (styleStyle != null || styleSize != null) { + val fontStyle = fontStyle + if (fontStyle != null || styleSize != null) { val fontSize = styleSize ?: defautlFontSize - return when (styleStyle) { + return when (fontStyle) { FontStyle.BOLD -> UIFont.boldSystemFontOfSize(fontSize = fontSize) FontStyle.MEDIUM -> UIFont.systemFontOfSize(fontSize = fontSize, weight = UIFontWeightMedium) else -> UIFont.systemFontOfSize(fontSize = fontSize) @@ -38,10 +38,10 @@ fun UILabel.applyTextStyleIfNeeded(textStyle: TextStyle?) { val currentFontSize = font.pointSize val styleSize = textStyle.size?.toDouble() - val styleStyle = textStyle.fontStyle - if (styleStyle != null || styleSize != null) { + val fontStyle = textStyle.fontStyle + if (fontStyle != null || styleSize != null) { val fontSize = styleSize ?: currentFontSize - font = when (styleStyle) { + font = when (fontStyle) { FontStyle.BOLD -> UIFont.boldSystemFontOfSize(fontSize = fontSize) else -> UIFont.systemFontOfSize(fontSize = fontSize) } @@ -54,10 +54,10 @@ fun UITextField.applyTextStyleIfNeeded(textStyle: TextStyle?) { val currentFontSize = font?.pointSize ?: UIFont.systemFontSize val styleSize = textStyle.size?.toDouble() - val styleStyle = textStyle.fontStyle - if (styleStyle != null || styleSize != null) { + val fontStyle = textStyle.fontStyle + if (fontStyle != null || styleSize != null) { val fontSize = styleSize ?: currentFontSize - font = when (styleStyle) { + font = when (fontStyle) { FontStyle.BOLD -> UIFont.boldSystemFontOfSize(fontSize = fontSize) else -> UIFont.systemFontOfSize(fontSize = fontSize) } @@ -97,10 +97,10 @@ fun UITextView.applyTextStyleIfNeeded(textStyle: TextStyle?) { val currentFontSize = font?.pointSize ?: UIFont.systemFontSize val styleSize = textStyle.size?.toDouble() - val styleStyle = textStyle.fontStyle - if (styleStyle != null || styleSize != null) { + val fontStyle = textStyle.fontStyle + if (fontStyle != null || styleSize != null) { val fontSize = styleSize ?: currentFontSize - font = when (styleStyle) { + font = when (fontStyle) { FontStyle.BOLD -> UIFont.boldSystemFontOfSize(fontSize = fontSize) else -> UIFont.systemFontOfSize(fontSize = fontSize) } From e149e788af3957ed9ca9d330dc8435a2cb101cc7 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 22:49:40 +0700 Subject: [PATCH 26/48] #138 separate composited widgets, fix flatAlert --- .../icerock/moko/widgets/FlatAlertWidget.kt | 47 +++++++++++++++++++ ...itionWidgets.kt => SwitchLabeledWidget.kt} | 31 +----------- 2 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt rename widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/{CompositionWidgets.kt => SwitchLabeledWidget.kt} (51%) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt new file mode 100644 index 00000000..2fe4c464 --- /dev/null +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/FlatAlertWidget.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets + +import dev.icerock.moko.mvvm.livedata.LiveData +import dev.icerock.moko.mvvm.livedata.map +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.resources.desc.desc +import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.core.Value +import dev.icerock.moko.widgets.core.Widget +import dev.icerock.moko.widgets.style.view.SizeSpec +import dev.icerock.moko.widgets.style.view.WidgetSize + +fun Theme.flatAlert( + size: WS, + message: LiveData, + buttonText: LiveData, + onTap: () -> Unit +): Widget = constraint(size = size) { + val msg = +text( + id = FlatAlertIds.Message, + size = WidgetSize.Const(width = SizeSpec.MatchConstraint, height = SizeSpec.WrapContent), + text = message.map { it ?: "".desc() } + ) + val submitBtn = +button( + id = FlatAlertIds.Button, + size = WidgetSize.WrapContent, + content = ButtonWidget.Content.Text(Value.liveData(buttonText)), + onTap = onTap + ) + + constraints { + msg centerYToCenterY root + msg centerXToCenterX root + + submitBtn topToBottom msg offset 8 + submitBtn centerXToCenterX root + } +} + +object FlatAlertIds { + object Message : TextWidget.Id + object Button : ButtonWidget.Id +} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/CompositionWidgets.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/SwitchLabeledWidget.kt similarity index 51% rename from widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/CompositionWidgets.kt rename to widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/SwitchLabeledWidget.kt index 13524f93..2728ae8c 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/CompositionWidgets.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/SwitchLabeledWidget.kt @@ -1,16 +1,13 @@ /* - * Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. */ package dev.icerock.moko.widgets import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData -import dev.icerock.moko.mvvm.livedata.map import dev.icerock.moko.resources.desc.StringDesc -import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.core.Value import dev.icerock.moko.widgets.core.Widget import dev.icerock.moko.widgets.style.view.SizeSpec import dev.icerock.moko.widgets.style.view.WidgetSize @@ -38,29 +35,3 @@ fun Theme.switchLabeled( ) } } - -fun Theme.flatAlert( - size: WS, - message: LiveData, - buttonText: LiveData, - onTap: () -> Unit -): Widget = constraint(size = size) { - val msg = +text( - size = WidgetSize.Const(width = SizeSpec.MatchConstraint, height = SizeSpec.WrapContent), - text = message.map { it ?: "".desc() } - ) - val submitBtn = +button( - size = WidgetSize.Const(width = SizeSpec.MatchConstraint, height = SizeSpec.WrapContent), - content = ButtonWidget.Content.Text(Value.liveData(buttonText)), - onTap = onTap - ) - - constraints { - msg topToTop root - msg leftRightToLeftRight root - - submitBtn topToBottom msg offset 8 - submitBtn leftRightToLeftRight root - submitBtn bottomToBottom root - } -} From eff620dcb229ff44108f66c42dcdd6459141d3ca Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sat, 22 Feb 2020 22:58:03 +0700 Subject: [PATCH 27/48] #138 update flatAlert sample --- sample/mpp-library/src/commonMain/kotlin/App.kt | 6 ++++++ .../com/icerockdev/library/sample/StateSample.kt | 16 ++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/sample/mpp-library/src/commonMain/kotlin/App.kt b/sample/mpp-library/src/commonMain/kotlin/App.kt index 36098649..d8e183e2 100644 --- a/sample/mpp-library/src/commonMain/kotlin/App.kt +++ b/sample/mpp-library/src/commonMain/kotlin/App.kt @@ -19,6 +19,7 @@ import dev.icerock.moko.parcelize.Parcelable import dev.icerock.moko.parcelize.Parcelize import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.widgets.ButtonWidget +import dev.icerock.moko.widgets.FlatAlertIds import dev.icerock.moko.widgets.ImageWidget import dev.icerock.moko.widgets.InputWidget import dev.icerock.moko.widgets.TabsWidget @@ -33,6 +34,7 @@ import dev.icerock.moko.widgets.factory.LinearViewFactory import dev.icerock.moko.widgets.factory.SystemImageViewFactory import dev.icerock.moko.widgets.factory.SystemInputViewFactory import dev.icerock.moko.widgets.factory.SystemTabsViewFactory +import dev.icerock.moko.widgets.factory.SystemTextViewFactory import dev.icerock.moko.widgets.flat.FlatInputViewFactory import dev.icerock.moko.widgets.sample.InputWidgetGalleryScreen import dev.icerock.moko.widgets.sample.ScrollContentScreen @@ -60,6 +62,7 @@ import dev.icerock.moko.widgets.style.state.PressableState import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.style.view.MarginValues import dev.icerock.moko.widgets.style.view.PaddingValues +import dev.icerock.moko.widgets.style.view.TextHorizontalAlignment import dev.icerock.moko.widgets.style.view.TextStyle import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.utils.platformSpecific @@ -170,6 +173,9 @@ class App() : BaseApplication() { } val widgetsTheme = Theme(theme) { + factory[FlatAlertIds.Message] = SystemTextViewFactory( + textHorizontalAlignment = TextHorizontalAlignment.CENTER + ) factory[InputWidget.DefaultCategory] = SystemInputViewFactory( textStyle = TextStyle( size = 16, diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt index 78e500b2..e8f1c4b4 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/sample/StateSample.kt @@ -91,16 +91,12 @@ open class StateScreen( } private fun Theme.flatAlertWrapped(message: LiveData) = - container(size = WidgetSize.AsParent) { - center { - flatAlert( - size = WidgetSize.Const(width = SizeSpec.Exact(300f), height = SizeSpec.WrapContent), - message = message.map { it ?: "".desc() as StringDesc? }, - buttonText = const("press me".desc() as StringDesc?), - onTap = { println("pressed") } - ) - } - } + flatAlert( + size = WidgetSize.AsParent, + message = message.map { it ?: "".desc() as StringDesc? }, + buttonText = const("press me".desc() as StringDesc?), + onTap = { println("pressed") } + ) } interface StateViewModelContract { From 3f308387460d6c2195a08178ec9caf5958694fa1 Mon Sep 17 00:00:00 2001 From: Andrew Kovalev Date: Sat, 22 Feb 2020 23:10:59 +0700 Subject: [PATCH 28/48] #133 placeholder logic implementation moved to delegate --- .../factory/MultilineInputViewFactory.kt | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt index 21942f56..cfbdf1f3 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/factory/MultilineInputViewFactory.kt @@ -6,6 +6,7 @@ package dev.icerock.moko.widgets.factory import dev.icerock.moko.graphics.Color import dev.icerock.moko.graphics.toUIColor +import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.widgets.InputWidget import dev.icerock.moko.widgets.core.ViewBundle import dev.icerock.moko.widgets.core.ViewFactory @@ -45,8 +46,6 @@ actual class MultilineInputViewFactory actual constructor( private val textHorizontalAlignment: TextHorizontalAlignment? ) : ViewFactory> { - private var isPlaceholderShow: Boolean = false - override fun build( widget: InputWidget, size: WS, @@ -91,6 +90,7 @@ actual class MultilineInputViewFactory actual constructor( val textDelegate = TextViewDelegate( + isPlaceholderShow = widget.field.data.value.isEmpty(), textChangedHandler = { newValue -> val currentValue = widget.field.data.value @@ -98,25 +98,13 @@ actual class MultilineInputViewFactory actual constructor( widget.field.data.value = newValue } }, - didBeginEditHandler = { - if (isPlaceholderShow) { - textView.text = "" - textView.textColor = textStyle?.color?.toUIColor() ?: UIColor.blackColor - isPlaceholderShow = false - } - }, - didEndEditHandler = { - if (textView.text.isEmpty()) { - textView.text = widget.label.value.localized() - textView.textColor = labelTextColor?.toUIColor() ?: UIColor.grayColor - isPlaceholderShow = true - } - } + placeholderText = widget.label.value, + placeholderColor = labelTextColor, + textColor = textStyle?.color ) if (widget.label.value.localized().isNotEmpty()) { if (widget.field.data.value.isEmpty()) { - isPlaceholderShow = true textView.text = widget.label.value.localized() textView.textColor = labelTextColor?.toUIColor() ?: UIColor.grayColor } @@ -133,9 +121,11 @@ actual class MultilineInputViewFactory actual constructor( } private class TextViewDelegate( - private val textChangedHandler: (String) -> Unit, - private val didBeginEditHandler: (() -> Unit)?, - private val didEndEditHandler: (() -> Unit)? + private var isPlaceholderShow: Boolean, + private val placeholderColor: Color?, + private val textColor: Color?, + private val placeholderText: StringDesc?, + private val textChangedHandler: (String) -> Unit ) : NSObject(), UITextViewDelegateProtocol { override fun textViewDidChange(textView: UITextView) { @@ -143,11 +133,19 @@ actual class MultilineInputViewFactory actual constructor( } override fun textViewDidBeginEditing(textView: UITextView) { - didBeginEditHandler?.invoke() + if (isPlaceholderShow) { + textView.text = "" + textView.textColor = textColor?.toUIColor() ?: UIColor.blackColor + isPlaceholderShow = false + } } override fun textViewDidEndEditing(textView: UITextView) { - didEndEditHandler?.invoke() + if (textView.text.isEmpty()) { + textView.text = placeholderText?.localized() ?: "" + textView.textColor = placeholderColor?.toUIColor() ?: UIColor.grayColor + isPlaceholderShow = true + } } } } From d384d5dfdb0dc7e05ae0aa6412c4565def289b0e Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sun, 23 Feb 2020 12:33:17 +0700 Subject: [PATCH 29/48] #127 add fragment library dependency --- buildSrc/src/main/kotlin/Deps.kt | 3 +++ buildSrc/src/main/kotlin/Versions.kt | 1 + widgets/build.gradle.kts | 1 + 3 files changed, 5 insertions(+) diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt index a4b55dfe..434774ec 100755 --- a/buildSrc/src/main/kotlin/Deps.kt +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -18,6 +18,9 @@ object Deps { val appCompat = AndroidLibrary( name = "androidx.appcompat:appcompat:${Versions.Libs.Android.appCompat}" ) + val fragment = AndroidLibrary( + name = "androidx.fragment:fragment:${Versions.Libs.Android.fragment}" + ) val swipeRefreshLayout = AndroidLibrary( name = "androidx.swiperefreshlayout:swiperefreshlayout:${Versions.Libs.Android.swipeRefreshLayout}" ) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 2efe49e6..2c7d017e 100755 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -21,6 +21,7 @@ object Versions { object Libs { object Android { const val appCompat = "1.1.0" + const val fragment = "1.2.2" const val swipeRefreshLayout = "1.0.0" const val material = "1.1.0" const val constraintLayout = "1.1.3" diff --git a/widgets/build.gradle.kts b/widgets/build.gradle.kts index f4fb51a5..7fbea83f 100644 --- a/widgets/build.gradle.kts +++ b/widgets/build.gradle.kts @@ -38,6 +38,7 @@ dependencies { mppLibrary(Deps.Libs.MultiPlatform.mokoParcelize) androidLibrary(Deps.Libs.Android.appCompat) + androidLibrary(Deps.Libs.Android.fragment) androidLibrary(Deps.Libs.Android.recyclerView) androidLibrary(Deps.Libs.Android.material) androidLibrary(Deps.Libs.Android.swipeRefreshLayout) From 7ad94043bcfd7977404356bceb094e51a4cf4b2b Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sun, 23 Feb 2020 12:33:35 +0700 Subject: [PATCH 30/48] #127 replace FrameLayout to FragmentContainerView --- .../moko/widgets/screen/navigation/BottomNavigationScreen.kt | 3 ++- .../moko/widgets/screen/navigation/NavigationScreen.kt | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt index 11ad0b20..48afeb1e 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt @@ -17,6 +17,7 @@ import androidx.activity.OnBackPressedCallback import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.FragmentManager import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.LabelVisibilityMode @@ -110,7 +111,7 @@ actual abstract class BottomNavigationScreen actual constructor( savedInstanceState: Bundle? ): android.view.View? { val context = requireContext() - val root = FrameLayout(context).apply { + val root = FragmentContainerView(context).apply { id = android.R.id.content } val bottomNavigation = BottomNavigationView(context).apply { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index 2c28b824..12506b9f 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -22,6 +22,8 @@ import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentContainer +import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.FragmentManager import dev.icerock.moko.parcelize.Parcelable import dev.icerock.moko.widgets.core.View @@ -126,7 +128,7 @@ actual abstract class NavigationScreen actual constructor( savedInstanceState: Bundle? ): android.view.View? { val context = requireContext() - val root = FrameLayout(context).apply { + val root = FragmentContainerView(context).apply { id = android.R.id.content } val toolbar = Toolbar(context).apply { From 7c6aa73fbed289f3ef93cee41b9d2dd9508e3ba8 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Sun, 23 Feb 2020 12:36:04 +0700 Subject: [PATCH 31/48] #127 reformat --- .../moko/widgets/screen/navigation/NavigationScreen.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index 12506b9f..4771f677 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -14,7 +14,6 @@ import android.text.style.StyleSpan import android.view.LayoutInflater import android.view.MenuItem import android.view.ViewGroup -import android.widget.FrameLayout import android.widget.LinearLayout import androidx.activity.OnBackPressedCallback import androidx.appcompat.widget.Toolbar @@ -22,7 +21,6 @@ import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentContainer import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.FragmentManager import dev.icerock.moko.parcelize.Parcelable @@ -360,7 +358,7 @@ actual abstract class NavigationScreen actual constructor( return object : Route { override fun route(arg: Unit) { val fragmentManager = navigationScreen!!.getChildFragmentManager() - for(i in 0 until fragmentManager.backStackEntryCount) { + for (i in 0 until fragmentManager.backStackEntryCount) { fragmentManager.popBackStack() } } From ccaf360c13df0d34c0fc0fd60b76b93a4263c99c Mon Sep 17 00:00:00 2001 From: Aleksandr Gusev Date: Mon, 24 Feb 2020 13:06:18 +0700 Subject: [PATCH 32/48] #100, Added searchViewController. Removed swift and xib files --- .../iosMain/bundle/SearchViewController.xib | 39 ------------- .../moko/widgets/screen/SearchScreen.kt | 55 ++++++++++++++++++- .../widgets/screen/SearchViewController.kt | 34 ++++++++++++ .../iosMain/swift/SearchViewController.swift | 40 -------------- 4 files changed, 87 insertions(+), 81 deletions(-) delete mode 100644 widgets/src/iosMain/bundle/SearchViewController.xib create mode 100644 widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt delete mode 100644 widgets/src/iosMain/swift/SearchViewController.swift diff --git a/widgets/src/iosMain/bundle/SearchViewController.xib b/widgets/src/iosMain/bundle/SearchViewController.xib deleted file mode 100644 index 32fc1c91..00000000 --- a/widgets/src/iosMain/bundle/SearchViewController.xib +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index c0dbbd4c..4e13657e 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -3,9 +3,60 @@ package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.ListWidget +import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.core.ViewBundle +import dev.icerock.moko.widgets.core.ViewFactoryContext +import dev.icerock.moko.widgets.factory.SystemListViewFactory +import dev.icerock.moko.widgets.style.view.WidgetSize +import kotlinx.cinterop.readValue +import platform.CoreGraphics.CGRectZero +import platform.UIKit.translatesAutoresizingMaskIntoConstraints +import platform.UIKit.UIViewController +import platform.UIKit.UIView - -actual abstract class SearchScreen: Screen() { +actual abstract class SearchScreen ( + theme: Theme, + size: WidgetSize, + id: ListWidget.Id +) : Screen() { actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> + + override fun createViewController(isLightStatusBar: Boolean?): UIViewController { + return SearchViewController(isLightStatusBar) + } + + var listWidget = ListWidget( + factory = theme.factory.get( + id = id, + category = ListWidget.DefaultCategory, + defaultCategory = ListWidget.DefaultCategory, + fallback = { SystemListViewFactory() } + ), + size = size, + id = id, + items = searchItems, + onReachEnd = null, + onRefresh = null + ) + + fun build( + widget: ListWidget, + size: WS, + viewFactoryContext: ViewFactoryContext + ): ViewBundle { + val viewController: UIViewController = viewFactoryContext + + val container = UIView(frame = CGRectZero.readValue()).apply { + translatesAutoresizingMaskIntoConstraints = false + } + + return ViewBundle( + view = container, + size = size, + margins = null + ) + } + } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt new file mode 100644 index 00000000..34c7dc4a --- /dev/null +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt @@ -0,0 +1,34 @@ +package dev.icerock.moko.widgets.screen + +import kotlinx.cinterop.ExportObjCClass +import platform.UIKit.* + +@ExportObjCClass +class SearchViewController( + private val isLightStatusBar: Boolean? +) : UIViewController(nibName = null, bundle = null), UISearchResultsUpdatingProtocol { + var navItem: UINavigationItem? = null + + override fun viewDidLoad() { + super.viewDidLoad() + setupSearchController() + } + + fun setupSearchController() { + navItem = UINavigationItem(title = "SearchViewController") + val searchController = UISearchController(searchResultsController = null) + // Setup the Search Controller + searchController.searchResultsUpdater = this + searchController.obscuresBackgroundDuringPresentation = false + searchController.searchBar.placeholder = "Search" + navItem!!.searchController = searchController + definesPresentationContext = true + + val searchField = searchController.searchBar.searchTextField + searchField.textColor = UIColor.redColor + } + + override fun updateSearchResultsForSearchController(searchController: UISearchController) { + print("\n updateSearchResults \n") + } +} diff --git a/widgets/src/iosMain/swift/SearchViewController.swift b/widgets/src/iosMain/swift/SearchViewController.swift deleted file mode 100644 index 597ea5f7..00000000 --- a/widgets/src/iosMain/swift/SearchViewController.swift +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. -*/ - -import UIKit - -@objc public class SearchViewController: UIViewController { - @IBOutlet weak var navItem: UINavigationItem! - - @objc public static func create() -> SearchViewController { - return SearchViewController( - nibName: nil, - bundle: Bundle(for: SearchViewController.self) - ) - } - - func setupSearchController() { - let searchController = UISearchController(searchResultsController: nil) - // Setup the Search Controller - searchController.searchResultsUpdater = self - searchController.obscuresBackgroundDuringPresentation = false - searchController.searchBar.placeholder = "Search" - navItem.searchController = searchController - definesPresentationContext = true - - let searchField = searchController.searchBar.searchTextField - searchField.textColor = UIColor.red - - //tableView.tableHeaderView = searchController.searchBar - } -} - -// MARK: - UISearchResultsUpdating Delegate -extension SearchViewController: UISearchResultsUpdating { - - public func updateSearchResults(for searchController: UISearchController) { - print("\n updateSearchResults \n") - } -} - From 4c0a4e466f8c4d6426fd523686a783533c1ba2cc Mon Sep 17 00:00:00 2001 From: Aleksandr Gusev Date: Mon, 24 Feb 2020 14:37:15 +0700 Subject: [PATCH 33/48] #100, Fixed actual declaration of SearchScreen --- .../dev/icerock/moko/widgets/screen/SearchScreen.kt | 8 +++++++- .../dev/icerock/moko/widgets/screen/SearchScreen.kt | 8 +++++++- .../dev/icerock/moko/widgets/screen/SearchScreen.kt | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 2cd33c77..1eec267a 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -3,9 +3,15 @@ package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.ListWidget import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.style.view.WidgetSize -actual abstract class SearchScreen: Screen() { +actual abstract class SearchScreen actual constructor( + theme: Theme, + size: WidgetSize, + id: ListWidget.Id +) : Screen() { actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> } diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 51e74bb3..34eadc71 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -3,10 +3,16 @@ package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.ListWidget import dev.icerock.moko.widgets.core.Theme import dev.icerock.moko.widgets.screen.navigation.Route +import dev.icerock.moko.widgets.style.view.WidgetSize -expect abstract class SearchScreen: Screen { +expect abstract class SearchScreen( + theme: Theme, + size: WidgetSize, + id: ListWidget.Id +): Screen { abstract val searchQuery: MutableLiveData abstract val searchItems: LiveData> } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 4e13657e..763ec704 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -15,7 +15,7 @@ import platform.UIKit.translatesAutoresizingMaskIntoConstraints import platform.UIKit.UIViewController import platform.UIKit.UIView -actual abstract class SearchScreen ( +actual abstract class SearchScreen actual constructor( theme: Theme, size: WidgetSize, id: ListWidget.Id From 6e4685bf43a3dd2fc34b1e0038fa90c86174e154 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Mon, 24 Feb 2020 21:50:41 +0700 Subject: [PATCH 34/48] #100 search screen iOS implementation --- .../moko/widgets/screen/SearchScreen.kt | 15 ++-- .../moko/widgets/screen/SearchScreen.kt | 16 ++-- .../moko/widgets/screen/SearchScreen.kt | 60 +++------------ .../widgets/screen/SearchViewController.kt | 77 ++++++++++++++++--- 4 files changed, 91 insertions(+), 77 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 1eec267a..27f435dd 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -1,17 +1,16 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem -import dev.icerock.moko.widgets.ListWidget -import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.style.view.WidgetSize -actual abstract class SearchScreen actual constructor( - theme: Theme, - size: WidgetSize, - id: ListWidget.Id -) : Screen() { +actual abstract class SearchScreen : Screen() { + actual abstract val searchPlaceholder: StringDesc actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> } diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 34eadc71..60b74bea 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -1,18 +1,16 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem -import dev.icerock.moko.widgets.ListWidget -import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.screen.navigation.Route -import dev.icerock.moko.widgets.style.view.WidgetSize -expect abstract class SearchScreen( - theme: Theme, - size: WidgetSize, - id: ListWidget.Id -): Screen { +expect abstract class SearchScreen() : Screen { + abstract val searchPlaceholder: StringDesc abstract val searchQuery: MutableLiveData abstract val searchItems: LiveData> } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 763ec704..d65c6f14 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -1,62 +1,26 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem -import dev.icerock.moko.widgets.ListWidget -import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.core.ViewBundle -import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.factory.SystemListViewFactory -import dev.icerock.moko.widgets.style.view.WidgetSize -import kotlinx.cinterop.readValue -import platform.CoreGraphics.CGRectZero -import platform.UIKit.translatesAutoresizingMaskIntoConstraints import platform.UIKit.UIViewController -import platform.UIKit.UIView -actual abstract class SearchScreen actual constructor( - theme: Theme, - size: WidgetSize, - id: ListWidget.Id -) : Screen() { +actual abstract class SearchScreen : Screen() { + actual abstract val searchPlaceholder: StringDesc actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> override fun createViewController(isLightStatusBar: Boolean?): UIViewController { - return SearchViewController(isLightStatusBar) - } - - var listWidget = ListWidget( - factory = theme.factory.get( - id = id, - category = ListWidget.DefaultCategory, - defaultCategory = ListWidget.DefaultCategory, - fallback = { SystemListViewFactory() } - ), - size = size, - id = id, - items = searchItems, - onReachEnd = null, - onRefresh = null - ) - - fun build( - widget: ListWidget, - size: WS, - viewFactoryContext: ViewFactoryContext - ): ViewBundle { - val viewController: UIViewController = viewFactoryContext - - val container = UIView(frame = CGRectZero.readValue()).apply { - translatesAutoresizingMaskIntoConstraints = false - } - - return ViewBundle( - view = container, - size = size, - margins = null + return SearchViewController( + isLightStatusBar = isLightStatusBar, + searchQuery = searchQuery, + searchItems = searchItems, + searchPlaceholder = searchPlaceholder ) } - } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt index 34c7dc4a..59a39186 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt @@ -1,34 +1,87 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + package dev.icerock.moko.widgets.screen -import kotlinx.cinterop.ExportObjCClass -import platform.UIKit.* +import dev.icerock.moko.mvvm.livedata.LiveData +import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.units.UnitTableViewDataSource +import dev.icerock.moko.widgets.utils.bind +import dev.icerock.moko.widgets.utils.getStatusBarStyle +import dev.icerock.moko.widgets.utils.setEventHandler +import kotlinx.cinterop.readValue +import platform.CoreGraphics.CGRectZero +import platform.UIKit.UIControlEventValueChanged +import platform.UIKit.UISearchController +import platform.UIKit.UISearchResultsUpdatingProtocol +import platform.UIKit.UIStatusBarStyle +import platform.UIKit.UITableView +import platform.UIKit.UIViewController +import platform.UIKit.addSubview +import platform.UIKit.bottomAnchor +import platform.UIKit.leadingAnchor +import platform.UIKit.navigationItem +import platform.UIKit.searchTextField +import platform.UIKit.topAnchor +import platform.UIKit.trailingAnchor +import platform.UIKit.translatesAutoresizingMaskIntoConstraints -@ExportObjCClass class SearchViewController( - private val isLightStatusBar: Boolean? + private val isLightStatusBar: Boolean?, + private val searchQuery: MutableLiveData, + private val searchItems: LiveData>, + private val searchPlaceholder: StringDesc ) : UIViewController(nibName = null, bundle = null), UISearchResultsUpdatingProtocol { - var navItem: UINavigationItem? = null + + private lateinit var unitsDataSource: UnitTableViewDataSource override fun viewDidLoad() { super.viewDidLoad() + setupSearchController() + setupTableView() } - fun setupSearchController() { - navItem = UINavigationItem(title = "SearchViewController") + private fun setupSearchController() { val searchController = UISearchController(searchResultsController = null) // Setup the Search Controller searchController.searchResultsUpdater = this searchController.obscuresBackgroundDuringPresentation = false - searchController.searchBar.placeholder = "Search" - navItem!!.searchController = searchController + searchController.searchBar.placeholder = searchPlaceholder.localized() + + navigationItem.searchController = searchController + definesPresentationContext = true + } - val searchField = searchController.searchBar.searchTextField - searchField.textColor = UIColor.redColor + private fun setupTableView() { + val tableView = UITableView(frame = CGRectZero.readValue()).apply { + translatesAutoresizingMaskIntoConstraints = false + } + + unitsDataSource = UnitTableViewDataSource(tableView = tableView) + + searchItems.bind { unitsDataSource.unitItems = it } + + with(view) { + addSubview(tableView) + + leadingAnchor.constraintEqualToAnchor(tableView.leadingAnchor).active = true + tableView.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true + topAnchor.constraintEqualToAnchor(tableView.topAnchor).active = true + tableView.bottomAnchor.constraintEqualToAnchor(bottomAnchor).active = true + } } override fun updateSearchResultsForSearchController(searchController: UISearchController) { - print("\n updateSearchResults \n") + searchQuery.value = searchController.searchBar.text.orEmpty() + } + + override fun preferredStatusBarStyle(): UIStatusBarStyle { + val isLight = isLightStatusBar ?: application.isLightStatusBar + return getStatusBarStyle(isLight) ?: super.preferredStatusBarStyle() } } From 0c88efeec4b3d3ab3c4d48e362c01ea4d55d201f Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Mon, 24 Feb 2020 21:50:51 +0700 Subject: [PATCH 35/48] #100 add sample --- .../mpp-library/src/commonMain/kotlin/App.kt | 18 ++++- .../widgets/sample/ProductsSearchScreen.kt | 69 +++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt diff --git a/sample/mpp-library/src/commonMain/kotlin/App.kt b/sample/mpp-library/src/commonMain/kotlin/App.kt index d8e183e2..e596b7bd 100644 --- a/sample/mpp-library/src/commonMain/kotlin/App.kt +++ b/sample/mpp-library/src/commonMain/kotlin/App.kt @@ -37,6 +37,7 @@ import dev.icerock.moko.widgets.factory.SystemTabsViewFactory import dev.icerock.moko.widgets.factory.SystemTextViewFactory import dev.icerock.moko.widgets.flat.FlatInputViewFactory import dev.icerock.moko.widgets.sample.InputWidgetGalleryScreen +import dev.icerock.moko.widgets.sample.ProductsSearchScreen import dev.icerock.moko.widgets.sample.ScrollContentScreen import dev.icerock.moko.widgets.sample.SelectGalleryScreen import dev.icerock.moko.widgets.screen.Args @@ -104,6 +105,7 @@ class App() : BaseApplication() { theme = theme, routes = listOf( buildInputGalleryRouteInfo(theme, router), + buildSearchRouteInfo(theme, router), SelectGalleryScreen.RouteInfo( name = "Old Demo".desc(), route = router.createPushRoute(oldDemo(router)) @@ -142,7 +144,21 @@ class App() : BaseApplication() { ) } - fun oldDemo( + private fun buildSearchRouteInfo( + theme: Theme, + router: NavigationScreen.Router + ): SelectGalleryScreen.RouteInfo { + val searchScreen = registerScreen(ProductsSearchScreen::class) { + ProductsSearchScreen(theme) + } + + return SelectGalleryScreen.RouteInfo( + name = "SearchScreen".desc(), + route = router.createPushRoute(searchScreen) + ) + } + + private fun oldDemo( router: NavigationScreen.Router ): TypedScreenDesc { val sharedFactory = SharedFactory() diff --git a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt new file mode 100644 index 00000000..62a21a9f --- /dev/null +++ b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.sample + +import dev.icerock.moko.graphics.Color +import dev.icerock.moko.mvvm.livedata.LiveData +import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.mvvm.livedata.map +import dev.icerock.moko.resources.desc.StringDesc +import dev.icerock.moko.resources.desc.desc +import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.constraint +import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.screen.Args +import dev.icerock.moko.widgets.screen.SearchScreen +import dev.icerock.moko.widgets.screen.navigation.NavigationBar +import dev.icerock.moko.widgets.screen.navigation.NavigationItem +import dev.icerock.moko.widgets.style.view.WidgetSize +import dev.icerock.moko.widgets.text +import dev.icerock.moko.widgets.units.UnitItemRoot +import dev.icerock.moko.widgets.units.WidgetsTableUnitItem + +class ProductsSearchScreen( + private val theme: Theme +) : SearchScreen(), NavigationItem { + + override val navigationBar: NavigationBar = NavigationBar.Normal( + title = "Products search".desc(), + styles = NavigationBar.Normal.Styles(backgroundColor = Color(0xAA3333FF)) + ) + + private val products: List = List(size = 50) { "It's product $it" } + + override val searchQuery: MutableLiveData = MutableLiveData(initialValue = "") + override val searchItems: LiveData> = searchQuery.map { query -> + products + .filter { it.contains(query) } + .map { ProductUnitItem(theme, itemId = it.hashCode().toLong(), data = it) } + } + + class ProductUnitItem( + private val theme: Theme, + itemId: Long, + data: String + ) : WidgetsTableUnitItem(itemId, data) { + override val reuseId: String = "ProductUnitItem" + + override fun createWidget(data: LiveData): UnitItemRoot { + return with(theme) { + constraint( + size = WidgetSize.WidthAsParentHeightWrapContent + ) { + val title = +text( + size = WidgetSize.WidthAsParentHeightWrapContent, + text = data.map { it.desc() as StringDesc } + ) + + constraints { + title topToTop root offset 8 + title leftRightToLeftRight root offset 16 + title bottomToBottom root + } + } + }.let { UnitItemRoot.from(it) } + } + } +} From bc7fa23f3fe9d7b80922f37c630bacefbcfe2cfb Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 09:50:17 +0700 Subject: [PATCH 36/48] removed ApplicationHolder from iOS side --- sample/ios-app/src/AppDelegate.swift | 1 - .../dev/icerock/moko/widgets/screen/BaseApplication.kt | 7 +++++++ .../dev/icerock/moko/widgets/screen/ApplicationHolder.kt | 9 --------- .../icerock/moko/widgets/screen/WidgetViewController.kt | 2 +- .../widgets/screen/navigation/BottomNavigationScreen.kt | 4 ++-- .../moko/widgets/screen/navigation/NavigationScreen.kt | 4 ++-- 6 files changed, 12 insertions(+), 15 deletions(-) delete mode 100644 widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ApplicationHolder.kt diff --git a/sample/ios-app/src/AppDelegate.swift b/sample/ios-app/src/AppDelegate.swift index 9acd058b..7b4577ee 100755 --- a/sample/ios-app/src/AppDelegate.swift +++ b/sample/ios-app/src/AppDelegate.swift @@ -14,7 +14,6 @@ class AppDelegate: NSObject, UIApplicationDelegate { let app = App() app.initialize() - ApplicationHolderKt.application = app let screen = app.rootScreen.instantiate() let rootViewController = screen.viewController diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/BaseApplication.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/BaseApplication.kt index 9a825317..2faa921c 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/BaseApplication.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/BaseApplication.kt @@ -5,6 +5,7 @@ package dev.icerock.moko.widgets.screen import dev.icerock.moko.graphics.Color +import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass abstract class BaseApplication { @@ -21,6 +22,7 @@ abstract class BaseApplication { fun initialize() { rootScreen = setup() + sharedInstance = this } fun > registerScreen( @@ -29,4 +31,9 @@ abstract class BaseApplication { ): TypedScreenDesc = TypedScreenDesc(factory).also { _registeredScreens[kClass] = it } + + @ThreadLocal + companion object { + lateinit var sharedInstance: BaseApplication + } } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ApplicationHolder.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ApplicationHolder.kt deleted file mode 100644 index e264557c..00000000 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ApplicationHolder.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.screen - -// correct DI for screens require large refactoring, so we just save singleton reference on application -// it's should be set from ios swift code -lateinit var application: BaseApplication \ No newline at end of file diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/WidgetViewController.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/WidgetViewController.kt index 50714608..5ecb11b8 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/WidgetViewController.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/WidgetViewController.kt @@ -160,7 +160,7 @@ class WidgetViewController( } override fun preferredStatusBarStyle(): UIStatusBarStyle { - val light = isLightStatusBar ?: application.isLightStatusBar + val light = isLightStatusBar ?: BaseApplication.sharedInstance.isLightStatusBar return getStatusBarStyle(light) ?: super.preferredStatusBarStyle() } } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt index 7d9f4f8b..1d6ea4d6 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/BottomNavigationScreen.kt @@ -7,8 +7,8 @@ package dev.icerock.moko.widgets.screen.navigation import dev.icerock.moko.graphics.Color import dev.icerock.moko.graphics.toUIColor import dev.icerock.moko.widgets.screen.Args +import dev.icerock.moko.widgets.screen.BaseApplication import dev.icerock.moko.widgets.screen.Screen -import dev.icerock.moko.widgets.screen.application import dev.icerock.moko.widgets.style.state.SelectableState import dev.icerock.moko.widgets.utils.getStatusBarStyle import platform.UIKit.UIStatusBarStyle @@ -104,7 +104,7 @@ private class TabBarController( ) : UITabBarController(nibName = null, bundle = null) { override fun preferredStatusBarStyle(): UIStatusBarStyle { - val light = isLightStatusBar ?: application.isLightStatusBar + val light = isLightStatusBar ?: BaseApplication.sharedInstance.isLightStatusBar return getStatusBarStyle(light) ?: super.preferredStatusBarStyle() } } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index f3ec2715..5bb5fa17 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -6,9 +6,9 @@ package dev.icerock.moko.widgets.screen.navigation import dev.icerock.moko.parcelize.Parcelable import dev.icerock.moko.widgets.screen.Args +import dev.icerock.moko.widgets.screen.BaseApplication import dev.icerock.moko.widgets.screen.Screen import dev.icerock.moko.widgets.screen.TypedScreenDesc -import dev.icerock.moko.widgets.screen.application import dev.icerock.moko.widgets.screen.getAssociatedScreen import dev.icerock.moko.widgets.style.applyNavigationBarStyle import dev.icerock.moko.widgets.utils.getStatusBarStyle @@ -192,7 +192,7 @@ private class NavigationController( override fun preferredStatusBarStyle(): UIStatusBarStyle { val topScreen = topViewController?.getAssociatedScreen() - val isLight = topScreen?.isLightStatusBar ?: isLightStatusBar ?: application.isLightStatusBar + val isLight = topScreen?.isLightStatusBar ?: isLightStatusBar ?: BaseApplication.sharedInstance.isLightStatusBar return getStatusBarStyle(isLight) ?: super.preferredStatusBarStyle() } } From 6be9ee76199a504d17ec26b1b7b56e7759a9a04b Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 10:08:22 +0700 Subject: [PATCH 37/48] #100 fix sample --- .../dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt index 62a21a9f..b2799236 100644 --- a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt +++ b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt @@ -33,6 +33,7 @@ class ProductsSearchScreen( private val products: List = List(size = 50) { "It's product $it" } + override val searchPlaceholder: StringDesc = "Search".desc() override val searchQuery: MutableLiveData = MutableLiveData(initialValue = "") override val searchItems: LiveData> = searchQuery.map { query -> products From 4ecd81c2614910d9d982deef9e082d21727b8165 Mon Sep 17 00:00:00 2001 From: Andrey Dorofeev Date: Tue, 25 Feb 2020 10:15:29 +0700 Subject: [PATCH 38/48] #90 added date picker for ios --- .../widgets/screen/DatePickerDialogHandler.kt | 5 + .../moko/widgets/screen/ShowDatePickerExt.kt | 1 + .../moko/widgets/screen/ShowDatePickerExt.kt | 214 +++++++++++++++++- 3 files changed, 216 insertions(+), 4 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt index 213caafd..db3dd409 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt @@ -58,6 +58,7 @@ actual class DatePickerDialogBuilder( ) { private var startDate: DateTime? = null private var endDate: DateTime? = null + private var selectedDate: DateTime? = null actual fun accentColor(color: Color) { //android color from style @@ -71,6 +72,10 @@ actual class DatePickerDialogBuilder( endDate = date } + actual fun selectedDate(date: DateTime) { + selectedDate = date + } + internal fun show() { val alertDialogFragment = DatePickerDialogFragment.instantiate( diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index 03ed1eea..fd4f6fd7 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -19,6 +19,7 @@ expect class DatePickerDialogBuilder { fun accentColor(color: Color) fun startDate(date: DateTime) fun endDate(date: DateTime) + fun selectedDate(date: DateTime) } expect fun Screen<*>.showDatePickerDialog( diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index 4939e84d..5ea557f1 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -3,30 +3,85 @@ */ package dev.icerock.moko.widgets.screen - import com.soywiz.klock.DateTime import dev.icerock.moko.graphics.Color +import dev.icerock.moko.graphics.toUIColor +import dev.icerock.moko.widgets.utils.setEventHandler import kotlin.properties.ReadOnlyProperty +import platform.UIKit.UIModalPresentationOverCurrentContext +import platform.UIKit.UIViewController +import platform.UIKit.UIColor +import platform.UIKit.UIView +import platform.UIKit.translatesAutoresizingMaskIntoConstraints +import platform.UIKit.backgroundColor +import platform.UIKit.addSubview +import platform.UIKit.leadingAnchor +import platform.UIKit.trailingAnchor +import platform.UIKit.bottomAnchor +import platform.UIKit.UIDatePicker +import platform.UIKit.UIDatePickerMode +import platform.UIKit.safeAreaLayoutGuide +import platform.UIKit.heightAnchor +import platform.UIKit.topAnchor +import platform.UIKit.UIButton +import platform.UIKit.UIControlStateNormal +import platform.UIKit.UIControlEventTouchUpInside +import platform.Foundation.NSBundle +import platform.Foundation.NSDate -actual class DatePickerDialogHandler +actual class DatePickerDialogHandler( + val positive: ((dialogId: Int, date: DateTime) -> Unit)?, + val negative: ((dialogId: Int) -> Unit)? +) actual fun Screen<*>.registerDatePickerDialogHandler( positive: ((dialogId: Int, date: DateTime) -> Unit)?, negative: ((dialogId: Int) -> Unit)? ): ReadOnlyProperty, DatePickerDialogHandler> { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + val handler = DatePickerDialogHandler( + positive = positive, + negative = negative + ) + return createConstReadOnlyProperty(handler) } actual class DatePickerDialogBuilder { + private var accentColor: Color? = null + private var startDate: DateTime? = null + private var endDate: DateTime? = null + private var selectedDate: DateTime? = null + actual fun accentColor(color: Color) { + accentColor = color } actual fun startDate(date: DateTime) { + startDate = date } actual fun endDate(date: DateTime) { + endDate = date + } + + actual fun selectedDate(date: DateTime) { + selectedDate = date + } + + fun createViewController( + handler: DatePickerDialogHandler, + dialogId: Int + ): DatePickerController { + return DatePickerController( + accentColor = accentColor, + startDate = startDate, + endDate = endDate, + selectedDate = selectedDate, + handler = handler, + dialogId = dialogId + ) } + } actual fun Screen<*>.showDatePickerDialog( @@ -34,5 +89,156 @@ actual fun Screen<*>.showDatePickerDialog( handler: DatePickerDialogHandler, factory: DatePickerDialogBuilder.() -> Unit ) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + val builder = DatePickerDialogBuilder() + factory(builder) + val controller = builder.createViewController(handler = handler, dialogId = dialogId) + controller.modalPresentationStyle = UIModalPresentationOverCurrentContext + this.viewController.presentViewController(controller, animated = true, completion = null) } + +class DatePickerController( + private val accentColor: Color?, + private val startDate: DateTime?, + private val endDate: DateTime?, + private val selectedDate: DateTime?, + private val handler: DatePickerDialogHandler, + private val dialogId: Int +) : UIViewController(nibName = null, bundle = null) { + override fun viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = UIColor.blackColor.colorWithAlphaComponent(0.7) + + val pickerBackground = UIView() + view.addSubview(pickerBackground) + pickerBackground.translatesAutoresizingMaskIntoConstraints = false + pickerBackground.backgroundColor = UIColor.whiteColor + pickerBackground.leadingAnchor.constraintEqualToAnchor( + anchor = view.leadingAnchor + ).active = true + pickerBackground.trailingAnchor.constraintEqualToAnchor( + anchor = view.trailingAnchor + ).active = true + pickerBackground.bottomAnchor.constraintEqualToAnchor( + anchor = view.bottomAnchor + ).active = true + + val datePicker = UIDatePicker() + datePicker.translatesAutoresizingMaskIntoConstraints = false + datePicker.datePickerMode = UIDatePickerMode.UIDatePickerModeDate + view.addSubview(datePicker) + datePicker.leadingAnchor.constraintEqualToAnchor( + anchor = view.leadingAnchor + ).active = true + datePicker.trailingAnchor.constraintEqualToAnchor( + anchor = view.trailingAnchor + ).active = true + datePicker.bottomAnchor.constraintEqualToAnchor( + anchor = view.safeAreaLayoutGuide.bottomAnchor + ).active = true + datePicker.heightAnchor.constraintEqualToConstant(232.0) + + + pickerBackground.topAnchor.constraintEqualToAnchor( + anchor = datePicker.topAnchor + ).active = true + + + val controlPanel = UIView() + controlPanel.translatesAutoresizingMaskIntoConstraints = false + controlPanel.backgroundColor = UIColor(red = 0.97, green = 0.97, blue = 0.97, alpha = 1.0) + view.addSubview(controlPanel) + controlPanel.leadingAnchor.constraintEqualToAnchor( + anchor = view.leadingAnchor + ).active = true + controlPanel.trailingAnchor.constraintEqualToAnchor( + anchor = view.trailingAnchor + ).active = true + controlPanel.bottomAnchor.constraintEqualToAnchor( + anchor = datePicker.topAnchor + ).active = true + controlPanel.heightAnchor.constraintEqualToConstant(44.0) + + val bundle = NSBundle.bundleWithIdentifier("com.apple.UIKit") + val doneButton = UIButton() + doneButton.translatesAutoresizingMaskIntoConstraints = false + doneButton.setTitle( + title = bundle?.localizedStringForKey( + key = "Done", + value = "", + table = null + ) ?: "Done", + forState = UIControlStateNormal + ) + if (accentColor != null) { + doneButton.setTitleColor(accentColor.toUIColor(), UIControlStateNormal) + } + controlPanel.addSubview(doneButton) + doneButton.trailingAnchor.constraintEqualToAnchor( + anchor = controlPanel.trailingAnchor, + constant = -16.0 + ).active = true + doneButton.bottomAnchor.constraintEqualToAnchor( + anchor = controlPanel.bottomAnchor + ).active = true + doneButton.topAnchor.constraintEqualToAnchor( + anchor = controlPanel.topAnchor + ).active = true + + val cancelButton = UIButton() + cancelButton.translatesAutoresizingMaskIntoConstraints = false + cancelButton.setTitle( + title = bundle?.localizedStringForKey( + key = "Cancel", + value = "", + table = null + ) ?: "Cancel", + forState = UIControlStateNormal + ) + if (accentColor != null) { + cancelButton.setTitleColor(accentColor.toUIColor(), UIControlStateNormal) + } + controlPanel.addSubview(cancelButton) + cancelButton.leadingAnchor.constraintEqualToAnchor( + anchor = controlPanel.leadingAnchor, + constant = 16.0 + ).active = true + cancelButton.bottomAnchor.constraintEqualToAnchor( + anchor = controlPanel.bottomAnchor + ).active = true + cancelButton.topAnchor.constraintEqualToAnchor( + anchor = controlPanel.topAnchor + ).active = true + + val nsDate = NSDate() + val date = DateTime.nowUnix() + val diffDate = date - nsDate.timeIntervalSinceReferenceDate + + if (startDate != null) { + startDate.unixMillis + datePicker.minimumDate = NSDate(startDate.unixMillis - diffDate) + } + + if (endDate != null) { + endDate.unixMillis + datePicker.maximumDate = NSDate(endDate.unixMillis - diffDate) + } + + if (selectedDate != null) { + datePicker.setDate(NSDate(selectedDate.unixMillis - diffDate)) + } + + doneButton.setEventHandler(UIControlEventTouchUpInside) { + this.dismissViewControllerAnimated(flag = true, completion = null) + handler.positive?.invoke( + dialogId, + DateTime(diffDate + datePicker.date.timeIntervalSinceReferenceDate) + ) + } + cancelButton.setEventHandler(UIControlEventTouchUpInside) { + this.dismissViewControllerAnimated(flag = true, completion = null) + handler.negative?.invoke(dialogId) + } + } + +} \ No newline at end of file From ce151bab3497a8011fd4c38413abc478b220edc8 Mon Sep 17 00:00:00 2001 From: alobynya Date: Tue, 25 Feb 2020 10:35:51 +0700 Subject: [PATCH 39/48] #100 android search screen --- .../moko/widgets/screen/SearchScreen.kt | 66 ++++++++++++++++--- .../moko/widgets/screen/SearchScreen.kt | 13 +++- .../moko/widgets/screen/SearchScreen.kt | 7 +- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index cf046e3e..60df1d09 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -1,30 +1,39 @@ package dev.icerock.moko.widgets.screen import android.graphics.Color +import android.os.Build import android.os.Bundle +import android.util.TypedValue +import android.view.Gravity import android.view.LayoutInflater import android.view.ViewGroup +import android.widget.ImageView import android.widget.LinearLayout import android.widget.SearchView import androidx.cardview.widget.CardView +import dev.icerock.moko.graphics.colorInt import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem import dev.icerock.moko.widgets.ListWidget +import dev.icerock.moko.widgets.core.Image import dev.icerock.moko.widgets.core.Theme import dev.icerock.moko.widgets.core.ViewFactoryContext import dev.icerock.moko.widgets.list +import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded +import dev.icerock.moko.widgets.style.background.Background import dev.icerock.moko.widgets.style.view.WidgetSize + actual abstract class SearchScreen actual constructor() : Screen() { actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> - actual open val theme: Theme? = null - actual open val listCategory: ListWidget.Category? = null actual abstract fun onReachEnd() - open val searchHint: StringDesc? = null + actual open val searchHint: StringDesc? = null + actual open val background: Background? = null + actual open val androidBackItem: Image? = null override fun onCreateView( inflater: LayoutInflater, @@ -36,9 +45,47 @@ actual abstract class SearchScreen actual constructor() : Screen() rootLayout.orientation = LinearLayout.VERTICAL context?.let { context -> - val cardView = CardView(context) + + val searchContainer = LinearLayout(context) + searchContainer.orientation = LinearLayout.HORIZONTAL + searchContainer.gravity = Gravity.CENTER_VERTICAL + searchContainer.setVerticalGravity(Gravity.CENTER_VERTICAL) + androidStatusBarColor?.let { + searchContainer.setBackgroundColor(it.colorInt()) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + searchContainer.elevation = 10f + } + } + val tv = TypedValue() + if (context.theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) { + val actionBarHeight = TypedValue.complexToDimensionPixelSize( + tv.data, + resources.displayMetrics + ) + searchContainer.layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + actionBarHeight + ) + } + + if (androidBackItem != null) { + val imageView = ImageView(context) + imageView.layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + val margin = (20 * context.resources.displayMetrics.density).toInt() + setMargins(margin, 0, margin, 0) + } + androidBackItem?.loadIn(imageView) + imageView.setOnClickListener { + activity?.onBackPressed() + } + searchContainer.addView(imageView) + } + val radius = 8 * context.resources.displayMetrics.density val padding = radius.toInt() cardView.radius = radius @@ -74,14 +121,15 @@ actual abstract class SearchScreen actual constructor() : Screen() cardView.addView(searchView) - rootLayout.addView(cardView) + searchContainer.addView(cardView) + + rootLayout.addView(searchContainer) } val listWidget = - (theme ?: Theme()).list( + Theme().list( size = WidgetSize.AsParent, id = Ids.ListId, - category = listCategory ?: ListWidget.DefaultCategory, items = searchItems, onReachEnd = ::onReachEnd ) @@ -94,9 +142,7 @@ actual abstract class SearchScreen actual constructor() : Screen() ) ).view - rootLayout.background = view.background - view.background = null - + rootLayout.applyBackgroundIfNeeded(background) rootLayout.addView(view) return rootLayout } diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 51e74bb3..682b1a64 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -2,11 +2,18 @@ package dev.icerock.moko.widgets.screen import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem -import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.screen.navigation.Route +import dev.icerock.moko.widgets.core.Image +import dev.icerock.moko.widgets.style.background.Background -expect abstract class SearchScreen: Screen { +expect abstract class SearchScreen() : Screen { abstract val searchQuery: MutableLiveData abstract val searchItems: LiveData> + abstract fun onReachEnd() + + open val searchHint: StringDesc? + open val background: Background? + + open val androidBackItem: Image? } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt index 744347a2..13227d95 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt @@ -5,13 +5,16 @@ import dev.icerock.moko.mvvm.livedata.MutableLiveData import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.units.TableUnitItem import dev.icerock.moko.widgets.ListWidget +import dev.icerock.moko.widgets.core.Image import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.style.background.Background actual abstract class SearchScreen actual constructor() : Screen() { actual abstract val searchQuery: MutableLiveData actual abstract val searchItems: LiveData> actual abstract fun onReachEnd() - actual open val theme: Theme? = null - actual open val listCategory: ListWidget.Category? = null + actual open val searchHint: StringDesc? = null + actual open val background: Background? = null + actual open val androidBackItem: Image? = null } From 3ac1b48859059e95071840225e82589b64ae850e Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 11:29:43 +0700 Subject: [PATCH 40/48] #100 replace SearchScreen to NavigationBar.Search in API --- .../library/universal/ProductScreen.kt | 6 +- .../widgets/sample/ProductsSearchScreen.kt | 60 +++++++++++++++---- .../widgets/sample/SelectGalleryScreen.kt | 2 +- .../screen/navigation/NavigationScreen.kt | 35 +++++++---- .../moko/widgets/style/NavigationBarExt.kt | 4 +- .../widgets/utils/NavigationItemActionExt.kt | 4 +- 6 files changed, 77 insertions(+), 34 deletions(-) diff --git a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/universal/ProductScreen.kt b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/universal/ProductScreen.kt index baad4e7e..ef708e30 100644 --- a/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/universal/ProductScreen.kt +++ b/sample/mpp-library/src/commonMain/kotlin/com/icerockdev/library/universal/ProductScreen.kt @@ -41,7 +41,7 @@ class ProductScreen( override val navigationBar get() = NavigationBar.Normal( title = getArgument().productId.let { "Product $it".desc() }, - styles = NavigationBar.Normal.Styles( + styles = NavigationBar.Styles( backgroundColor = Color(0x00AA00FF), tintColor = Color(0xFF0000FF), textStyle = TextStyle( @@ -51,12 +51,12 @@ class ProductScreen( ) ), actions = listOf( - NavigationBar.Normal.BarButton( + NavigationBar.BarButton( icon = MR.images.cart_black_18 ) { println("first press") }, - NavigationBar.Normal.BarButton( + NavigationBar.BarButton( icon = MR.images.stars_black_18 ) { println("second press") diff --git a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt index b2799236..16cc4e6e 100644 --- a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt +++ b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt @@ -8,15 +8,20 @@ import dev.icerock.moko.graphics.Color import dev.icerock.moko.mvvm.livedata.LiveData import dev.icerock.moko.mvvm.livedata.MutableLiveData import dev.icerock.moko.mvvm.livedata.map +import dev.icerock.moko.mvvm.viewmodel.ViewModel import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.units.TableUnitItem +import dev.icerock.moko.widgets.ListWidget import dev.icerock.moko.widgets.constraint import dev.icerock.moko.widgets.core.Theme +import dev.icerock.moko.widgets.list import dev.icerock.moko.widgets.screen.Args -import dev.icerock.moko.widgets.screen.SearchScreen +import dev.icerock.moko.widgets.screen.WidgetScreen +import dev.icerock.moko.widgets.screen.getViewModel import dev.icerock.moko.widgets.screen.navigation.NavigationBar import dev.icerock.moko.widgets.screen.navigation.NavigationItem +import dev.icerock.moko.widgets.style.view.SizeSpec import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.text import dev.icerock.moko.widgets.units.UnitItemRoot @@ -24,21 +29,39 @@ import dev.icerock.moko.widgets.units.WidgetsTableUnitItem class ProductsSearchScreen( private val theme: Theme -) : SearchScreen(), NavigationItem { +) : WidgetScreen(), NavigationItem { - override val navigationBar: NavigationBar = NavigationBar.Normal( - title = "Products search".desc(), - styles = NavigationBar.Normal.Styles(backgroundColor = Color(0xAA3333FF)) - ) + private val viewModel: ProductsSearchViewModel by lazy { + getViewModel { ProductsSearchViewModel() } + } - private val products: List = List(size = 50) { "It's product $it" } + override val navigationBar: NavigationBar + get() = NavigationBar.Search( + title = "Products search".desc(), + styles = NavigationBar.Styles(backgroundColor = Color(0xAA3333FF)), + searchQuery = viewModel.searchQuery + ) - override val searchPlaceholder: StringDesc = "Search".desc() - override val searchQuery: MutableLiveData = MutableLiveData(initialValue = "") - override val searchItems: LiveData> = searchQuery.map { query -> - products - .filter { it.contains(query) } - .map { ProductUnitItem(theme, itemId = it.hashCode().toLong(), data = it) } + override fun createContentWidget() = with(theme) { + constraint(size = WidgetSize.AsParent) { + val results = +list( + size = WidgetSize.Const(width = SizeSpec.MatchConstraint, height = SizeSpec.MatchConstraint), + items = viewModel.products.map { products -> + products.map { ProductUnitItem(theme, itemId = it.hashCode().toLong(), data = it) as TableUnitItem } + }, + id = Ids.ResultsList + ) + + constraints { + results topToTop root.safeArea + results leftRightToLeftRight root + results bottomToBottom root.safeArea + } + } + } + + object Ids { + object ResultsList : ListWidget.Id } class ProductUnitItem( @@ -68,3 +91,14 @@ class ProductsSearchScreen( } } } + +class ProductsSearchViewModel : ViewModel() { + val searchQuery = MutableLiveData(initialValue = "") + + private val _products: List = List(size = 50) { "It's product $it" } + + val products: LiveData> = searchQuery.map { query -> + _products + .filter { it.contains(query) } + } +} diff --git a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/SelectGalleryScreen.kt b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/SelectGalleryScreen.kt index fd4348ea..c6f902ab 100644 --- a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/SelectGalleryScreen.kt +++ b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/SelectGalleryScreen.kt @@ -28,7 +28,7 @@ class SelectGalleryScreen( override val navigationBar: NavigationBar = NavigationBar.Normal( title = "Select gallery".desc(), - styles = NavigationBar.Normal.Styles( + styles = NavigationBar.Styles( backgroundColor = Color(0x4444EEFF) ) ) diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index 15b99162..74c1d9aa 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -5,6 +5,7 @@ package dev.icerock.moko.widgets.screen.navigation import dev.icerock.moko.graphics.Color +import dev.icerock.moko.mvvm.livedata.MutableLiveData import dev.icerock.moko.parcelize.Parcelable import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.desc.StringDesc @@ -101,22 +102,30 @@ interface NavigationItem { sealed class NavigationBar { object None : NavigationBar() + data class Normal( val title: StringDesc, val styles: Styles? = null, val backButton: BarButton? = null, val actions: List? = null - ) : NavigationBar() { - - data class Styles( - val backgroundColor: Color? = null, - val textStyle: TextStyle? = null, - val tintColor: Color? = null - ) - - data class BarButton( - val icon: ImageResource, - val action: () -> Unit - ) - } + ) : NavigationBar() + + data class Search( + val title: StringDesc, + val styles: Styles? = null, + val backButton: BarButton? = null, + val searchPlaceholder: StringDesc? = null, + val searchQuery: MutableLiveData + ) : NavigationBar() + + data class Styles( + val backgroundColor: Color? = null, + val textStyle: TextStyle? = null, + val tintColor: Color? = null + ) + + data class BarButton( + val icon: ImageResource, + val action: () -> Unit + ) } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt index 4fe4b91e..4a117e8b 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt @@ -12,7 +12,7 @@ import platform.UIKit.UIApplication import platform.UIKit.UINavigationBar import platform.UIKit.tintColor -fun UINavigationBar.applyNavigationBarStyle(style: NavigationBar.Normal.Styles?) { +fun UINavigationBar.applyNavigationBarStyle(style: NavigationBar.Styles?) { barTintColor = style?.backgroundColor?.toUIColor() if (style?.textStyle != null) { @@ -33,4 +33,4 @@ fun UINavigationBar.applyNavigationBarStyle(style: NavigationBar.Normal.Styles?) tintColor = style?.tintColor?.toUIColor() ?: UIApplication.sharedApplication.keyWindow?.rootViewController()?.view?.tintColor!! -} \ No newline at end of file +} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/NavigationItemActionExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/NavigationItemActionExt.kt index d9a23085..c895dfb5 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/NavigationItemActionExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/utils/NavigationItemActionExt.kt @@ -9,7 +9,7 @@ import platform.Foundation.NSSelectorFromString import platform.UIKit.UIBarButtonItem import platform.UIKit.UIBarButtonItemStyle -fun NavigationBar.Normal.BarButton.toUIBarButtonItem(): UIBarButtonItem { +fun NavigationBar.BarButton.toUIBarButtonItem(): UIBarButtonItem { val actionHandler = LambdaTarget(action) val button = UIBarButtonItem( image = icon.toUIImage(), @@ -19,4 +19,4 @@ fun NavigationBar.Normal.BarButton.toUIBarButtonItem(): UIBarButtonItem { ) setAssociatedObject(button, actionHandler) return button -} \ No newline at end of file +} From cb1c989368160be7eba2757eb0b59035c31a3e42 Mon Sep 17 00:00:00 2001 From: alobynya Date: Tue, 25 Feb 2020 11:32:18 +0700 Subject: [PATCH 41/48] #90 Add selectedDate --- .../widgets/screen/DatePickerDialogHandler.kt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt index db3dd409..dfe849b6 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/DatePickerDialogHandler.kt @@ -82,7 +82,8 @@ actual class DatePickerDialogBuilder( arg = DatePickerDialogFragment.Args( dialogId = dialogId, startDate = startDate?.unixMillisLong, - endDate = endDate?.unixMillisLong + endDate = endDate?.unixMillisLong, + selectedDate = selectedDate?.unixMillisLong ) ) alertDialogFragment.show(fragmentManager, null) @@ -99,7 +100,10 @@ class DatePickerDialogFragment : DialogFragment() { requireNotNull(argument) { "can't be opened without argument" } val dialogId = argument.dialogId - val currentDate = Calendar.getInstance() + val selectedDate = Calendar.getInstance() + argument.selectedDate?.let { + selectedDate.timeInMillis = it + } val dialog = DatePickerDialog( context, { _ , year @@ -110,9 +114,9 @@ class DatePickerDialogFragment : DialogFragment() { date.set(year, month, day) listener?.onPositivePressed(dialogId, DateTime(date.timeInMillis)) }, - currentDate.get(Calendar.YEAR), - currentDate.get(Calendar.MONTH), - currentDate.get(Calendar.DAY_OF_MONTH) + selectedDate.get(Calendar.YEAR), + selectedDate.get(Calendar.MONTH), + selectedDate.get(Calendar.DAY_OF_MONTH) ) argument.endDate?.let { dialog.datePicker.maxDate = it } argument.startDate?.let { dialog.datePicker.minDate = it } @@ -129,7 +133,8 @@ class DatePickerDialogFragment : DialogFragment() { data class Args( val dialogId: Int, val startDate: Long?, - val endDate: Long? + val endDate: Long?, + val selectedDate: Long? ) : Parcelable companion object { From 4d167ea52166ffce36d7b5c3bebd74f63e1724e3 Mon Sep 17 00:00:00 2001 From: Andrey Dorofeev Date: Tue, 25 Feb 2020 12:19:59 +0700 Subject: [PATCH 42/48] #90 fixed buttons localization --- .../icerock/moko/widgets/screen/ShowDatePickerExt.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt index 5ea557f1..9c7b6edc 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/ShowDatePickerExt.kt @@ -26,6 +26,7 @@ import platform.UIKit.topAnchor import platform.UIKit.UIButton import platform.UIKit.UIControlStateNormal import platform.UIKit.UIControlEventTouchUpInside +import platform.UIKit.UIApplication import platform.Foundation.NSBundle import platform.Foundation.NSDate @@ -159,13 +160,13 @@ class DatePickerController( ).active = true controlPanel.heightAnchor.constraintEqualToConstant(44.0) - val bundle = NSBundle.bundleWithIdentifier("com.apple.UIKit") + val bundle = NSBundle.bundleForClass(UIApplication) val doneButton = UIButton() doneButton.translatesAutoresizingMaskIntoConstraints = false doneButton.setTitle( - title = bundle?.localizedStringForKey( + title = bundle.localizedStringForKey( key = "Done", - value = "", + value = "Done", table = null ) ?: "Done", forState = UIControlStateNormal @@ -188,9 +189,9 @@ class DatePickerController( val cancelButton = UIButton() cancelButton.translatesAutoresizingMaskIntoConstraints = false cancelButton.setTitle( - title = bundle?.localizedStringForKey( + title = bundle.localizedStringForKey( key = "Cancel", - value = "", + value = "Cancel", table = null ) ?: "Cancel", forState = UIControlStateNormal From 5c318030cf178ec7e8f81d2e2ca9483eb51b6433 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 13:04:47 +0700 Subject: [PATCH 43/48] #100 ios implementation of search navbar --- .../widgets/sample/ProductsSearchScreen.kt | 5 +- .../screen/navigation/NavigationScreen.kt | 97 ++------------- .../moko/widgets/style/NavigationBarNormal.kt | 99 ++++++++++++++++ .../moko/widgets/style/NavigationBarSearch.kt | 109 +++++++++++++++++ .../screen/navigation/NavigationScreen.kt | 23 +--- .../moko/widgets/style/NavigationBarExt.kt | 112 +++++++++++++++--- 6 files changed, 327 insertions(+), 118 deletions(-) create mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarNormal.kt create mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt diff --git a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt index 16cc4e6e..f7cbd1ec 100644 --- a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt +++ b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt @@ -38,7 +38,10 @@ class ProductsSearchScreen( override val navigationBar: NavigationBar get() = NavigationBar.Search( title = "Products search".desc(), - styles = NavigationBar.Styles(backgroundColor = Color(0xAA3333FF)), + styles = NavigationBar.Styles( + backgroundColor = Color(0xAA3333FF), + tintColor = Color(0x00FF00FF) + ), searchQuery = viewModel.searchQuery ) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index 4771f677..6385546f 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -5,20 +5,12 @@ package dev.icerock.moko.widgets.screen.navigation import android.content.Context -import android.graphics.Typeface import android.os.Bundle -import android.text.Spannable -import android.text.SpannableString -import android.text.style.AbsoluteSizeSpan -import android.text.style.StyleSpan import android.view.LayoutInflater -import android.view.MenuItem import android.view.ViewGroup import android.widget.LinearLayout import androidx.activity.OnBackPressedCallback import androidx.appcompat.widget.Toolbar -import androidx.core.content.ContextCompat -import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentContainerView @@ -30,10 +22,9 @@ import dev.icerock.moko.widgets.screen.FragmentNavigation import dev.icerock.moko.widgets.screen.Screen import dev.icerock.moko.widgets.screen.TypedScreenDesc import dev.icerock.moko.widgets.screen.unsafeSetScreenArgument -import dev.icerock.moko.widgets.style.view.FontStyle +import dev.icerock.moko.widgets.style.apply import dev.icerock.moko.widgets.utils.ThemeAttrs import dev.icerock.moko.widgets.utils.dp -import dev.icerock.moko.widgets.utils.sp actual abstract class NavigationScreen actual constructor( @@ -202,80 +193,18 @@ actual abstract class NavigationScreen actual constructor( toolbar.visibility = View.GONE } is NavigationBar.Normal -> { - toolbar.visibility = View.VISIBLE - - val title = navBar.title.toString(context) - toolbar.title = SpannableString(title).apply { - val size = navBar.styles?.textStyle?.size?.toFloat()?.sp(context) - if (size != null) { - val sizeSpan = AbsoluteSizeSpan(size.toInt()) - setSpan(sizeSpan, 0, title.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - } - - val fontStyle = navBar.styles?.textStyle?.fontStyle - if (fontStyle != null) { - val style = when (fontStyle) { - FontStyle.BOLD -> Typeface.BOLD - FontStyle.MEDIUM -> Typeface.NORMAL - } - val styleSpan = StyleSpan(style) - setSpan(styleSpan, 0, title.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - } - } - - val bgColor = if (navBar.styles?.backgroundColor != null) { - navBar.styles.backgroundColor.argb.toInt() - } else { - ThemeAttrs.getPrimaryColor(context) - } - toolbar.setBackgroundColor(bgColor) - - val fallbackTintColor = ThemeAttrs.getControlNormalColor(context) - - val tintColor = navBar.styles?.tintColor?.argb?.toInt() ?: fallbackTintColor - - toolbar.setTitleTextColor(tintColor) - toolbar.overflowIcon?.also { DrawableCompat.setTint(it, tintColor) } - - if (navBar.styles?.textStyle?.color != null) { - toolbar.setTitleTextColor(navBar.styles.textStyle.color.argb.toInt()) - } else { - toolbar.setTitleTextColor(fallbackTintColor) - } - - val backBtn = navBar.backButton - if (backBtn != null) { - toolbar.navigationIcon = ContextCompat.getDrawable(context, backBtn.icon.drawableResId) - toolbar.setNavigationOnClickListener { - backBtn.action() - } - } else { - toolbar.navigationIcon = if (childFragmentManager.backStackEntryCount > 0) { - ThemeAttrs.getToolBarUpIndicator(requireContext()) - } else { - null - } - toolbar.setNavigationOnClickListener { - childFragmentManager.popBackStack() - } - } - toolbar.navigationIcon?.also { DrawableCompat.setTint(it, tintColor) } - - val actions = navBar.actions - if (actions != null) { - actions.forEach { barBtn -> - val item = toolbar.menu.add("$barBtn") - item.icon = ContextCompat.getDrawable(context, barBtn.icon.drawableResId) - DrawableCompat.setTint(item.icon, tintColor) - item.setOnMenuItemClickListener { - barBtn.action() - true - } - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) - } - } else { - toolbar.menu.clear() - } + navBar.apply( + toolbar = toolbar, + context = context, + fragmentManager = childFragmentManager + ) + } + is NavigationBar.Search -> { + navBar.apply( + toolbar = toolbar, + context = context, + fragmentManager = childFragmentManager + ) } } } diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarNormal.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarNormal.kt new file mode 100644 index 00000000..04ea6401 --- /dev/null +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarNormal.kt @@ -0,0 +1,99 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style + +import android.content.Context +import android.graphics.Typeface +import android.text.Spannable +import android.text.SpannableString +import android.text.style.AbsoluteSizeSpan +import android.text.style.StyleSpan +import android.view.MenuItem +import android.view.View +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import androidx.fragment.app.FragmentManager +import dev.icerock.moko.widgets.screen.navigation.NavigationBar +import dev.icerock.moko.widgets.style.view.FontStyle +import dev.icerock.moko.widgets.utils.ThemeAttrs +import dev.icerock.moko.widgets.utils.sp + + +fun NavigationBar.Normal.apply( + toolbar: Toolbar, + context: Context, + fragmentManager: FragmentManager +) { + toolbar.visibility = View.VISIBLE + + val title = title.toString(context) + toolbar.title = SpannableString(title).apply { + val size = styles?.textStyle?.size?.toFloat()?.sp(context) + if (size != null) { + val sizeSpan = AbsoluteSizeSpan(size.toInt()) + setSpan(sizeSpan, 0, title.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + } + + val fontStyle = styles?.textStyle?.fontStyle + if (fontStyle != null) { + val style = when (fontStyle) { + FontStyle.BOLD -> Typeface.BOLD + FontStyle.MEDIUM -> Typeface.NORMAL + } + val styleSpan = StyleSpan(style) + setSpan(styleSpan, 0, title.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + } + } + + val bgColor = styles?.backgroundColor?.argb?.toInt() + ?: ThemeAttrs.getPrimaryColor(context) + + toolbar.setBackgroundColor(bgColor) + + val fallbackTintColor = ThemeAttrs.getControlNormalColor(context) + + val tintColor = styles?.tintColor?.argb?.toInt() ?: fallbackTintColor + + toolbar.setTitleTextColor(tintColor) + toolbar.overflowIcon?.also { DrawableCompat.setTint(it, tintColor) } + + val textColor = styles?.textStyle?.color?.argb?.toInt() ?: fallbackTintColor + toolbar.setTitleTextColor(textColor) + + val backBtn = backButton + if (backBtn != null) { + toolbar.navigationIcon = ContextCompat.getDrawable(context, backBtn.icon.drawableResId) + toolbar.setNavigationOnClickListener { + backBtn.action() + } + } else { + toolbar.navigationIcon = if (fragmentManager.backStackEntryCount > 0) { + ThemeAttrs.getToolBarUpIndicator(context) + } else { + null + } + toolbar.setNavigationOnClickListener { + fragmentManager.popBackStack() + } + } + toolbar.navigationIcon?.also { DrawableCompat.setTint(it, tintColor) } + + val actions = actions + if (actions != null) { + actions.forEach { barBtn -> + val item = toolbar.menu.add("$barBtn") + item.icon = ContextCompat.getDrawable(context, barBtn.icon.drawableResId) + DrawableCompat.setTint(item.icon, tintColor) + item.setOnMenuItemClickListener { + barBtn.action() + true + } + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) + } + } else { + toolbar.menu.clear() + } +} diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt new file mode 100644 index 00000000..eda46ab5 --- /dev/null +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.moko.widgets.style + +import android.content.Context +import android.graphics.Typeface +import android.text.Spannable +import android.text.SpannableString +import android.text.style.AbsoluteSizeSpan +import android.text.style.StyleSpan +import android.view.MenuItem +import android.view.View +import android.widget.SearchView +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import androidx.fragment.app.FragmentManager +import dev.icerock.moko.widgets.screen.navigation.NavigationBar +import dev.icerock.moko.widgets.style.view.FontStyle +import dev.icerock.moko.widgets.utils.ThemeAttrs +import dev.icerock.moko.widgets.utils.sp + + +fun NavigationBar.Search.apply( + toolbar: Toolbar, + context: Context, + fragmentManager: FragmentManager +) { + toolbar.visibility = View.VISIBLE + + val title = title.toString(context) + toolbar.title = SpannableString(title).apply { + val size = styles?.textStyle?.size?.toFloat()?.sp(context) + if (size != null) { + val sizeSpan = AbsoluteSizeSpan(size.toInt()) + setSpan(sizeSpan, 0, title.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + } + + val fontStyle = styles?.textStyle?.fontStyle + if (fontStyle != null) { + val style = when (fontStyle) { + FontStyle.BOLD -> Typeface.BOLD + FontStyle.MEDIUM -> Typeface.NORMAL + } + val styleSpan = StyleSpan(style) + setSpan(styleSpan, 0, title.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + } + } + + val bgColor = styles?.backgroundColor?.argb?.toInt() + ?: ThemeAttrs.getPrimaryColor(context) + + toolbar.setBackgroundColor(bgColor) + + val fallbackTintColor = ThemeAttrs.getControlNormalColor(context) + + val tintColor = styles?.tintColor?.argb?.toInt() ?: fallbackTintColor + + toolbar.setTitleTextColor(tintColor) + toolbar.overflowIcon?.also { DrawableCompat.setTint(it, tintColor) } + + val textColor = styles?.textStyle?.color?.argb?.toInt() ?: fallbackTintColor + toolbar.setTitleTextColor(textColor) + + val backBtn = backButton + if (backBtn != null) { + toolbar.navigationIcon = ContextCompat.getDrawable(context, backBtn.icon.drawableResId) + toolbar.setNavigationOnClickListener { + backBtn.action() + } + } else { + toolbar.navigationIcon = if (fragmentManager.backStackEntryCount > 0) { + ThemeAttrs.getToolBarUpIndicator(context) + } else { + null + } + toolbar.setNavigationOnClickListener { + fragmentManager.popBackStack() + } + } + toolbar.navigationIcon?.also { DrawableCompat.setTint(it, tintColor) } + + // TODO SEARCH + val searchItem = toolbar.menu.add("search") + searchItem.actionView = SearchView(context).apply { + setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?): Boolean { + searchQuery.value = query ?: "" + return true + } + + override fun onQueryTextChange(newText: String?): Boolean { + if (newText?.isEmpty() == true) { + searchQuery.value = newText + return true + } + return false + } + + }) + setOnSearchClickListener { _ -> + searchQuery.value = query.toString() + } + queryHint = searchPlaceholder?.toString(context) + } + searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) +} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index f3ec2715..f3ac19da 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -10,16 +10,13 @@ import dev.icerock.moko.widgets.screen.Screen import dev.icerock.moko.widgets.screen.TypedScreenDesc import dev.icerock.moko.widgets.screen.application import dev.icerock.moko.widgets.screen.getAssociatedScreen -import dev.icerock.moko.widgets.style.applyNavigationBarStyle +import dev.icerock.moko.widgets.style.apply import dev.icerock.moko.widgets.utils.getStatusBarStyle -import dev.icerock.moko.widgets.utils.toUIBarButtonItem import kotlinx.coroutines.Runnable -import platform.UIKit.UIBarButtonItem import platform.UIKit.UINavigationController import platform.UIKit.UINavigationControllerDelegateProtocol import platform.UIKit.UIStatusBarStyle import platform.UIKit.UIViewController -import platform.UIKit.navigationItem import platform.darwin.NSObject import kotlin.native.ref.WeakReference @@ -52,21 +49,9 @@ actual abstract class NavigationScreen actual constructor( viewController: UIViewController ) { when (val navBar = navigationItem.navigationBar) { - is NavigationBar.None -> navigationController?.navigationBarHidden = true - is NavigationBar.Normal -> { - navigationController?.navigationBarHidden = false - viewController.navigationItem.title = navBar.title.localized() - navigationController?.navigationBar?.applyNavigationBarStyle(navBar.styles) - - if (navBar.backButton != null) { - viewController.navigationItem.leftBarButtonItem = navBar.backButton.toUIBarButtonItem() - } - - val rightButtons: List? = navBar.actions?.map { - it.toUIBarButtonItem() - }?.reversed() - viewController.navigationItem.rightBarButtonItems = rightButtons - } + is NavigationBar.None -> navBar.apply(navigationController) + is NavigationBar.Normal -> navBar.apply(navigationController, viewController) + is NavigationBar.Search -> navBar.apply(navigationController, viewController) } } diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt index 4a117e8b..9fb4ef1f 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt @@ -4,33 +4,117 @@ package dev.icerock.moko.widgets.style import dev.icerock.moko.graphics.toUIColor +import dev.icerock.moko.mvvm.livedata.MutableLiveData +import dev.icerock.moko.widgets.objc.setAssociatedObject import dev.icerock.moko.widgets.screen.navigation.NavigationBar +import dev.icerock.moko.widgets.utils.toUIBarButtonItem import dev.icerock.moko.widgets.utils.toUIFont import platform.UIKit.NSFontAttributeName import platform.UIKit.NSForegroundColorAttributeName import platform.UIKit.UIApplication +import platform.UIKit.UIBarButtonItem +import platform.UIKit.UIDevice import platform.UIKit.UINavigationBar +import platform.UIKit.UINavigationBarAppearance +import platform.UIKit.UINavigationController +import platform.UIKit.UISearchController +import platform.UIKit.UISearchResultsUpdatingProtocol +import platform.UIKit.UIViewController +import platform.UIKit.navigationItem import platform.UIKit.tintColor +import platform.darwin.NSObject fun UINavigationBar.applyNavigationBarStyle(style: NavigationBar.Styles?) { - barTintColor = style?.backgroundColor?.toUIColor() - - if (style?.textStyle != null) { - var textAttibutes = mapOf() - if (style.textStyle.color != null) { - style.textStyle.color.toUIColor().CGColor - textAttibutes = textAttibutes.plus(NSForegroundColorAttributeName to style.textStyle.color.toUIColor()) + val textAttributes: Map? = style?.textStyle?.let { ts -> + val attributes = mutableMapOf() + if (ts.color != null) { + attributes[NSForegroundColorAttributeName] = ts.color.toUIColor() } - val font = style.textStyle.toUIFont() + val font = ts.toUIFont() if (font != null) { - textAttibutes = textAttibutes.plus(NSFontAttributeName to font) + attributes[NSFontAttributeName] = font } + attributes + } + val backgroundColor = style?.backgroundColor?.toUIColor() + val tintColor = style?.tintColor?.toUIColor() + ?: UIApplication.sharedApplication.keyWindow?.rootViewController()?.view?.tintColor!! + + +// if (UIDevice.currentDevice.systemVersion.compareTo("13.0") < 0) { + println("pre 13.0") + this.barTintColor = backgroundColor + this.titleTextAttributes = textAttributes + this.tintColor = tintColor +// } else { +// val appearance = UINavigationBarAppearance().apply { +// configureWithDefaultBackground() +// +// this.backgroundColor = backgroundColor +// textAttributes?.let { this.titleTextAttributes = it } +// } +// +// this.scrollEdgeAppearance = appearance +// this.standardAppearance = appearance +// this.tintColor = tintColor +// } +} - titleTextAttributes = textAttibutes - } else { - titleTextAttributes = null +@Suppress("unused") +fun NavigationBar.None.apply( + navigationController: UINavigationController? +) { + navigationController?.navigationBarHidden = true +} + +fun NavigationBar.Normal.apply( + navigationController: UINavigationController?, + viewController: UIViewController +) { + navigationController?.navigationBarHidden = false + viewController.navigationItem.title = title.localized() + navigationController?.navigationBar?.applyNavigationBarStyle(styles) + + if (backButton != null) { + viewController.navigationItem.leftBarButtonItem = backButton.toUIBarButtonItem() } - tintColor = style?.tintColor?.toUIColor() - ?: UIApplication.sharedApplication.keyWindow?.rootViewController()?.view?.tintColor!! + val rightButtons: List? = actions?.map { + it.toUIBarButtonItem() + }?.reversed() + viewController.navigationItem.rightBarButtonItems = rightButtons +} + +fun NavigationBar.Search.apply( + navigationController: UINavigationController?, + viewController: UIViewController +) { + navigationController?.navigationBarHidden = false + viewController.navigationItem.title = title.localized() + navigationController?.navigationBar?.applyNavigationBarStyle(styles) + + if (backButton != null) { + viewController.navigationItem.leftBarButtonItem = backButton.toUIBarButtonItem() + } + + val searchController = UISearchController(searchResultsController = null).apply { + searchResultsUpdater = SearchResultsLiveDataUpdater(searchQuery).also { + setAssociatedObject(this, it) + } + obscuresBackgroundDuringPresentation = false + searchBar.placeholder = searchPlaceholder?.localized() + styles?.tintColor?.also { searchBar.tintColor = it.toUIColor() } + } + + viewController.navigationItem.searchController = searchController + viewController.definesPresentationContext = true +} + +class SearchResultsLiveDataUpdater( + private val liveData: MutableLiveData +) : NSObject(), UISearchResultsUpdatingProtocol { + + override fun updateSearchResultsForSearchController(searchController: UISearchController) { + liveData.value = searchController.searchBar.text.orEmpty() + } } From fc441a3b7f51bba274c598d9f1fc7d5a1b0c8fd1 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 13:05:55 +0700 Subject: [PATCH 44/48] #100 todo --- .../kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt index 9fb4ef1f..abd4a38c 100644 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt +++ b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarExt.kt @@ -41,8 +41,8 @@ fun UINavigationBar.applyNavigationBarStyle(style: NavigationBar.Styles?) { ?: UIApplication.sharedApplication.keyWindow?.rootViewController()?.view?.tintColor!! +// TODO uncomment when kotlin-native will fix linking to newest api // if (UIDevice.currentDevice.systemVersion.compareTo("13.0") < 0) { - println("pre 13.0") this.barTintColor = backgroundColor this.titleTextAttributes = textAttributes this.tintColor = tintColor From f13304e84a682094bfd8f1c97091816b3cc01bc2 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 13:35:53 +0700 Subject: [PATCH 45/48] #100 android implementation --- .../widgets/sample/ProductsSearchScreen.kt | 13 ++++++-- .../moko/widgets/style/NavigationBarSearch.kt | 33 ++++++++++++------- .../screen/navigation/NavigationScreen.kt | 5 ++- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt index f7cbd1ec..6e7983de 100644 --- a/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt +++ b/sample/mpp-library/src/commonMain/kotlin/dev/icerock/moko/widgets/sample/ProductsSearchScreen.kt @@ -21,6 +21,8 @@ import dev.icerock.moko.widgets.screen.WidgetScreen import dev.icerock.moko.widgets.screen.getViewModel import dev.icerock.moko.widgets.screen.navigation.NavigationBar import dev.icerock.moko.widgets.screen.navigation.NavigationItem +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.SizeSpec import dev.icerock.moko.widgets.style.view.WidgetSize import dev.icerock.moko.widgets.text @@ -39,10 +41,15 @@ class ProductsSearchScreen( get() = NavigationBar.Search( title = "Products search".desc(), styles = NavigationBar.Styles( - backgroundColor = Color(0xAA3333FF), - tintColor = Color(0x00FF00FF) + backgroundColor = Color(0xFFFFFFFF), + tintColor = Color(0x111111FF) ), - searchQuery = viewModel.searchQuery + searchQuery = viewModel.searchQuery, + searchPlaceholder = "Product title".desc(), + androidSearchBackground = Background( + fill = Fill.Solid(color = Color(0xF2F2F2FF)), + cornerRadius = 2f + ) ) override fun createContentWidget() = with(theme) { diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt index eda46ab5..84526e94 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt @@ -12,11 +12,14 @@ import android.text.style.AbsoluteSizeSpan import android.text.style.StyleSpan import android.view.MenuItem import android.view.View -import android.widget.SearchView +import android.view.ViewGroup +import android.widget.ImageView +import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import androidx.fragment.app.FragmentManager +import dev.icerock.moko.widgets.R import dev.icerock.moko.widgets.screen.navigation.NavigationBar import dev.icerock.moko.widgets.style.view.FontStyle import dev.icerock.moko.widgets.utils.ThemeAttrs @@ -83,20 +86,16 @@ fun NavigationBar.Search.apply( toolbar.navigationIcon?.also { DrawableCompat.setTint(it, tintColor) } // TODO SEARCH - val searchItem = toolbar.menu.add("search") - searchItem.actionView = SearchView(context).apply { + val searchView = SearchView(context).apply { setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String?): Boolean { - searchQuery.value = query ?: "" + override fun onQueryTextSubmit(query: String): Boolean { + searchQuery.value = query return true } - override fun onQueryTextChange(newText: String?): Boolean { - if (newText?.isEmpty() == true) { - searchQuery.value = newText - return true - } - return false + override fun onQueryTextChange(newText: String): Boolean { + searchQuery.value = newText + return true } }) @@ -104,6 +103,16 @@ fun NavigationBar.Search.apply( searchQuery.value = query.toString() } queryHint = searchPlaceholder?.toString(context) + + applyBackgroundIfNeeded(androidSearchBackground) + + val mlp = findViewById(R.id.search_edit_frame).layoutParams as? ViewGroup.MarginLayoutParams + mlp?.leftMargin = 0 + mlp?.rightMargin = 0 } - searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) + + val searchItem = toolbar.menu.add("search") + searchItem.icon = searchView.findViewById(R.id.search_button).drawable + searchItem.actionView = searchView + searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW or MenuItem.SHOW_AS_ACTION_ALWAYS) } diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt index 74c1d9aa..c80aa1e3 100644 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt +++ b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/navigation/NavigationScreen.kt @@ -12,6 +12,8 @@ import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.widgets.screen.Args import dev.icerock.moko.widgets.screen.Screen import dev.icerock.moko.widgets.screen.TypedScreenDesc +import dev.icerock.moko.widgets.style.background.Background +import dev.icerock.moko.widgets.style.background.Fill import dev.icerock.moko.widgets.style.view.TextStyle expect abstract class NavigationScreen( @@ -115,7 +117,8 @@ sealed class NavigationBar { val styles: Styles? = null, val backButton: BarButton? = null, val searchPlaceholder: StringDesc? = null, - val searchQuery: MutableLiveData + val searchQuery: MutableLiveData, + val androidSearchBackground: Background? = null ) : NavigationBar() data class Styles( From 753266235a01462e520a3661ddbde9747834fc11 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 13:37:56 +0700 Subject: [PATCH 46/48] #100 SearchScreen class removed (now use NavigationBar.Search) --- .../moko/widgets/screen/SearchScreen.kt | 154 ------------------ .../moko/widgets/screen/SearchScreen.kt | 21 --- .../moko/widgets/screen/SearchScreen.kt | 34 ---- .../widgets/screen/SearchViewController.kt | 87 ---------- 4 files changed, 296 deletions(-) delete mode 100644 widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt delete mode 100644 widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt delete mode 100644 widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt delete mode 100644 widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt deleted file mode 100644 index a1bd3918..00000000 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.screen - -import android.graphics.Color -import android.os.Build -import android.os.Bundle -import android.util.TypedValue -import android.view.Gravity -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.ImageView -import android.widget.LinearLayout -import android.widget.SearchView -import androidx.cardview.widget.CardView -import dev.icerock.moko.graphics.colorInt -import dev.icerock.moko.mvvm.livedata.LiveData -import dev.icerock.moko.mvvm.livedata.MutableLiveData -import dev.icerock.moko.resources.desc.StringDesc -import dev.icerock.moko.units.TableUnitItem -import dev.icerock.moko.widgets.ListWidget -import dev.icerock.moko.widgets.core.Image -import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.core.ViewFactoryContext -import dev.icerock.moko.widgets.list -import dev.icerock.moko.widgets.style.applyBackgroundIfNeeded -import dev.icerock.moko.widgets.style.background.Background -import dev.icerock.moko.widgets.style.view.WidgetSize - - -actual abstract class SearchScreen : Screen() { - actual abstract val searchPlaceholder: StringDesc - actual abstract val searchQuery: MutableLiveData - actual abstract val searchItems: LiveData> - actual open val background: Background<*>? = null - actual open val androidBackItem: Image? = null - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): android.view.View? { - - val rootLayout = LinearLayout(context) - rootLayout.orientation = LinearLayout.VERTICAL - - context?.let { context -> - val cardView = CardView(context) - - - val searchContainer = LinearLayout(context) - searchContainer.orientation = LinearLayout.HORIZONTAL - searchContainer.gravity = Gravity.CENTER_VERTICAL - searchContainer.setVerticalGravity(Gravity.CENTER_VERTICAL) - androidStatusBarColor?.let { - searchContainer.setBackgroundColor(it.colorInt()) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - searchContainer.elevation = 10f - } - } - val tv = TypedValue() - if (context.theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) { - val actionBarHeight = TypedValue.complexToDimensionPixelSize( - tv.data, - resources.displayMetrics - ) - searchContainer.layoutParams = LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - actionBarHeight - ) - } - - if (androidBackItem != null) { - val imageView = ImageView(context) - imageView.layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - val margin = (20 * context.resources.displayMetrics.density).toInt() - setMargins(margin, 0, margin, 0) - } - androidBackItem?.loadIn(imageView) - imageView.setOnClickListener { - activity?.onBackPressed() - } - searchContainer.addView(imageView) - } - - val radius = 8 * context.resources.displayMetrics.density - val padding = radius.toInt() - cardView.radius = radius - cardView.layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - setMargins(padding, padding, padding, padding) - } - - val searchView = SearchView(context) - searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String?): Boolean { - searchQuery.value = query ?: "" - return true - } - - override fun onQueryTextChange(newText: String?): Boolean { - if (newText?.isEmpty() == true) { - searchQuery.value = newText - return true - } - return false - } - - }) - searchView.setOnSearchClickListener { _ -> - searchQuery.value = searchView.query.toString() - } - searchView.queryHint = searchPlaceholder.toString(context) - - searchView.setBackgroundColor(Color.WHITE) - - cardView.addView(searchView) - - searchContainer.addView(cardView) - - rootLayout.addView(searchContainer) - } - - val listWidget = - Theme().list( - size = WidgetSize.AsParent, - id = Ids.ListId, - items = searchItems - ) - - val view = listWidget.buildView( - ViewFactoryContext( - context = requireContext(), - lifecycleOwner = this, - parent = container - ) - ).view - - rootLayout.applyBackgroundIfNeeded(background) - rootLayout.addView(view) - return rootLayout - } - - object Ids { - object ListId : ListWidget.Id - } -} diff --git a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt deleted file mode 100644 index 61eed95b..00000000 --- a/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.screen - -import dev.icerock.moko.mvvm.livedata.LiveData -import dev.icerock.moko.mvvm.livedata.MutableLiveData -import dev.icerock.moko.resources.desc.StringDesc -import dev.icerock.moko.units.TableUnitItem -import dev.icerock.moko.widgets.core.Image -import dev.icerock.moko.widgets.style.background.Background - -expect abstract class SearchScreen() : Screen { - abstract val searchPlaceholder: StringDesc - abstract val searchQuery: MutableLiveData - abstract val searchItems: LiveData> - - open val background: Background<*>? - open val androidBackItem: Image? -} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt deleted file mode 100644 index 956a705b..00000000 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchScreen.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.screen - -import dev.icerock.moko.mvvm.livedata.LiveData -import dev.icerock.moko.mvvm.livedata.MutableLiveData -import dev.icerock.moko.resources.desc.StringDesc -import dev.icerock.moko.units.TableUnitItem -import platform.UIKit.UIViewController -import dev.icerock.moko.widgets.ListWidget -import dev.icerock.moko.widgets.core.Image -import dev.icerock.moko.widgets.core.Theme -import dev.icerock.moko.widgets.style.background.Background - - -actual abstract class SearchScreen : Screen() { - actual abstract val searchPlaceholder: StringDesc - actual abstract val searchQuery: MutableLiveData - actual abstract val searchItems: LiveData> - - override fun createViewController(isLightStatusBar: Boolean?): UIViewController { - return SearchViewController( - isLightStatusBar = isLightStatusBar, - searchQuery = searchQuery, - searchItems = searchItems, - searchPlaceholder = searchPlaceholder - ) - } - - actual open val background: Background<*>? = null - actual open val androidBackItem: Image? = null -} diff --git a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt b/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt deleted file mode 100644 index 59a39186..00000000 --- a/widgets/src/iosMain/kotlin/dev/icerock/moko/widgets/screen/SearchViewController.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2020 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.moko.widgets.screen - -import dev.icerock.moko.mvvm.livedata.LiveData -import dev.icerock.moko.mvvm.livedata.MutableLiveData -import dev.icerock.moko.resources.desc.StringDesc -import dev.icerock.moko.units.TableUnitItem -import dev.icerock.moko.units.UnitTableViewDataSource -import dev.icerock.moko.widgets.utils.bind -import dev.icerock.moko.widgets.utils.getStatusBarStyle -import dev.icerock.moko.widgets.utils.setEventHandler -import kotlinx.cinterop.readValue -import platform.CoreGraphics.CGRectZero -import platform.UIKit.UIControlEventValueChanged -import platform.UIKit.UISearchController -import platform.UIKit.UISearchResultsUpdatingProtocol -import platform.UIKit.UIStatusBarStyle -import platform.UIKit.UITableView -import platform.UIKit.UIViewController -import platform.UIKit.addSubview -import platform.UIKit.bottomAnchor -import platform.UIKit.leadingAnchor -import platform.UIKit.navigationItem -import platform.UIKit.searchTextField -import platform.UIKit.topAnchor -import platform.UIKit.trailingAnchor -import platform.UIKit.translatesAutoresizingMaskIntoConstraints - -class SearchViewController( - private val isLightStatusBar: Boolean?, - private val searchQuery: MutableLiveData, - private val searchItems: LiveData>, - private val searchPlaceholder: StringDesc -) : UIViewController(nibName = null, bundle = null), UISearchResultsUpdatingProtocol { - - private lateinit var unitsDataSource: UnitTableViewDataSource - - override fun viewDidLoad() { - super.viewDidLoad() - - setupSearchController() - setupTableView() - } - - private fun setupSearchController() { - val searchController = UISearchController(searchResultsController = null) - // Setup the Search Controller - searchController.searchResultsUpdater = this - searchController.obscuresBackgroundDuringPresentation = false - searchController.searchBar.placeholder = searchPlaceholder.localized() - - navigationItem.searchController = searchController - - definesPresentationContext = true - } - - private fun setupTableView() { - val tableView = UITableView(frame = CGRectZero.readValue()).apply { - translatesAutoresizingMaskIntoConstraints = false - } - - unitsDataSource = UnitTableViewDataSource(tableView = tableView) - - searchItems.bind { unitsDataSource.unitItems = it } - - with(view) { - addSubview(tableView) - - leadingAnchor.constraintEqualToAnchor(tableView.leadingAnchor).active = true - tableView.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true - topAnchor.constraintEqualToAnchor(tableView.topAnchor).active = true - tableView.bottomAnchor.constraintEqualToAnchor(bottomAnchor).active = true - } - } - - override fun updateSearchResultsForSearchController(searchController: UISearchController) { - searchQuery.value = searchController.searchBar.text.orEmpty() - } - - override fun preferredStatusBarStyle(): UIStatusBarStyle { - val isLight = isLightStatusBar ?: application.isLightStatusBar - return getStatusBarStyle(isLight) ?: super.preferredStatusBarStyle() - } -} From 1730de4ab11e6c64ba60af3b8aed186ab6a0e08c Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 13:42:56 +0700 Subject: [PATCH 47/48] #100 fix android navbar reuse --- .../kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt index 84526e94..60703dcf 100644 --- a/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt +++ b/widgets/src/androidMain/kotlin/dev/icerock/moko/widgets/style/NavigationBarSearch.kt @@ -111,6 +111,7 @@ fun NavigationBar.Search.apply( mlp?.rightMargin = 0 } + toolbar.menu.clear() val searchItem = toolbar.menu.add("search") searchItem.icon = searchView.findViewById(R.id.search_button).drawable searchItem.actionView = searchView From 6bde6a5da14f4caf7786fde40cf47fc2fc58048a Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Tue, 25 Feb 2020 14:22:49 +0700 Subject: [PATCH 48/48] update readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 780952c3..acc001fc 100755 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This is a Kotlin MultiPlatform library that provides declarative UI and applicat in common code. You can implement full application for Android and iOS only from common code with it. ## Current status -Current version - `0.1.0-dev-12`. Dev version is not tested in production tasks yet, API can be changed and +Current version - `0.1.0-dev-13`. Dev version is not tested in production tasks yet, API can be changed and bugs may be found. But dev version is chance to test limits of API and concepts to feedback and improve lib. We open for any feedback and ideas (go to issues or #moko at [kotlinlang.slack.com](https://kotlinlang.slack.com))! @@ -219,6 +219,7 @@ val loginScreen = Theme(baseTheme) { - 0.1.0-dev-10 - 0.1.0-dev-11 - 0.1.0-dev-12 + - 0.1.0-dev-13 ## Installation root build.gradle @@ -233,7 +234,7 @@ allprojects { project build.gradle ```groovy dependencies { - commonMainApi("dev.icerock.moko:widgets:0.1.0-dev-12") + commonMainApi("dev.icerock.moko:widgets:0.1.0-dev-13") } ``` @@ -251,7 +252,7 @@ buildscript { } dependencies { - classpath "dev.icerock.moko.widgets:gradle-plugin:0.1.0-dev-12" + classpath "dev.icerock.moko.widgets:gradle-plugin:0.1.0-dev-13" } }