Compose尝鲜体验(三)

284 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

Compose尝鲜体验(三)

Compose 常规使用

1、布局

Row Column Box ConstraintLayout

2、Modifier

modifier=Modifier.clip(RoundedCornerShape())

3、脚手架 Scaffold

Scaffold允许您使用基本的 Material Design 布局结构来实现 UI。它为最常见的顶级 Material 组件提供了插槽,例如 TopAppBarBottomAppBarFloatingActionButtonDrawer。使用Scaffold,您可以确保这些组件正确定位并协同工作。

kotlin
Scaffold(topBar = {
	TopAppBar(
		title = {
			Text(text = "LayoutsCodelab")
		}, actions = {
			IconButton(onClick = { /*TODO*/ }) {
			Icon(Icons.Filled.Favorite, contentDescription = null)
		}
	}
)
}

4、自定义布局

使用layout修改器手动控制如何测量和定位元素。通常,自定义layout修饰符的常见结构如下:

kotlin
/**
*measurable 要测量和放置的孩子
*constraints 孩子的宽度和高度的最小值和最大值
*/
fun Modifier.customLayoutModifier(...) = Modifier.layout { measurable, constraints ->
  ...
})

5、约束布局

 kotlin
 ConstraintLayout {
 	//给每个@composeable关联一个引用
  	val (btn_next1,btn_next2,text) = createRefs()
  	//使用constrainAs提供约束,该修饰符将引用作为修饰符
  	nextStepButton(buttonName = "下一步",
	 modifier =Modifier.constrainAs(btn_next1){
  		//使用linkTo或其他有用的方法指定约束
 		top.linkTo(parent.top,margin = 20.dp)
 	}) {

   }
   Text(text = "text", Modifier.constrainAs(text) {
 		top.linkTo(btn_next1.bottom,margin = 20.dp)
     /*
     *Dimension的行为
     *preferredWrapContent 内容自适应,但受约束条件影响,也就是说,当宽小于约束条件下可用的		 *宽时,则view的宽就是自身的宽,但大于的时候,则受约束条件影响。
     *fillToConstraints 填充约束条件下所剩的可用空间
     *wrapContent 内容自适应,不受约束条件影响
     *preferredValue 指定固定值大小,受约束条件影响。
     *value 指定固定值大小,不受约束条件影响。
     */
 	width = Dimension.preferredWrapContent
 	centerAround(btn_next1.end)
})
   nextStepButton(buttonName = "取消",
	 modifier =Modifier.constrainAs(btn_next2){
   		top.linkTo(parent.top,margin = 20.dp)
   		start.linkTo(btn_next1.end,margin = 10.dp)
	}) {

  }
}

6、指定组合项透明程度Alpha

kotlin
//ContentAlpha 标准 alpha 值 ( high, medium, disabled)
ompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Text(
text = text,
modifier = modifier
)


kotlin
/** 下一步按钮
 * @param buttonName 按钮名称
 * @param modifier 按钮附加修饰符
 * @param onclick 按钮单击事件
 * **/
@Composable
fun nextStepButton(buttonName: String,modifier: Modifier, onclick: () -> Unit) {
    Button(
        onClick = onclick,
        modifier = modifier
            .clip(RoundedCornerShape(15.dp))
            .width(200.dp),
        colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFFFD5D59)
            ,contentColor = Color(0xffffffff)),
    ) {
        Text(text = buttonName)
    }
}

7、Compose状态

8、网络加载库Coil\Glide

添加Glide Compose依赖
//glide
implementation "com.google.accompanist:accompanist-glide:0.12.0"

/**Glide使用**/
/**
 * @param modifier 外部传入Image的大小
 * @param placeholder 占位图,默认是 R.drawable.loadding
 */
@OptIn(ExperimentalCoilApi::class)
@Composable
fun UrlImage(
    modifier: Modifier = Modifier,
    url: Any? = null,
    @DrawableRes resId:Int? = null,
    contentScale: ContentScale = ContentScale.Crop,
) {
    val painter = if (resId != null)
        painterResource(id = resId)
    else {
        rememberGlidePainter(request = url,fadeIn = true)
    }
    Image(
        painter = painter,
        contentDescription = null,
        modifier = modifier,
        contentScale = contentScale,
    )
}

​ ​ //Coli 添加依赖 ​ implementation("io.coil-kt:coil-compose:1.4.0") ​ /Coli使用/ Image( painter = rememberCoilPainter( request = "picsum.photos/300/300", requestBuilder = { transformations(CircleCropTransformation()) }, ), contentDescription = stringResource(R.string.image_content_desc), ) Glide和Coli对比 Glide:可以设置动画 并且支持Gif、SVG等格式的图片不需要添加其他依赖库 Coli:Google官网推的网络图片加载库,偶尔会出现图片加载不出来的情况,没有图片的动画

9、在Compose中做屏幕适配

//屏幕适配是通过获取设备屏幕像素
object ScreenConfigInfo {
    //设计图宽高px
    private const val designWidthDp = 1280f
    private const val designHeightDp = 720f

    //高度比例
    var heightFactor = 0f

    //屏幕密度
    var scale = 0f

    //宽度比例
    var  widthFactor = 0f

​ ​ @Composable ​ fun initScreenConfigInfo() { ​ val config = LocalConfiguration.current ​ val widthDp = config.screenWidthDp.toFloat() val heightDp = config.screenHeightDp.toFloat()

        scale = config.densityDpi/160f

        if (heightFactor == 0f) heightFactor = heightDp / designHeightDp
        if (widthFactor == 0f) widthFactor = widthDp / designWidthDp

    }
}
//宽度适配
inline val Int.wdp: Dp
    get() {
        val result = this.toFloat() * widthFactor
        return Dp(value = result)
    }
//高度适配
@Stable
inline val Int.hdp: Dp
    get() {
        val result = this.toFloat() * heightFactor
        return Dp(value = result)
    }
//字体适配
@Stable
inline val Int.spi:TextUnit
    get() {
        return this* heightFactor.sp
}
//在主题中进行工具类初始化
@Composable
fun HolderStoreAioTheme(
    content: @Composable() () -> Unit
) {
    //初始化屏幕宽高
    ScreenConfigInfo.initScreenConfigInfo()
}

10、在Compose中使用Android原生控件

AndroidView(
    //Compose修改器
    modifier = Modifier
        .fillMaxSize()
        .padding(start = 5.wdp),
    factory = { context ->
         //Android 原生控件
        EditText(context).apply {
            isFocusable = true
            isFocusableInTouchMode = true
            showSoftInputOnFocus = false
        }
    },
    update = { view ->
        //Android 更新响应      
        view.setText(text)
        view.setTextColor(ContextCompat.getColor(context, R.color.black272727))
        view.textSize = 16.spi.value

        view.setSelection(text.length)
        view.hint = placeHolder
        view.setHintTextColor((ContextCompat.getColor(context, R.color.gray9A9A9A)))

        // view.setTextCursorDrawable(ContextCompat.getDrawable(context, R.drawable.cursor_color))
        view.background = null
        if (!isVisible) view.transformationMethod = PasswordTransformationMethod.getInstance()
        view.inputType = TYPE_MASK_VARIATION
        view.setOnTouchListener { v, event ->
            onItemClick()
            false
        }
    }
)