构建用户界面声明是网络社区广泛采用的东西,如今,按照这些原则构建了大型应用程序。例如,Google推出了JetPack Compose,Apple在WWDC19宣布了Swiftui,并收到了开发人员的极为积极回应。
在Valor Software,我们总是对开发技术的新进步感到兴奋,并且我们是NativeScript的粉丝。我们与Nstudio合作,为由NativeScript驱动的Android应用程序提供有效且愉快的JetPack组成。
本月早些时候,我们宣布了SwiftUI for NativeScript,该SwiftUI for NativeScript遵循与JetPack撰写的API设计相同的原理和API设计。
在本文中,我们将演示如何在NativeScript中使用JetPack撰写,以探索有趣的新可能性。
创建一个Antivescript应用程序
我们可以使用标准打字稿模板创建应用程序:
ns create jetpackcompose --ts
cd jetpackcompose
这将设置通常称为“香草”调味的nativesscript应用程序的内容。不过,您可以使用最适合的风味。将插件设置为Angular(和大多数其他口味)通常是注册视图的情况,我们将在下面的一节中演示。
安装JetPack组成的插件:
npm install @nativescript/jetpack-compose
注意: JetPack组成需要您至少使用API 21(Lollipop)作为最低SDK版本。您可以通过将minSdkVersion 21
添加到您的app.gradle。
如果您打算直接从Android Studio构建库,则不需要其他任何东西,只需将构建的.aar
放入App_Resources/Android/libs/
中,然后跳到下一节即可。但是,如果您打算直接在App_Resources/Android/src/main/java
中的.kt
文件中编写Kotlin代码,那么我们需要一些额外的步骤。
首先,在app.gradle
中添加您的撰写依赖项:
dependencies {
def compose_version = "1.2.1"
implementation "androidx.compose.ui:ui:$compose_version"
// Tooling support (Previews, etc.)
implementation "androidx.compose.ui:ui-tooling:$compose_version"
// Add any other dependencies your Jetpack Compose UI needs
// like material design:
// implementation 'androidx.compose.material:material:$compose_version'
}
然后修改android
节,以便您启用撰写:
android {
// other settings like targetSdk, etc.
buildFeatures {
compose true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
composeOptions {
kotlinCompilerExtensionVersion '1.3.2'
}
}
最后,通过创建文件App_Resources/Android/gradle.properties
启用kotlin
useKotlin=true
kotlinVersion=1.7.20 # you can choose your kotlin version here
JetPack构成用法
a。创建您的JetPack创作视图和包装器
创建App_Resources/Android/src/main/java/BasicView.kt
:
package com.example
import android.content.Context
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.setValue
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
class BasicView {
fun generateComposeView(view: ComposeView): ComposeView {
return view.apply {
setContent {
MaterialTheme {
Text("Hello from Jetpack Compose")
}
}
}
}
fun updateData(value: Map<Any, Any>) {
}
var onEvent: ((String) -> Unit)? = null
}
要使用组合视图的默认插件处理,您的实现必须遵循以下接口:
class Example {
fun generateComposeView(view: ComposeView): ComposeView {
// render your compose views into the ComposeView
}
fun updateData(value: Map<Any, Any>) {
// this function receives data from NativeScript
// value is a js object converted to a map
}
// this is the event you will send back to Jetpack Compose
// when you need to pass data, just call onEvent?.invoke(v)
var onEvent: ((Any) -> Unit)? = null
}
b。通过composeId
这可以在NativeScript应用程序的Bootstrap文件(通常是app.ts
或main.ts
)中完成。
import { registerJetpackCompose, ComposeDataDriver } from '@nativescript/jetpack-compose';
// A. You can generate types for your own Compose Provider with 'ns typings android --aar {path/to/{name}.aar}'
// B. Otherwise you can ignore by declaring the package resolution path you know you provided
declare var com;
registerJetpackCompose('sampleView', (view) => new ComposeDataDriver(new com.example.BasicView(), view));
此外,如果要使用Angular,则可以注册组合视图本身:
import { registerElement } from '@nativescript/angular';
import { JetpackCompose } from '@nativescript/jetpack-compose';
registerElement('JetpackCompose', () => JetpackCompose)
c。插入任何nativescript布局
app/main-page.xml
<Page
xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:jc="@nativescript/jetpack-compose"
class="page">
<StackLayout>
<jc:JetpackCompose composeId="sampleView" height="100" />
</StackLayout>
</Page>
您现在可以使用ns debug android
运行该应用。
使用Android Studio开发和预览JetPack撰写
运行应用程序后,一旦您可以在Android Studio中打开platforms/android
文件夹,您可以在其中找到BasicView.kt
文件。从那里,您可以开始修改它并预览更改(通过在要预览的@Composable
上添加@Preview
Decorator)。
很重要:保存此文件不会更改生活在App_Resources
中的BasicView.kt
,因此,一旦完成编辑,请非常小心地复制文件内容!这将成为未来的DX改进。
另外,您可以create a new Android library并在那里开发所有的JetPack构成视图。
将数据发送和接收到/从NativeScript发送
首先,让我们在我们的基本视图中添加一些绑定,因此它现在在updateData
中接收数据并显示该数据,并在数据更新后输出事件:
package com.example
import android.content.Context
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.setValue
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
class BasicView {
data class ExampleUiState(
val text: String = ""
) {}
class ExampleViewModel(
) : ViewModel() {
var uiState by mutableStateOf(ExampleUiState())
}
var mViewModel = ExampleViewModel()
fun generateComposeView(view: ComposeView): ComposeView {
return view.apply {
setContent {
MaterialTheme {
val uiState = mViewModel.uiState;
// In Compose world
Text(uiState.text)
}
}
}
}
fun updateData(value: Map<Any, Any>) {
val v = value["data"] as String;
onEvent?.invoke(v)
mViewModel.uiState = ExampleUiState(v);
}
var onEvent: ((String) -> Unit)? = null
}
在Nativescript布局中使用您的JetPack组合
app/main-page.xml:
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page"
xmlns:jc="@nativescript/jetpack-compose">
<StackLayout>
<Label text="The following view is Jetpack Compose inside NativeScript!" textWrap="true"></Label>
<jc:JetpackCompose composeEvent="{{ onEvent }}" data="{{ text }}" composeId="sampleView"></sw:JetpackCompose>
<Label text="This is NativeScript again"></Label>
<TextView textChange="{{ onTextChange }}" text="{{ text }}" textWrap="true"></TextView>
</StackLayout>
</Page>
app/main-page.ts:
import { Observable } from '@nativescript/core';
import { registerJetpackCompose, ComposeDataDriver } from '@nativescript/jetpack-compose';
import { EventData, Page, PropertyChangeData } from '@nativescript/core';
// A. You can generate types for your own Compose Provider with 'ns typings android --aar {path/to/{name}.aar}'
// B. Otherwise you can ignore by declaring the package resolution path you know you provided
declare var com;
registerJetpackCompose('sampleView', (view) => new ComposeDataDriver(new com.example.BasicView(), view));
export function navigatingTo(args: EventData) {
const page = <Page>args.object;
page.bindingContext = new DemoModel();
}
export class DemoModel extends Observable {
text = '';
onEvent(evt: JetpackComposeEventData<string>) {
console.log('onEvent', evt.data);
}
onTextChange(evt: PropertyChangeData) {
console.log('textChange', evt.value);
this.set('text', evt.value);
}
}
现在,每次您更改nativescript TextView
上的文本时,它都会更新JetPack撰写视图上的文本!
颜色点示例
这是我使用colorPicker更改NativeScript视图的背景颜色的另一个示例:
app.gradle
implementation "com.github.skydoves:colorpicker-compose:1.0.0"
package com.example
import android.content.Context
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
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.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import com.github.skydoves.colorpicker.compose.ColorEnvelope
import com.github.skydoves.colorpicker.compose.HsvColorPicker
import com.github.skydoves.colorpicker.compose.ImageColorPicker
import com.github.skydoves.colorpicker.compose.rememberColorPickerController
class ColorPickerCompose {
fun generateComposeView(view: ComposeView): ComposeView {
return view.apply {
setContent {
val controller = rememberColorPickerController()
HsvColorPicker(
modifier = Modifier
.fillMaxWidth()
.height(450.dp)
.padding(10.dp),
controller = controller,
onColorChanged = { colorEnvelope: ColorEnvelope ->
onEvent?.invoke(colorEnvelope.hexCode)
}
)
}
}
}
fun updateData(value: Map<Any, Any>) {}
var onEvent: ((String) -> Unit)? = null
}
<StackLayout backgroundColor="{{ backgroundColor }}">
<Label text="The following view is Jetpack Compose inside NativeScript!" textWrap="true"></Label>
<StackLayout backgroundColor="lightblue">
<jc:JetpackCompose composeEvent="{{ onEvent }}" data="{{ text }}" composeId="jetpackCompose"></sw:JetpackCompose>
</StackLayout>
<Label text="This is NativeScript again"></Label>
<TextView text="{{ backgroundColor }}" textWrap="true"></TextView>
</StackLayout>
最终考虑
与JetPack合作在NativeScript中构成非常透明且容易。我们期待着看到社区将在NativeScript的腰带中使用另一个功能强大的工具!
来建立什么!关于Valor软件:
官方的Nativecript专业支持合作伙伴Valor正在积极为Nativecript生态系统做出贡献,提供企业支持,咨询和团队增强。 Valor软件还可以帮助SDLC,Web,后端和移动设备的各个方面。如果您需要帮助,请立即预订call11或通过sales@valor-software.com给我们发送电子邮件。