我对Kotlin和Compose多平台非常陌生,但我想知道是否有一种方法可以在iOS和Android之间创建特定于平台的Views.

我已经设法为Android制作了一个特定于平台的按钮,但iOS的按钮是不可见的.该应用程序可以在两个平台上运行,并且没有错误.

commonMainApp.kt中的使用情况:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp


@Composable
fun App() {
    var counter by remember { mutableStateOf(0) }

    MaterialTheme {
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = Modifier
                .fillMaxSize()
        ) {
            Column(
                verticalArrangement = Arrangement.spacedBy(16.dp),
            ) {
                Text("Counter: $counter")
                PlatformButton.createButton("Click to increase Counter") {
                    counter++
                }
            }
        }
    }
}

我对commonMain年的期望值:

import androidx.compose.runtime.Composable

expect class PlatformButton {
    companion object {
        @Composable
        fun createButton(label: String, onClick: () -> Unit): Any
    }
}

androidMain岁时的实际班级:

import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable

actual class PlatformButton {
    actual companion object {
        @Composable
        actual fun createButton(label: String, onClick: () -> Unit): Any {
            return Button(onClick) {
                Text(label)
            }
        }
    }
}

iosMain岁时的实际班级:

import androidx.compose.runtime.Composable
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.ObjCAction
import platform.UIKit.UIButton
import platform.UIKit.UIButtonTypeSystem
import platform.UIKit.UIControlEventTouchUpInside
import platform.darwin.NSObject
import platform.darwin.sel_registerName

actual class PlatformButton {
    actual companion object {
        @OptIn(ExperimentalForeignApi::class)
        @Composable
        actual fun createButton(label: String, onClick: () -> Unit): Any {
            val uiButton = UIButton.buttonWithType(UIButtonTypeSystem)
            uiButton.setTitle(label, forState = 0u)

            val block = object : NSObject() {
                @ObjCAction
                fun buttonClicked() {
                    onClick()
                }
            }

            uiButton.addTarget(block, action = sel_registerName("buttonClicked"), forControlEvents = UIControlEventTouchUpInside)

            return uiButton
        }
    }
}

我已经搜索了文件,但没有找到任何文件.我也不太喜欢在Kotlin中使用UIKit.难道没有其他方法可以使用SwiftUI代码,并以某种方式用桥从它创建Composable View吗?我还想知道的是:这样的用例有没有特定的返回类型,而不是Any

推荐答案

在iOS上,你创建了UIButton,并希望Compose绘制它,但它不知道如何呈现这个视图.

要将UIKit视图转换为Compose,您需要UIKitView:

UIKitView(factory = {
    val uiButton = ...
    uiButton
})

此外,你不需要一个类来定义expect compose函数,你可以直接声明它-它会让你的compose代码看起来更自然:

@Composable
expect PlatformButton(...)
@Composable
actual PlatformButton(...) {
    UIKitView(factory = {
        ...
    })
}

Kotlin相关问答推荐

Kotlin多平台(KMP)保存到文件不能在iOS上保存

S使用MAP和ElseThrow的习惯用法是什么?

如何通过更改现有数据类型来执行Android房间数据库迁移?

在 kotlin 原始字符串中转义三重引号

如何获取@JsonProperty 名称列表?

Kotlin中用于调用常量名称的枚举类方法之间的区别

修改器的属性是什么,我需要更改以使角变圆且宽度更小?喷气背包组合

按钮无法在 Android Studio 上打开新活动

kotest 更改环境变量

从 Kotlin 调用 Java 时可以为空的规则是什么

你怎么知道什么时候需要 yield()?

Kotlin 使用迭代索引过滤 lambda 数组

kotlin-bom 库是做什么的?

当被Spring代理类访问时,Kotlin实例变量为null

Kotlin Native如何将字节数组转换为字符串?

ObjectAnimator.ofFloat 不能直接在kotlin中取Int作为参数

不推荐使用仅限生命周期的LifecycleEvent

使用 Moshi/Retrofit2 访问深度嵌套的 JSON 数组

Kotlin - 如果不为空,则使用修改后的 Obj props 覆盖 Obj props

Kotlin中的嵌套let块