Android进阶之路Android技术知识Android开发经验谈

Android Jatpack基础学习2

2019-02-18  本文已影响5人  进击的包籽

Android Jatpack基础学习1
本文Github代码

上一篇文章写了Jatpack工程的基础搭建,这篇继续写使用。dataBinding使用,ViewModel的使用。


1.ViewModel增加一个start变量,用于后面通知fragment跳转。

class MainViewModel : ViewModel() {
    ...
    var start = MutableLiveData<Boolean>().apply { value = false }
     ...
    fun startActivity() {
        start.postValue(true)
    }
}

2.xml里的控件点击事件绑定,另一个有id的Button,是dataBinding方式。

<Button
    android:onClick="@{view -> viewModel.startActivity()}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="跳转" />

<Button
    android:id="@+id/btn2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="跳转2" />

3.点击按钮后,在fragment中,就可以接受到ViewModel中start的变化,这里也能放网络请求,或者数据库变化,通知view更改。

//通过观察者模式,ViewModel参数变化,在此做跳转操作
viewModel.start.observe(viewLifecycleOwner, Observer {
    if (it!!) {
        activity?.let { activity ->
            startActivity(Intent(activity, BindingActivity::class.java))
        }
    }
})

4.不用ViewModel通知的话,也能用dataBinding直接给控件增加点击事件,也不需要像以前写findViewById了。

//通过dataBinding找到控件,
dataBinding.btn2.setOnClickListener {
    activity?.let { activity ->
        startActivity(Intent(activity, BindingActivity::class.java))
    }
}

两张结果是一样样的


点击

开发中,为了布局复用,我们一般会include复用布局,但是里面的参数,却只能再findViewById后设置,dataBinding可以在xml里直接复制,不用再写繁琐的代码。

1.编辑一个复用的布局,这样写,允许使用它的布局直接传参进来。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <!-- view的visible需要View类支持 -->
        <import type="android.view.View" />

        <variable
            name="title"
            type="String" />

        <variable
            name="background"
            type="android.graphics.drawable.Drawable" />

        <variable
            name="visible"
            type="java.lang.Boolean" />

        <variable
            name="resId"
            type="android.graphics.drawable.Drawable" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@{background}"
        android:orientation="vertical">

        <!-- default是开发时看的,真正运行时看不到 -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{title,default = `大包子`}"
            android:textSize="30sp" />

        <!-- visible属性用boolean来控制 -->
        <ImageView
            android:id="@+id/imgClose"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@{resId ?? @drawable/ic_star_black , default = @drawable/ic_star_black}"
            android:visibility="@{visible ? View.VISIBLE : View.INVISIBLE , default = visible}" />

    </LinearLayout>
</layout>

2.fragment布局里使用,传参进去,app:之前include布局对应的参数="@{}"

<include
    android:id="@+id/view1"
    layout="@layout/include_view"
    app:background="@{@color/white}"
    app:resId="@{@drawable/ic_star_black}"
    app:title="@{@string/title}"
    app:visible="@{true}" />

<include
    android:id="@+id/view2"
    layout="@layout/include_view"
    app:background="@{@color/grey}"
    app:resId="@{@drawable/ic_star_white}"
    app:title="@{@string/title2}"
    app:visible="@{true}" />

<include
    layout="@layout/include_view"
    app:background="@{@color/grey}"
    app:resId="@{@drawable/ic_star_white}"
    app:title="@{@string/title3}"
    app:visible="@{false}" />
include

3.include中控件要动态变化的方法,需要在使用include的时候设置对应的id。

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    dataBinding.view1.imgClose.setOnClickListener {
        activity?.let {
            it.finish()
        }
    }

    dataBinding.view2.imgClose.setOnClickListener {
        activity?.let {
            it.finish()
        }
    }
}

有很多时候,基础类型不够用,那我们也能通过BindAdapter自定义类型。

class BindAdapter {
    //设置字体颜色
    @BindingAdapter("app:textColor")
    fun setTextColor(textView: TextView, color: Int?) {
        color?.let {
            textView.setTextColor(ContextCompat.getColor(textView.context, color))
        }
    }

    //手机号隐藏
    @BindingAdapter("app:hidePhone")
    fun hidePhone(textView: TextView, phone: String?) {
        phone?.let {
            if (phone.length > 7) {
                var stringBuffer = StringBuffer(phone)
                for (i in 3..6) {
                    stringBuffer.setCharAt(i, '*')
                }
                textView.text = stringBuffer.toString()
            }
        }
    }
}

如果出现错误Cannot find the setter for attribute
错误解决

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    app:hidePhone="@{`17600331122`}"
    app:textColor="@{@color/blue}" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    app:hidePhone="@{viewModel.phone}"
    app:textColor="@{@color/colorAccent}" />
运行效果

跟多细节,可以看demo哦。

上一篇 下一篇

猜你喜欢

热点阅读