观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

前言

  在学习jetpack compose如何编写ui之前,我认为还是应该先了解与Android studio配合的UI预览@Preview。 这样就可以立刻看到UI效果,从而方便后续学习验证代码。

所需依赖

配合此章博客必须的依赖如下

    implementation "androidx.compose.ui:ui:1.2.1"                       //ui基础库 - 重要
    implementation "androidx.compose.ui:ui-tooling:1.2.1"               //ui工具基础库 - 重要
    implementation "androidx.compose.foundation:foundation:1.2.1"       //基础库 - 重要
    implementation "androidx.activity:activity-compose:1.5.1"           //配合activity使用的基础库 - 重要
    implementation "androidx.compose.ui:ui-tooling-preview:1.2.1"       //在Android studio里预览ui的基础库

Android Studio版本要求

请将Android Studio更新到Dolphin海豚版本

简单的初步了解预览

代码

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            //将MyText添加到Activity里
            MyText()
        }
    }

    @Preview    //在方法上增加@Preview    表明我们需要预览这个方法里的View
    @Composable //在方法上增加@Composable 表面这是compose的ui方法,增加后才能在方法里添加compose的View
    fun MyText(){
        Text(text = "Hello World", color = Color.White)
    }
}

Android studio中的预览

根据条件选择在Android Studio预览效果与设备上运行的UI效果 

下面的代码中判断的关键是LocalInspectionMode.current。 用来区分是在Android Studio上还是在设备上的效果。在项目中的实际意义是填充一些模拟数据方便查看预览ui效果。 比如给Image设置一张占位图或者给列表填充一些模拟数据。

代码:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyText()
        }
    }

    @Preview
    @Composable
    fun MyText(){
        if (LocalInspectionMode.current){
            //在Android studio中显示预览的ui
            Text(text = "android studio preview", color = Color.Red)
        } else {
            //实际在设备上显示的ui
            Text(text = "device run ui", color = Color.Red)
        }
    }
}

在Android studio上的效果图:

在设备上的效果图:

 

快速部署预览

Preview支持快速部署预览,这个功能解决的痛点是,在我们需要预览一些UI层级很深的页面时,每次都要去在设备上一个一个点击跳转到目标页面查看UI效果。这个特别费时费力,现在只需要按照下图点击就可立即在设备上显示当前页面。

这功能可以说是半个热加载...

可能出现的报错

 这可能应该是Android Studio的Bug,现在每次使用这个功能都需要build一下preview,在点击 build编译一下然后在点击上面的设备图标就行了。

一个方便使用的细节

你在某个activity里使用过一次快速部署预览功能后,在如下图中会自动生成一份预览文件选项。后续只要选择某个compose 方法的预览,点击运行就可以在设备上快速部署预览。

另外请注意!你需要及时清理掉一些失效的预览,这样可以防止创建新的并且相同名称的预览后,在尝试运行时却提示找不到文件,如下图所示:

      >>>>>>     

互动模式

借助互动模式,您可以采用类似于在设备上互动的方式与预览互动。互动模式被隔离在沙盒环境中(与其他预览隔离),在该模式下,您可以在预览中点击元素并输入用户输入;预览甚至还可以播放动画。通过使用这种模式,您可以快速测试可组合项的不同状态和手势,例如勾选或清空复选框。

预览互动模式直接在 Android Studio 中运行,并未运行模拟器,因此存在一些限制:

  • 无法访问网络
  • 无法访问文件

具体开启操作与体验如下图片:

 

@Preview的属性讲解

name

添加name的意义是,可以在预览页面增加名称区分。在有多个Compose方法需要预览的时候可以快速区分。另外预览@Preview 可以多个组合一起同时对一个Compose方法进行预览(比如同时创建平板设备与手机设备的显示效果,或者是不同文字缩放比例的显示效果),从而区分对应配置的预览。组合预览会在下面详细讲解,这里只是引用强调name的意义。最后建议一定需要给每一个@Preview添加name。

如图参考:

group

 group的作用是将若干Compose的方法进行分组,分组后可以选择只显示某个组别的View。这点google的官方文档真是啥都没说让人无语。

代码:

@Preview(name = "文本1", group = "文本组1")
@Composable
fun MyText1() {
    Text(text = "文本1", color = Color.White)
}

@Preview(name = "文本2", group = "文本组2")
@Composable
fun MyText2() {
    Text(text = "文本2", color = Color.Yellow)
}

@Preview(name = "文本3", group = "文本组2")
@Composable
fun MyText3() {
    Text(text = "文本3", color = Color.Red)
}

效果如下动图:

widthDp 与 heightDp

Android studio预览ui上设置预览的容器大小

代码:

@Preview(name = "文本1", widthDp = 50, heightDp = 100)
@Composable
fun MyText1() {
    Text(text = "文本1", color = Color.White)
}

@Preview(name = "文本2", widthDp = 100, heightDp = 50)
@Composable
fun MyText2() {
    Text(text = "文本2", color = Color.White)
}

效果图:

locale

Android studio预览ui上设置语言-地区显示预览

代码:

@Preview(name = "文本1", locale = "en")
@Composable
fun MyText1() {
    Text(text = stringResource(id = R.string.hello_world), color = Color.White)
}

@Preview(name = "文本2", locale = "zh")
@Composable
fun MyText2() {
    Text(text = stringResource(id = R.string.hello_world), color = Color.White)
}

效果图:

fontScale

Android studio预览ui上设置文字缩放比例 

代码:

@Preview(name = "文本1", fontScale = 0.8f)
@Composable
fun MyText1() {
    Text(text = stringResource(id = R.string.hello_world), color = Color.White)
}

@Preview(name = "文本2", fontScale = 1.5f)
@Composable
fun MyText2() {
    Text(text = stringResource(id = R.string.hello_world), color = Color.White)
}

效果图:

showSystemUi

Android studio预览ui上显示设备的状态栏和操作栏

代码:

@Preview(name = "文本1", showSystemUi = true)
@Composable
fun MyText1() {
    Text(text = stringResource(id = R.string.hello_world), color = Color.Black)
}

效果图:

 

backgroundColor 与 showBackground  

backgroundColor  通常与 showBackground 组合在一起使用,一个是设置Android studio预览ui背景颜色,一个是开启or关闭背景显示

代码:

@Preview(name = "文本1", showBackground = true, backgroundColor = 0xFFF44336)
@Composable
fun MyText1() {
    Color(0xFFF44336)
    Text(text = stringResource(id = R.string.hello_world), color = Color.White)
}

效果动图:

 

uiMode

设置Android studio预览ui模式,比如夜间模式 

代码:

    /**
     * UI_MODE_TYPE_UNDEFINED       未定义
     * UI_MODE_TYPE_NORMAL          正常模式
     * UI_MODE_TYPE_DESK            工作模式
     * UI_MODE_TYPE_CAR,            汽车模式
     * UI_MODE_TYPE_TELEVISION,     电视设备
     * UI_MODE_TYPE_APPLIANCE,      便携设备
     * UI_MODE_TYPE_WATCH,          手表设备
     * UI_MODE_TYPE_VR_HEADSET.     VR设备
     * UI_MODE_NIGHT_MASK.          夜间模式
     * UI_MODE_NIGHT_UNDEFINED.     夜间未定义
     * UI_MODE_NIGHT_NO.            白天模式
     * UI_MODE_NIGHT_YES.           黑夜模式
     */
    @Preview(name = "文本1", uiMode = Configuration.UI_MODE_NIGHT_YES)
    @Composable
    fun MyText1() {
        Text(text = stringResource(id = R.string.hello_world),
            fontSize = 24.sp,
            color = Color.Gray,
            modifier = Modifier.background(Color.Black))
    }

device

指定在Android studio中预览的设备样式

@Preview(name = "文本1", device = Devices.WEAR_OS_LARGE_ROUND)
@Composable
fun MyText1() {
    Text(
        text = stringResource(id = R.string.hello_world),
        fontSize = 24.sp,
        color = Color.Gray,
        modifier = Modifier.background(Color.Black)
    )
}

其他device参数

const val DEFAULT = ""

const val NEXUS_7 = "id:Nexus 7"
const val NEXUS_7_2013 = "id:Nexus 7 2013"
const val NEXUS_5 = "id:Nexus 5"
const val NEXUS_6 = "id:Nexus 6"
const val NEXUS_9 = "id:Nexus 9"
const val NEXUS_10 = "name:Nexus 10"
const val NEXUS_5X = "id:Nexus 5X"
const val NEXUS_6P = "id:Nexus 6P"
const val PIXEL_C = "id:pixel_c"
const val PIXEL = "id:pixel"
const val PIXEL_XL = "id:pixel_xl"
const val PIXEL_2 = "id:pixel_2"
const val PIXEL_2_XL = "id:pixel_2_xl"
const val PIXEL_3 = "id:pixel_3"
const val PIXEL_3_XL = "id:pixel_3_xl"
const val PIXEL_3A = "id:pixel_3a"
const val PIXEL_3A_XL = "id:pixel_3a_xl"
const val PIXEL_4 = "id:pixel_4"
const val PIXEL_4_XL = "id:pixel_4_xl"

const val AUTOMOTIVE_1024p = "id:automotive_1024p_landscape"

const val WEAR_OS_LARGE_ROUND = "id:wearos_large_round"
const val WEAR_OS_SMALL_ROUND = "id:wearos_small_round"
const val WEAR_OS_SQUARE = "id:wearos_square"
const val WEAR_OS_RECT = "id:wearos_rect"

// Reference devices
const val PHONE = "spec:id=reference_phone,shape=Normal,width=411,height=891,unit=dp,dpi=420"
const val FOLDABLE = "spec:shape=Normal,width=673,height=841,unit=dp,dpi=480"
const val TABLET = "spec:shape=Normal,width=1280,height=800,unit=dp,dpi=420"
const val DESKTOP = "spec:shape=Normal,width=1920,height=1080,unit=dp,dpi=420"

Multipreview  自定义预览注解

注意:此功能从 Android Studio Dolphin 和 Jetpack Compose 1.2.0-beta01 开始提供

简单的说,这个功能其实是多个@Preview 自定义组合在一起,这样你可以配置属于你需求的@Preview 。并且可以选择满足在不同条件下的ui预览。

代码:

class DeploymentActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyText1()
        }
    }

    @LandscapeAndPortraitPreviews
    @Composable
    fun MyText1() {
        Text(
            text = stringResource(id = R.string.hello_world),
            fontSize = 24.sp,
            color = Color.White,
            modifier = Modifier.background(Color.Black)
        )
    }
}

@Preview(
    name = "横屏",
    group = "横屏组",
    fontScale = 0.5f,
    widthDp = 1280,
    heightDp = 720
)
@Preview(
    name = "竖屏",
    group = "竖屏组",
    fontScale = 1.5f,
    widthDp = 720,
    heightDp = 1280
)
annotation class LandscapeAndPortraitPreviews

效果图:

@PreviewParameter 带参数预览

在正常开发中,我们经常会需要给Composable方法传入数据参数(注意,这里的参数是指数据类型,如果你传入Composable的一些参数例如Modifier则没问题)。但是我们添加预览后会出现如下报错提示:

这里需要给name这个String参数添加@PreviewParameter注释。

首先我们需要创建预览数据提供PreviewParameterProvider,这里请注意,这里创建的类不能是内部类,否则可能会出现无法预览的问题(估计Android studio是路径识别的问题,就不纠结了)

class NameProvider : PreviewParameterProvider<String> {
    override val values: Sequence<String> get() = listOf("苹果","香蕉","西瓜","葡萄").asSequence()
}

把PreviewParameterProvider添加到Composable方法里

@Preview(device = Devices.AUTOMOTIVE_1024p)
@Composable
fun TextDemo(@PreviewParameter(NameProvider::class, 1) name: String) {
    Text(text = name)
}

 预览效果图:

@PreviewParameter的参数limit

在上面的例子可以看到,在传入了 NameProvider 这个类后,还传入了一个Int值。 这个值与我们实现的NameProvider 的数据是集合有关。修改limit会自动生产集合里其他数据的预览,参考动图如下:

@PreviewParameter 集合数据预览

举例一个更复杂一点点的使用情况

PreviewParameterProvider数据代码:

class ImageProvider : PreviewParameterProvider<SnapshotStateList<Int>> {
    override val values: Sequence<SnapshotStateList<Int>>
        get() = listOf(
            mutableStateListOf(
                R.mipmap.copybook_1,
                R.mipmap.copybook_1,
                R.mipmap.copybook_1
            )
        ).asSequence()
}

Composable方法添加预览数据

@Preview(device = Devices.AUTOMOTIVE_1024p)
@Composable
private fun ImageList(@PreviewParameter(ImageProvider::class, 1) list: SnapshotStateList<Int>) {
    Column {
        LazyVerticalGrid(
            columns = GridCells.Adaptive(minSize = 200.dp),
            verticalArrangement = Arrangement.spacedBy(20.dp),
            horizontalArrangement = Arrangement.spacedBy(20.dp),
            contentPadding = PaddingValues(top = 20.dp, start = 20.dp, end = 20.dp)
        ) {
            items(list.size) { index ->
                Image(painter = painterResource(list[index]), contentDescription = null)
            }
        }
    }
}

预览效果图:

 

 

 

End

posted on 2022-10-11 10:34  观心静  阅读(1846)  评论(0编辑  收藏  举报