Android layout 复用

作者: 不再更新_ | 来源:发表于2021-06-08 16:31 被阅读0次
微信截图

在编写类似上图的界面时,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>

相关文章

网友评论

    本文标题:Android layout 复用

    本文链接:https://www.haomeiwen.com/subject/lzbdeltx.html