在编写类似上图的界面时,layout 里会有大段的重复代码。
<!-- activity_me.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
...... >
<!-- 下面这一段会重复很多次 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<ImageView
android:id="@+id/imageView2"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="16dp"
android:contentDescription="收藏"
android:src="@drawable/ic_collection"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="收藏"
android:textSize="32sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/imageView2"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- .... 重复多次,略去 .... -->
</androidx.appcompat.widget.LinearLayoutCompat>
这种情况下我们通常会想到把 ConstraintLayout
那部分抽出来复用。不过虽然这些代码在结构是一样的,但里边的图标和文字不一样。这时候可以使用 <include>
标签,结合 Android 的 ViewBinding 功能来实现代码结构上的复用。文字和图标可以以参数的形式传递到被复用的局部模板当中。
首先,在 build.gradle 里开启 dataBinding:
// build.gradle
android {
......
dataBinding {
enabled = true
}
......
}
然后在原 activity 的 xml 文件最外层包上一层 layout 标签:
<!-- activity_me.xml -->
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.appcompat.widget.LinearLayoutCompat
android:orientation="vertical"
.... >
<androidx.constraintlayout.widget.ConstraintLayout
.... >
<ImageView.... />
<TextView .... />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>
这样编译器会以 xml 的文件名为名,生成对应的 Binding 类,本例中 xml 文件名为 activity_me
,则生成的数据绑定类名为 ActivityMeBinding
。
接着修改 Activity,将 setContentView()
的调用替换为 DataBindingUtil.setContentView()
class MeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_me)
DataBindingUtil.setContentView<ActivityMeBinding>(this, R.layout.activity_me)
......
}
}
如果用了 Fragment(以 MeFragment 为例),则将 inflater.inflate(R.layout.fragment_home, container, false)
替换为 FragmentMeBinding.inflate(inflater).root
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// return inflater.inflate(R.layout.fragment_me, container, false)
return FragmentMeBinding.inflate(inflater).root
}
接着就可将原来的 ConstraintLayout
部分抽取出来:
<!-- entry.xml -->
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- 声明两个变量,用于传递参数 -->
<data>
<variable name="icon" type="android.graphics.drawable.Drawable" />
<variable name="text" type="String" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
......>
<!-- 从 text 和 icon 两个变量中取值 -->
<ImageView
android:contentDescription="@{text}"
android:src="@{icon}"
...... />
<TextView
android:text="@{text}"
....../>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
同样,由于根元素套上了 layout
,同时开启了 dataBinding,该文件会生成一个叫 EntryBinding
的类。
接着,在原 activity_me.xml 里 include 该文件即可
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.appcompat.widget.LinearLayoutCompat
...... >
<!-- 注意传递参数的方式 -->
<include
layout="@layout/entry"
android:id="@+id/payment_entry"
app:text="支付"
app:icon="@{@drawable/ic_payment}"/>
<include
layout="@layout/entry"
android:id="@+id/collection_entry"
app:text="收藏"
app:icon="@{@drawable/ic_collection}"/>
......
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>
网友评论