Android 片段未保存 UI 按下后退按钮时的状态
Android Fragment not saving UI State on pressing Back Button
我 运行 我的用例有问题。它非常基本的用例。我有一个主要 activity 和 2 个片段。主要 activity 没有多少 UI。它所做的只是用 FirstFragment 替换它的容器。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, FirstFragment.newInstance())
.addToBackStack(null)
.commit()
}
}
FirstFragment有2个按钮——initializeButton和button1,其中initializeButton默认处于启用状态,而button1只有在按下initializeButton后才启用。
一旦在 initializeButton 之后按下 Button1,它就会启动 SecondFragment。以下是执行此操作的代码。
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.container, SecondFragment.newInstance())
.addToBackStack(null)
.commit()
现在,这将正确启动 Secondfragment。现在,当我在 Fragment2 中按下后退按钮时,我想要的行为是启动第一个片段时两个按钮都处于启用状态。相反,它将进入第一个片段中的默认状态(在启用状态下初始化按钮,而在禁用状态下初始化按钮 1)。感谢任何反馈。谢谢
主要活动
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, FirstFragment.newInstance())
.addToBackStack(null)
.commit()
}
}
}
MainActivity 布局
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
第一个片段
class FirstFragment : Fragment() {
companion object {
fun newInstance() = FirstFragment()
}
private lateinit var viewModel: SharedViewModel
private lateinit var initializeButton: Button
private lateinit var button1: Button
private lateinit var newview: View
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (savedInstanceState == null) {
newview = inflater.inflate(R.layout.fragment_first, container, false)
}
return newview
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeButton = view.findViewById(R.id.button1)
initializeButton.setOnClickListener{
button1.isEnabled = true
}
button1 = view.findViewById(R.id.button2)
button1.setOnClickListener{
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.container, SecondFragment.newInstance())
.addToBackStack(null)
.commit()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean("initState", initializeButton.isEnabled)
outState.putBoolean("button1State", button1.isEnabled)
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
if (savedInstanceState != null) {
initializeButton.isEnabled = savedInstanceState.getBoolean("initState")
button1.isEnabled = savedInstanceState.getBoolean("button1State")
}
}
片段优先布局
<LinearLayout 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="wrap_content"
tools:context=".FirstFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/initialize"
android:enabled="true"
android:layout_marginTop="5dp"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/button1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/button2"
android:enabled="false"
android:layout_marginTop="5dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
第二个片段
class SecondFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false)
}
companion object {
fun newInstance() = SecondFragment()
}
}
第二个片段布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/second_fragment"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textStyle="bold"
android:visibility="visible"/>
<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
您更换片段有什么特别的原因吗?如果没有,您可以简单地添加它而不是替换它,这将确保状态得到维护。
你的代码会变成这样
.add(R.id.container, SecondFragment.newInstance())
.addToBackStack(null)
.commit()
我 运行 我的用例有问题。它非常基本的用例。我有一个主要 activity 和 2 个片段。主要 activity 没有多少 UI。它所做的只是用 FirstFragment 替换它的容器。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, FirstFragment.newInstance())
.addToBackStack(null)
.commit()
}
}
FirstFragment有2个按钮——initializeButton和button1,其中initializeButton默认处于启用状态,而button1只有在按下initializeButton后才启用。 一旦在 initializeButton 之后按下 Button1,它就会启动 SecondFragment。以下是执行此操作的代码。
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.container, SecondFragment.newInstance())
.addToBackStack(null)
.commit()
现在,这将正确启动 Secondfragment。现在,当我在 Fragment2 中按下后退按钮时,我想要的行为是启动第一个片段时两个按钮都处于启用状态。相反,它将进入第一个片段中的默认状态(在启用状态下初始化按钮,而在禁用状态下初始化按钮 1)。感谢任何反馈。谢谢
主要活动
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, FirstFragment.newInstance())
.addToBackStack(null)
.commit()
}
}
}
MainActivity 布局
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
第一个片段
class FirstFragment : Fragment() {
companion object {
fun newInstance() = FirstFragment()
}
private lateinit var viewModel: SharedViewModel
private lateinit var initializeButton: Button
private lateinit var button1: Button
private lateinit var newview: View
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (savedInstanceState == null) {
newview = inflater.inflate(R.layout.fragment_first, container, false)
}
return newview
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeButton = view.findViewById(R.id.button1)
initializeButton.setOnClickListener{
button1.isEnabled = true
}
button1 = view.findViewById(R.id.button2)
button1.setOnClickListener{
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.container, SecondFragment.newInstance())
.addToBackStack(null)
.commit()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean("initState", initializeButton.isEnabled)
outState.putBoolean("button1State", button1.isEnabled)
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
if (savedInstanceState != null) {
initializeButton.isEnabled = savedInstanceState.getBoolean("initState")
button1.isEnabled = savedInstanceState.getBoolean("button1State")
}
}
片段优先布局
<LinearLayout 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="wrap_content"
tools:context=".FirstFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/initialize"
android:enabled="true"
android:layout_marginTop="5dp"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/button1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/button2"
android:enabled="false"
android:layout_marginTop="5dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
第二个片段
class SecondFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false)
}
companion object {
fun newInstance() = SecondFragment()
}
}
第二个片段布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/second_fragment"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textStyle="bold"
android:visibility="visible"/>
<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
您更换片段有什么特别的原因吗?如果没有,您可以简单地添加它而不是替换它,这将确保状态得到维护。
你的代码会变成这样
.add(R.id.container, SecondFragment.newInstance())
.addToBackStack(null)
.commit()