Android kotlin的 Views-DSL的看法
2023-05-11 本文已影响0人
海龙lv
伴随着时间的流逝,公司项目的功能也基本上趋于稳定,所以空闲的时间也就多了起来,就想着写写安卓原生,来将自己负责的公司项目的相关的功能用安卓来写一下,因为之前是写过Jetpack Compose的,但是现在看来,还是不太和当前的现实契合。比如版本,比如很多公司用的还是安卓原先的框架,甚至很多是用Java的,所以Jetpack Compose虽然更加的优秀,奈何现实如此,只能从头研究先前的框架了
因为自己主攻iOS,一般的来说UI布局用的也是代码来实现,现在安卓要用XML,倒不是感觉难,因为自己也会Vue,只是感觉和iOS的开发有点突兀,并且布局如果和数据相关的话,就感觉很呆,还有Views DSL vs xml layouts
所以我就学习了一种代码布局的框架——Views DSL,这样一来,就能和写iOS一样了,用代码进行布局。这个框架还是谷歌官方推荐的(当然最推荐的还是Jetpack Compose...)。
最蛋疼的一个问题是,网上相关的中尉教程我没有找到,顶多是将官网的英文翻译一下,而且,官网的文档写的也是言简意赅,让人味同嚼蜡,苦不堪言,所以我自己总结了下使用的经验,共同学习。
和iOS一样,因为主要使用的Masonry框架,相对于安卓来讲,布局就很多,什么FrameLayout、LinearLayout... 也感觉有点乱套,还是觉得ConstraintLayout感觉更加的顺手。这个框架可以用代码进行创建常用的UI控件,比如TextView、Button、ImageView、EditTextView等,可以方便的进行创建UI,结合Views DSL ConstraintLayout可以很顺利的进行UI的创建、布局。
例子:下面的是DSL创建的ImageView,并且用的ConstraintLayout进行的布局
// 放大镜
val glass = imageView {
imageResource = R.drawable.searchggla
scaleType = ImageView.ScaleType.CENTER_CROP
}
searchBg.add(glass, glass.constraintLayout().lParams {
width = 20.sp2px()
height = 20.sp2px()
centerVertically()
startOfParent(20.sp2px())
})
但是如果说遇到一些三方的,比如一个三方的轮播图,那怎么办呢?我现在的办法是用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="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.youth.banner.Banner
android:id="@+id/bannerLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:banner_indicator_normal_color="@color/clear"
app:banner_indicator_selected_color="@color/clear"
app:banner_radius="15sp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
// 轮播图
let constraintLayout = requireContext().inflate<ConstraintLayout>(R.layout.banner)
let banner =
constraintLayout.findViewById<Banner<String, BannerImageAdapter<String>>>(R.id.bannerLayout1)
// 轮播图设置
banner.apply {
addBannerLifecycleObserver(activity)
indicator = CircleIndicator(activity)
}
constraintLayout.add(banner, banner.lParams {
width = 0
height = 102.sp2px()
topOfParent(60.sp2px())
leftOfParent(16.sp2px())
rightOfParent(16.sp2px())
})
还有一些比较特殊的不是三方的UI组件如ShapeableImageView这些,Views-DSL没有提供代码的对象创建方法,可以如此:
例子:下面的是一个圆形的网络图片(用Glide进行网络图片的赋值)
// 图片(加载网络图片的,需要剪圆角的,需要ShapeableImageView)
val shapeModel = ShapeAppearanceModel.builder()
.setAllCorners(RoundedCornerTreatment())
.setAllCornerSizes(28.dp2pxFloat())
.build()
val imageV = ShapeableImageView(ctx).apply {
shapeAppearanceModel = shapeModel
}
supView.add(imageV, imageV.constraintLayout().lParams {
width = 56.sp2px()
height = 56.sp2px()
centerHorizontally()
topOfParent(22.sp2px())
})
Glide.with(ctx)
.load(hotRoom[index].icon)
.into(imageV)
如果布局在Activity中的话,可以直接进行在onCreate中进行创建,然后setContentView,但是在fragement中的话,那就需要如此(继承Ui的一个类进行布局):
// 消息
class MessageFragment: Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val ui = MessageUi(requireContext())
return ui.root
}
}
class MessageUi(override val ctx: Context) : Ui {
override val root = constraintLayout {
setBackgroundResource(R.color.purple_700)
lParams {
width = matchParent
height = matchParent
}
}
}