Android: Single Activity with multiple Fragments, Navigation implements Fragment jumps, and Fragments share data through ViewModel

Single Activity with multiple Fragments, Navigation implements Fragment jumps, and Fragments share data through ViewModel

1、MainActivity

1、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">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentContainerView"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

2、MainActivity

/**
 * kotlin_jetpack_navigation
 * 使用navigation  + dataBinding + viewModel
 * 三个fragment共享一个viewModel中的数据,在NavigationView中显示
 */
class MainActivity : AppCompatActivity() {
    
    
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

2、HomeFragment, DetailFragment

  • FragmentA: includes SeekBar and a button, click the button to jump to FragmentB
  • FragmentB: A button for SeekBar plus one and minus one operation, a button to return to FragmentA, that is, after the addition and subtraction operation, the result of addition and subtraction is displayed on FragmentA.

insert image description here
nav_graph.xml

<navigation 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:id="@+id/nav_graph"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/detailFragment"
        android:name="cn.hk.navigation3.DetailFragment"
        android:label="fragment_detail"
        tools:layout="@layout/fragment_detail" >
        <action
            android:id="@+id/action_detailFragment_to_homeFragment"
            app:destination="@id/homeFragment" />
    </fragment>
    <fragment
        android:id="@+id/homeFragment"
        android:name="cn.hk.navigation3.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" >
        <action
            android:id="@+id/action_homeFragment_to_detailFragment"
            app:destination="@id/detailFragment" />
    </fragment>
</navigation>

2.1、HomeFragment

insert image description here1、fragment_home.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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="data"
            type="cn.hk.navigation3.MyViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".HomeFragment">


        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_begin="320dp"
            app:layout_constraintGuide_percent="0.5" />

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(data.number)}"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline" />

        <SeekBar
            android:id="@+id/seekBar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toTopOf="@+id/textView"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

2、HomeFragment

class HomeFragment : Fragment() {
    
    


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
    
    
        // Inflate the layout for this fragment
//        val myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
        val myViewModel by activityViewModels<MyViewModel>()
        val binding = DataBindingUtil.inflate<FragmentHomeBinding>(
            inflater, R.layout.fragment_home, container, false
        )
        binding.also {
    
    
            it.data = myViewModel
            it.lifecycleOwner = activity
            it.button.setOnClickListener {
    
     v ->
                val controller = Navigation.findNavController(v)
                controller.navigate(R.id.action_homeFragment_to_detailFragment)
            }
            myViewModel.get().value?.also {
    
     numberValue ->
                it.seekBar.progress = numberValue
            }
            it.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
    
    
                override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
    
    
                   myViewModel.set(p1)
                }

                override fun onStartTrackingTouch(p0: SeekBar?) {
    
    
                }

                override fun onStopTrackingTouch(p0: SeekBar?) {
    
    
                }

            })
        }

        return binding.root
    }

2.2、DetailFragment

insert image description here1、fragment_detail.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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="data"
            type="cn.hk.navigation3.MyViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".DetailFragment">


        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_begin="320dp"
            app:layout_constraintGuide_percent="0.5" />

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(data.number)}"
            android:textSize="20sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="add"
            android:onClick="@{()->data.count(1)}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/jian"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline" />

        <Button
            android:id="@+id/jian"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="cut"
            android:onClick="@{()->data.count(-1)}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/add"
            app:layout_constraintTop_toTopOf="@+id/guideline" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="返回"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/add" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

2、DetailFragment

class DetailFragment : Fragment() {
    
    


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
    
    
        // Inflate the layout for this fragment
//      val myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
        val myViewModel by activityViewModels<MyViewModel>()
        val binding = DataBindingUtil.inflate<FragmentDetailBinding>(
            inflater,
            R.layout.fragment_detail,
            container,
            false
        )
        binding.also {
    
    
            it.data = myViewModel
            it.lifecycleOwner = activity
            it.button3.setOnClickListener {
    
     v ->
                val controller = Navigation.findNavController(v)
                controller.navigate(R.id.action_detailFragment_to_homeFragment)
            }
        }
        return binding.root
    }

}

3、MyViewModel

class MyViewModel : ViewModel() {
    
    
    var number: MutableLiveData<Int> = MutableLiveData(0)

    fun get() = number

    fun set(result: Int) {
    
    
        number.value = result
    }


    fun count(x: Int) {
    
    
        number.value = number.value?.plus(x)
        if (number.value!! < 0)
            number.value = 0
    }
}

reference

Guess you like

Origin blog.csdn.net/JMW1407/article/details/127973691