Jetpack Compose UI预览

news2025/1/18 5:24:59

Android开发 Jetpack_Compose_2 UI预览@Preview

前言

  在学习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的基础库

简单的初步了解预览

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,这里请注意,这里创建的类不能是内部类,否则可能会出现无法预览的问题。

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. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/556869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CAPL(vTESTStudio) - 自动创建带有时间戳的报告和log

目录 getLocalTime - 获取本地时间函数 代码示例 获取当前时间并形成格式:"2023_05_22_23_20_18"

Qt中的坐标系

Qt中的坐标系 Qt中的坐标系与win10上画图工具的联系 上面这个图片的水印挡住了重要信息,然后又截了一张,显然,画图工具的像素就是Qt中的坐标系,所以,以后查坐标系直接打开Qt:画笔位置所显示的像素就是Qt的坐标!!! 再总结一下: 好奇:win10上的画图工具是qt写的吗? 答: 不是…

【SpringCloud】Nacos

文章目录 一、Nacos1、安装2、服务注册和发现3、服务分级存储模型4、负载均衡策略--NacosRule5、服务实例的权重设置 一、Nacos 1、安装 官网&#xff1a;https://nacos.io/zh-cn/ 下载 Github主页: https://github.com/alibaba/nacos Github的Release下载页: https://githu…

linux命令行如何查看命令帮助信息

一&#xff0c;简介 “授之以鱼不如授之以渔”&#xff0c;我们再学习linux命令的时候&#xff0c;想查看某个命令的详细说明&#xff0c;有哪些方法呢&#xff1f;本文来介绍一下如何在命令行查找命令的帮助信息。 二&#xff0c;linux命令格式介绍 Linux命令一般由三部分组…

【深度学习】- 作业1: Softmax实现手写数字识别

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

【深度学习】 - 作业7: 图像超分辨率重建

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

Linux网络编程—Day10

Linux服务器程序规范 Linux服务器程序一般以后台进程形式运行。后台进程又称守护进程。它没有控制终端&#xff0c;因而也不会意外接收到用户输入。 守护进程的父进程通常是init进程&#xff08;PID为1的进程&#xff09;&#xff1b;Linux服务器程序通常有一套日志系统&#…

Android 11.0 系统设置显示主菜单添加屏幕旋转菜单实现旋转屏幕功能

1.前言 在android11.0的系统rom定制化开发中,在对系统设置进行定制开发中,有产品需求要求增加 旋转屏幕功能的菜单,就是在点击旋转屏幕菜单后弹窗显示旋转0度,旋转 90度,旋转180度, 旋转270度针对不同分辨率的无重力感应的大屏设备的屏幕旋转功能的实现, 接下来就来分析…

chatgpt赋能Python-python_dill

Python dill - 更高效&#xff0c;更强大的对象序列化工具 在Python编程中&#xff0c;对象序列化是一个非常常见的操作&#xff0c;它将Python对象转换为可以存储或传输的格式。Python默认提供了pickle模块来实现序列化&#xff0c;但是pickle存在一些限制&#xff0c;比如无…

usb摄像头驱动-core层usb设备的注册

usb摄像头驱动-core层driver.c 文章目录 usb摄像头驱动-core层driver.cusb_bus_typeusb_device_matchusb_uevent usb_register_driver 在ubuntu中接入罗技c920摄像头打印的信息如下&#xff1a; 在内核中&#xff0c;/driver/usb/core/driver.c 文件扮演了 USB 核心驱动程序管…

复现ms17-010漏洞

复现ms17-010 复现条件环境操作效果 让我们来看看“hkl”在干嘛 复现 条件 1.靶机必须为win8以下。 2.靶机必须同攻击机处于相同网段&#xff08;即倒数第二位相同&#xff09;。 3.靶机的445端口必须要开启。 环境 虚拟机kali为攻击机&#xff0c;win7虚拟机为靶机。 kali…

SELECT LAST_INSERT_ID()自增主键冲突或者为0问题

问题 数据库为mysql&#xff1b; mapper.xml文件为mybatis-generator自动生成的&#xff1b; 连接池使用DruidDataSource&#xff1b; 最终生成的insertSelective如下&#xff1a; 出现问题&#xff1a; 主键冲突&#xff1a;[WMyBatisTraceInterceptor:54][com.mysql.jdbc.…

如何定位OOM

造成OOM的原因 定位OOM 针对第一和第二种情况需要定位OOM 系统已经挂了&#xff1a; 通过堆dump文件定位。 当JVM发生OOM时&#xff0c;自动生成DUMP文件&#xff1a; -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath${目录} java -Xms10M -Xmx10M -XX:HeapDumpOnOutOfMemo…

c#中的json数据

JSON数据 数据传输的语言&#xff0c;用于前后端数据交互的语言&#xff0c;注意xml的区别。 json和xml的区别 xml&#xff1a;可扩展标记语言&#xff0c;是一种用于标记电子文件使其具有结构性的标记语言。 json&#xff1a;(JavaScript Object Notation, JS 对象简谱) 是…

昆仲被投企业「鲲游光电」近期完成新一轮数亿元融资,继续致力于探索前沿光电子领域产品与创新应用|昆仲·链

鲲游光电(North Ocean Photonics)是专注于晶圆级光学、光集成领域的高科技企业&#xff0c;总部位于中国上海。依托自身深厚的技术积累、高精度的制造工艺&#xff0c;鲲游光电通过融合集成光学与集成电路的创新思路&#xff0c;致力于探索前沿光子、光电子领域的实现与创新应用…

MyBatis环境搭建配置、增删改查操作、分页、事务操作、动态SQL、缓存机制、注解开发

MyBatis 文章目录 MyBatisXML语言简介用途各部分注解声明元素属性注释CDATA转义字符 搭建环境读取实体类创建实体与映射关系的文件 配置MyBatis创建工具类接口实现 Mybatis工作流程增删改查指定映射规则指定构造方法字段名称带下划线处理条件查询插入数据复杂查询和事务一对多查…

Codeforces Round 860 (Div. 2)

A Showstopper 题意&#xff1a;给你两个长度为n的数组a和b&#xff0c;每次操作你可以互换a[i]与b[i]&#xff0c;问最终能否满足 思路&#xff1a;若a[i]>b[i]&#xff0c;我们就进行操作。这样数组b元素都是较大的&#xff0c; 一定比不操作更优。最后判断是否满足条件…

Python中的异常处理机制

什么是异常与异常处理 异常就是错误 异常会导致程序崩溃并停止运行 能监控并捕获到异常&#xff0c;将异常部位的程序进行修理使得程序继续正常运行 异常的语法结构 try:<代码块1> 被try关键字检查并保护的业务代码except <异常的类型>:<代码块2> # 代码…

Mybatis源码细节探究:sqlSessionFactory.openSession()这个方法到底发生了什么?

给自己的每日一句 不从恶人的计谋&#xff0c;不站罪人的道路&#xff0c;不坐亵慢人的座位&#xff0c;惟喜爱耶和华的律法&#xff0c;昼夜思想&#xff0c;这人便为有福&#xff01;他要像一棵树栽在溪水旁&#xff0c;按时候结果子&#xff0c;叶子也不枯干。凡他所做的尽…

【笔记】【Javascript】浅面了解原型和原型链

前言 原型和原型链是学习前端必备知识笔记中有些个人理解后整理的笔记&#xff0c;可能有所偏差&#xff0c;也恳请读者帮忙指出&#xff0c;谢谢。 免责声明 为了方便&#xff0c;本文中使用的部分图片来自于网络&#xff0c;如有侵权,请联系博主进行删除&#xff0c;感谢其…