compose UI(二)融合老代码,使用非compose的view简单示例(MPAndroidChart)

compose 部分

先附一个官方教程链接

核心是一个AndroidView,AndroidView也是一个@Composable,他的factory方法可以接收一个非compose 的view。官方示例的核心代码是这一段:

/**
 * ****************compose ui 中使用未实现compose版本ui的关键
AndroidView采用以编程方式创建的View。如果您想嵌入XML文件,
则可以使用androidx.compose.ui:ui-viewbinding库中的视图绑定和AndroidViewBinding API来使用
 */
@Composable
private fun PlantDescription(description: String) {
    val htmlDescription = remember(description) {
        HtmlCompat.fromHtml(description,HtmlCompat.FROM_HTML_MODE_COMPACT)
    }
    AndroidView(factory = { context -> TextView(context).apply {
        movementMethod = LinkMovementMethod.getInstance()
    }
    },
        update = {
            it.text = htmlDescription
        }
    )
    //在显示时在屏幕上显示TextView并使用HTML描述进行更新
	// 更新htmlDescription将使AndroidView重构并更新文本
}

TextView 有对富文本的实现,现有(1.0.0-bate06)的compose 并没有现有的实现。

示例部分(MPAndroidChart):

先附一个MPAndroidChart的GitHub
所有的写法应以官网文档为准。

首先,利用AndroidView,建立一个chart对象,我们以普通的LineChart为示例。compose UI不需要xml部分,可以把AndroidView的factory 简单理解为xml的放置操作。当然之前在代码部分初始化的内容也可以放置在里面。
简单代码示例:

		AndroidView(
            factory = { context ->
                LineChart(context).apply {
                    lineChart = this
                    this.setViewPortOffsets(0F, 0F, 0F, 0F)
                    this.setBackgroundColor(0XFFFFFF)
                    //说明文字
                    this.description.isEnabled = false
                    // 启用触摸手势
                    this.setTouchEnabled(true)
                    // 启用缩放和拖动
                    this.isDragEnabled = true
                    this.setScaleEnabled(true)
                    // 如果禁用,则可以分别在x轴和y轴上进行缩放
                    this.setPinchZoom(false)
                    this.setDrawGridBackground(false)
                    this.maxHighlightDistance = 300f

                    val x = this.xAxis
                    x.isEnabled = false

                    val y = this.axisLeft
                    //y.typeface = tfLight
                    y.setLabelCount(6, false)
                    y.textColor = Color.WHITE
                    y.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART)
                    y.setDrawGridLines(false)
                    y.axisLineColor = Color.WHITE

                    this.axisRight.isEnabled = false
                    
                    this.legend.isEnabled = false
                    //this.animateXY(1500, 1500)

                }
            },
            update = {
                if (setData(it, value)) {
                    it.data.dataSets[0].setDrawValues(true)
                }
                Timber.i("update chart")
                //it.legend.isEnabled = false
                it.animateXY(1500, 1500)
            },
            modifier = Modifier
                .fillMaxWidth()
                .fillMaxHeight()
        )

factory 结束之后是会执行update ,关系就像oncreate跟onstart.
上面代码有2个问题:

  1. 是setData(it, value) 是一个fun ,
  2. 是MPAndroidChart的刷新代码是animateXY()方法,update的绑定甚至不能触发。

刷新视图可以把对象生域,然后在外面手动调用setData() 和 animateXY () 方法,这里贴一个测试刷新的代码:

//todo test
    GlobalScope.launch {
        delay(6000)
        Timber.i("change value")
        value = value2
        if (setData(lineChart!!, value)) {
            lineChart!!.data.dataSets[0].setDrawValues(true)
        }
        withContext(Dispatchers.Main){
            lineChart?.animateXY(1500, 1500)
        }

    }

至于setData()方法,fun 里面是可以再fun 的,只不过跟c语言一样,要写在使用的前面。具体setData方法,可以参考MPAndroidChart官方文档。

5月28日修正:

MPAndroidChart 引入livedata后可以触发update,所以修正部分代码:

		val value by ViewModel.data.observeAsState()
		......
			update = {
			//给默认值可以去掉空判断
                value?.let { value->
                    if (setData(it, value)) {
                        it.data.dataSets[0].setDrawValues(true)
                    }
                    it.animateXY(1500, 1500)
                }
            }

GlobalScope.launch 不是compose ui 中调用协程的正确方式推荐使用LaunchedEffect()

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值