跳转至

查看安卓 Jetpack 中与碎片的绑定

原文:https://www . geesforgeks . org/view-binding-with-fragments-in-Android-jet pack/

在之前的文章安卓 Jetpack 中的视图绑定中,已经讨论了为什么在安卓项目中获取视图绑定特性会带来很多好处。但是当涉及到片段的视图绑定时,情况就变了。因为片段的生命周期是不同的,活动的生命周期也是不同的,这里的事情也和上面文章中讨论的一样,片段布局的命名约定被更改为帕斯卡格,片段布局的属性被更改为骆驼格。例如,fragment 1 . XML->fragment 1 bindingedit_text (id)在片段的布局下更改为 eEditText (camel case)所以在本文中视图绑定是使用 fragment 来讨论的。下面给出了一个示例视频,以了解我们将在本文中做什么。注意,我们将使用 Kotlin 语言来实现这个项目。

逐步实施

第一步:新建一个空的活动项目

步骤 2:启用视图绑定功能

  • 通过调用应用级 build.gradle 文件中的以下代码片段来启用视图绑定功能,并单击右上角的“立即同步”按钮。

构建功能{

视图绑定=真

}

  • 如果找不到应用程序级构建,请参考下面的图片。

步骤 3:使用 activity_main.xml 文件

  • 活动的主布局包含两个按钮,用于切换片段 1 和片段 2,以及一个框架布局,用于保存卡片视图中的片段。和一个提交按钮,用于检查按下时谁的片段数据被提交。
  • 为了实现相同的功能,在 activity_main.xml 文件中调用以下代码。

可扩展标记语言

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:ignore="HardcodedText"
    tools:viewBindingIgnore="true">

    <Button
        android:id="@+id/fragment_1B"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="FRAGMENT 1"
        app:layout_constraintEnd_toStartOf="@+id/fragment_2B"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/fragment_2B"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="FRAGMENT 2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/fragment_1B"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.cardview.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/fragment_1B">

        <FrameLayout
            android:id="@+id/fragment_holder"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp" />

    </androidx.cardview.widget.CardView>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:text="SUBMIT"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/card_view" />

</androidx.constraintlayout.widget.ConstraintLayout>

输出 UI:

第四步:创建两个片段

  • 创建两个片段,其中包括文本视图来表示片段号编辑文本和一个按钮。要实现每个片段的用户界面,您可以参考以下代码。
  • 片段 1:

可扩展标记语言

<?xml version="1.0" encoding="utf-8"?>
<!--fragment 1-->
<LinearLayout 
    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"
    android:orientation="vertical"
    tools:context=".ExampleFragment1"
    tools:ignore="HardcodedText">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="Fragment 1"
        android:textSize="18sp" />

    <EditText
        android:id="@+id/edit_text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:hint="Enter Something" />

    <Button
        android:id="@+id/done_button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="16dp"
        android:text="DONE" />

</LinearLayout>
  • 片段 2:

可扩展标记语言

<?xml version="1.0" encoding="utf-8"?>
<!--fragment 2-->
<LinearLayout 
    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"
    android:orientation="vertical"
    tools:context=".ExampleFragment2"
    tools:ignore="HardcodedText">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="Fragment 2"
        android:textSize="18sp" />

    <EditText
        android:id="@+id/edit_text2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:hint="Enter Something" />

    <Button
        android:id="@+id/done_button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="16dp"
        android:text="DONE" />

</LinearLayout>

第 5 步:使用碎片文件

  • 首先,可空的绑定变量最初被赋值为空,并且当片段的视图被破坏时,它必须再次被设置为空(在这种情况下为 _binding )。
  • 为了避免可空绑定对象的空检查,通过使用 kotlin 的 backing 属性,我们制作了绑定变量的另一个副本(在本例中是绑定)。
  • 但是,如果片段想要从宿主活动中访问视图,可以使用findwiewbyid()方法来完成。
  • 在每个片段的内部调用以下代码。kt 文件。添加注释是为了更好地理解。
  • 片段 1:

我的锅

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment

// Enter your package name here
import com.adityamshidlyali.gfgarticle.databinding.Fragment1Binding

class ExampleFragment1 : Fragment() {

    // assign the _binding variable initially to null and
    // also when the view is destroyed again it has to be set to null
    private var _binding: Fragment1Binding? = null

    // with the backing property of the kotlin we extract
    // the non null value of the _binding
    private val binding get() = _binding!!

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {

        // inflate the layout and bind to the _binding
        _binding = Fragment1Binding.inflate(inflater, container, false)

        // retrieve the entered data by the user
        binding.doneButton1.setOnClickListener {
            val str: String = binding.editText1.text.toString()
            if (str.isNotEmpty()) {
                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()
            }
        }

        // handle the button from the host activity using findViewById method
        val submitButton: Button = activity!!.findViewById(R.id.submit_button)
        submitButton.setOnClickListener {
            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 1", Toast.LENGTH_SHORT).show()
        }

        // Inflate the layout for this fragment
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
  • 片段 2:

我的锅

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment

// Enter your package name here
import com.adityamshidlyali.gfgarticle.databinding.Fragment2Binding

class ExampleFragment2 : Fragment() {

    // assign the _binding variable initially to null and
    // also when the view is destroyed again it has to be 
    // set to null
    private var _binding: Fragment2Binding? = null

    // with the backing property of the kotlin
    // we extract
    // the non null value of the _binding
    private val binding get() = _binding!!

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {

        // inflate the layout and bind to the _binding
        _binding = Fragment2Binding.inflate(inflater, container, false)

        // retrieve the entered data by the user
        binding.doneButton2.setOnClickListener {
            val str: String = binding.editText2.text.toString()
            if (str.isNotEmpty()) {
                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()
            }
        }

        // handle the button from the host activity using findViewById method
        val submitButton: Button = activity!!.findViewById(R.id.submit_button)
        submitButton.setOnClickListener {
            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 2", Toast.LENGTH_SHORT).show()
        }

        // Inflate the layout for this fragment
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

第 6 步:使用 MainActivity.kt 文件

  • MainActivity.kt 文件中,只实现了片段的事务功能。为了更好地理解,请参考下面的代码及其输出。

我的锅

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.adityamshidlyali.gfgarticle.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    // create binding instance for the activity_main.xml
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // when app is initially opened the Fragment 1 should be visible
        supportFragmentManager.beginTransaction().apply {
            replace(binding.fragmentHolder.id, ExampleFragment1())
            addToBackStack(null)
            commit()
        }

        // handle the fragment 2 button to toggle the fragment 2
        binding.fragment1B.setOnClickListener {
            changeFragment(ExampleFragment1())
        }

        // handle the fragment 2 button to toggle the fragment 2
        binding.fragment2B.setOnClickListener {
            changeFragment(ExampleFragment1())
        }
    }

    // function to change the fragment which is used to reduce the lines of code
    private fun changeFragment(fragmentToChange: Fragment): Unit {
        supportFragmentManager.beginTransaction().apply {
            replace(binding.fragmentHolder.id, fragmentToChange)
            addToBackStack(null)
            commit()
        }
    }
}

输出:



回到顶部