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