icerockdev / moko-widgets

Multiplatform UI DSL with screen management in common code for mobile (android & ios) Kotlin Multiplatform development
https://moko.icerock.dev
Apache License 2.0
387 stars 32 forks source link

Implement Context Menu on Button Click #259

Open Diy2210 opened 4 years ago

Diy2210 commented 4 years ago

How implement Context Menu on button click like:

unnamed

Alex009 commented 4 years ago

hi! thanks for suggestion! now it not implemented, but you can implement it yourself. for it you should create own Widget, for example as https://github.com/icerockdev/moko-widgets/blob/master/widgets/src/commonMain/kotlin/dev/icerock/moko/widgets/ClickableWidget.kt

widget:

@WidgetDef(ContextMenuViewFactory::class)
class ContextMenuWidget<WS : WidgetSize>(
    private val factory: ViewFactory<ContextMenuWidget<out WidgetSize>>,
    override val id: Id?,
    val child: Widget<WS>,
    val menuItems: List<MenuItem>
) : Widget<WS>(), OptionalId<ContextMenuWidget.Id> {

    override val size: WS = child.size

    override fun buildView(viewFactoryContext: ViewFactoryContext): ViewBundle<WS> {
        return factory.build(this, size, viewFactoryContext)
    }

    interface Id : Theme.Id<ContextMenuWidget<out WidgetSize>>
    interface Category : Theme.Category<ContextMenuWidget<out WidgetSize>>

    object DefaultCategory : Category

    data class MenuItem(
        val title: StringDesc,
        val onClick: () -> Unit
    )
}

for widget you should implement ViewFactory - it will construct views for each target systems: common code:

expect class ContextMenuViewFactory() : ViewFactory<ContextMenuWidget<out WidgetSize>>

android code:

actual class ContextMenuViewFactory actual constructor(
) : ViewFactory<ContextMenuWidget<out WidgetSize>> {

    override fun <WS : WidgetSize> build(
        widget: ContextMenuWidget<out WidgetSize>,
        size: WS,
        viewFactoryContext: ViewFactoryContext
    ): ViewBundle<WS> {
        val childViewBundle =
            widget.child.buildView(viewFactoryContext) as ViewBundle<WS>

        return childViewBundle.copy(
            view = childViewBundle.view.apply {
                // set here context menu showing on click to `this`
                // https://developer.android.com/guide/topics/ui/menus#context-menu
                // https://developer.android.com/guide/topics/ui/menus#PopupMenu
            }
        )
    }
}

ios code:

actual class ContextMenuViewFactory actual constructor(
) : ViewFactory<ContextMenuWidget<out WidgetSize>> {

    override fun <WS : WidgetSize> build(
        widget: ContextMenuWidget<out WidgetSize>,
        size: WS,
        viewFactoryContext: ViewFactoryContext
    ): ViewBundle<WS> {
        val childViewBundle =
            widget.child.buildView(viewFactoryContext) as ViewBundle<WS>

        childViewBundle.view.apply {
                // set here context menu showing on click to `this`
                // https://developer.apple.com/design/human-interface-guidelines/ios/controls/context-menus/
                // https://developer.apple.com/design/human-interface-guidelines/ios/views/action-sheets/
        }

        return childViewBundle
    }
}
Diy2210 commented 4 years ago

Ok, I try it tnx!

Alex009 commented 4 years ago

please left issue open - we implement it in library later

Diy2210 commented 4 years ago

I try implement context menu, but I dont understand how it use.

My ContextMenuWidget: Снимок экрана 2020-07-27 в 14 56 41

Common Expect class: Снимок экрана 2020-07-27 в 14 56 52

Android actual: Снимок экрана 2020-07-27 в 14 57 06

How use it this on button click? Снимок экрана 2020-07-27 в 14 56 31