观心静

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

前言

  Jetpack Compose虽然已经逐渐完善,但是其实还是有很多地方未满足需求。比如播放视频、相机预览等等依然需要原来的View。所以目前阶段Jetpack Compose与xml的混合开发非常重要

  官方文档地址:https://developer.android.google.cn/jetpack/compose/migrate/interoperability-apis/views-in-compose?hl=zh-cn

在compose中添加TextView

View与Jetpack Compose进行混合时,主要依靠的是AndroidView

效果图

代码

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        APage()
    }
}

@Composable
fun APage() {
    val timeData = remember {
        mutableStateOf(0L)
    }
    Column(
        Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        //这里在AndroidView的factory构建TextView
        AndroidView(factory = {
            TextView(it).apply {
                text = System.currentTimeMillis().toString()
                textSize = 40f
                setTextColor(android.graphics.Color.WHITE)
            }
        }, modifier = Modifier.background(color = Color.Gray)//这边依然可以使用compose的modifier对View进行配置

            , update = { //update是用来更新AndroidView里的数据的
                it.text = timeData.value.toString()
            })

        //这里举例通过Button更新AndroidView里的数据
        Button(onClick = {
            timeData.value = System.currentTimeMillis()
        }) {
            Text(text = "更新时间")
        }
    }
}

通过ViewBinding导入xml布局

效果图

所需依赖

这个版本是跟随compose的大版本,需要参考你的androidx.compose.ui:ui:  、androidx.compose.ui:ui-tooling: 版本

//androidView binding
implementation("androidx.compose.ui:ui-viewbinding:1.4.3")

此外还需要在build文件中启用viewBinding

android {
    //略...

    defaultConfig {
         //略...
    }
    
    buildFeatures{
        viewBinding = true
    }

    //略...		
}

xml布局

item_user_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ImageView
        android:id="@+id/image"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@mipmap/ic_fruit_apple"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textSize="40sp"
        android:text="名称"
        android:textColor="@color/black"
        app:layout_constraintEnd_toEndOf="@+id/image"
        app:layout_constraintStart_toStartOf="@+id/image"
        app:layout_constraintTop_toBottomOf="@+id/image" />

</androidx.constraintlayout.widget.ConstraintLayout>

代码

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        APage()
    }
}

@Composable
fun APage() {
    val imageRes = remember {
        mutableListOf(R.mipmap.ic_fruit_apple, R.mipmap.ic_fruit_banana,R.mipmap.ic_fruit_coconut)
    }
    val nameData = remember {
        mutableListOf("苹果", "香蕉","椰子")
    }
    val count = remember {
        mutableStateOf(0)
    }
    Column(
        Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        AndroidViewBinding(factory = ItemUserLayoutBinding::inflate) {
            //这里已经是AndroidViewBinding的update参数lambda
            image.setImageResource(imageRes[count.value])
            name.text = nameData[count.value]
            //这里也举例一下,可以在AndroidViewBinding里更新remember的数据
            image.setOnClickListener {
                image.setImageResource(imageRes[count.value])
                name.text = nameData[count.value]
                count.value++
                if (count.value > 2){
                    count.value = 0
                }
            }
        }
        //这是compose的Button,这里举例通过Button更新AndroidViewBinding里的数据
        Button(onClick = {
            count.value++
            if (count.value > 2){
                count.value = 0
            }
        }) {
            Text(text = "更新数据")
        }
    }
}

从Compose调用Android框架

下面的代码通过附带效应DisposableEffect实现了监听音量变化的例子,如果你对附带效应不甚了解可以参考我的博客:Android开发 Jetpack_Compose_6 附带效应

效果图

代码

@Composable
fun APage() {
    val volumeData = remember {
        mutableStateOf(0)
    }
    Column(
        Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        AndroidView(factory = {
            TextView(it).apply {
                setTextColor(android.graphics.Color.BLACK)
                textSize = 50f
            }
        }, update = {
            it.text = volumeData.value.toString()
        })
    }
    val context = LocalContext.current
    DisposableEffect(context){
        val volumeReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                if (intent.action.equals("android.media.VOLUME_CHANGED_ACTION")) {
                    val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
                    val currVolume: Int = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)       // 当前的媒体音量
                    volumeData.value = currVolume
                }
            }
        }
        val filter = IntentFilter()
        filter.addAction("android.media.VOLUME_CHANGED_ACTION")
        context.registerReceiver(volumeReceiver, filter)

        onDispose {
            //注销广播
            context.unregisterReceiver(volumeReceiver)
        }
    }
}

 

end

posted on 2023-08-05 15:34  观心静  阅读(1745)  评论(0编辑  收藏  举报