如何通过操作栏中的后退按钮转到上一个片段?(科特林)

Max*_*axB 4 android android-fragments kotlin android-actionbar android-navigation

我有两个片段,我想使用操作栏中的后退按钮在它们之间创建交互。理想情况下,我希望保存先前片段的状态。我只能找到有关活动的信息。

对于片段我发现了这个

private fun setupBackButton() {
        if (activity is AppCompatActivity) {
            (activity as AppCompatActivity?)?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
        }
    }
Run Code Online (Sandbox Code Playgroud)

但它只显示后退按钮,点击没有任何反应。

编辑

在第一个片段中,我将第二个片段称为:

val fragment = UserContentFragment()
fragment.setUser(item.user)

if (fragmentManager != null) {
    fragmentManager!!
      .beginTransaction()
      .replace(R.id.main_layout, fragment)
      .addToBackStack(null)
      .commit()
}
Run Code Online (Sandbox Code Playgroud)

这是我的UserContentFragment第二个片段:

class UserContentFragment : Fragment() {

    private lateinit var user: SearchUser

    fun setUser(user: SearchUser) {
        this.user = user
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val root = inflater.inflate(R.layout.fragment_user_content, container, false)

        val userImage = root.findViewById(R.id.user_img) as ImageView
        if (context != null) {
            Glide.with(context!!)
                .load(user.profile_pic_url)
                .circleCrop()
                .into(userImage)
        }

        val userName: TextView = root.findViewById(R.id.user_name)
        userName.text = user.full_name

        val toolbar: Toolbar = root.findViewById(R.id.toolbar)
        toolbar.setNavigationOnClickListener { requireActivity().onBackPressed() }

        setupBackButton()
        
        return root
    }

    private fun setupBackButton() {
        if (activity is AppCompatActivity) {
            (activity as AppCompatActivity?)?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是它的 .xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    android:background="@color/colorBlack">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/user_title"
        android:layout_width="match_parent"
        android:layout_height="100dp">

        <ImageView
            android:id="@+id/user_img"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_marginStart="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="ContentDescription" />

        <TextView
            android:id="@+id/user_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="32dp"
            android:layout_marginEnd="16dp"
            android:textColor="@color/colorWhite"
            android:textSize="22sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/user_img"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

Zai*_*ain 6

为了在您按下主页/向上按钮时得到响应,可以使用以下几个选项来解决此问题:

第一个选项

在显示 Home/UP 按钮的片段中,重写onOptionsItemSelected()方法并调用活动onBackPressed()的 home 按钮 id

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle presses on the action bar menu items
    when (item.itemId) {
        android.R.id.home -> {
            activity?.onBackPressed()
            return true
        }
    }
    return super.onOptionsItemSelected(item)
}
Run Code Online (Sandbox Code Playgroud)

边注:

您不必使用ActionBar下面的方法显示“主页/向上”按钮,而是必须使用以下方法为需要显示主页按钮的每个片段设置布尔值:

private fun setupBackButton() {
    if (activity is AppCompatActivity) {
        (activity as AppCompatActivity?)?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以改为设置活动的 in 方法,如下ActionBar所示AppBarConfigurationonCreate()

private lateinit var appBarConfiguration: AppBarConfiguration

override fun onCreate(savedInstanceState: Bundle?) {

    val host: NavHostFragment = supportFragmentManager
            .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return

    val navController = host.navController

    appBarConfiguration = AppBarConfiguration(
            setOf(R.id.second_fragment, R.id.third_fragment)) //  IDs of fragments you want without the ActionBar home/up button

    setupActionBarWithNavController(navController, appBarConfiguration)

}
Run Code Online (Sandbox Code Playgroud)

通过这样做,向上按钮将显示在所有片段中,但是R.id.second_fragment, R.id.third_fragment您不再需要setDisplayHomeAsUpEnabled()为每个单独的片段设置 来显示主页/向上按钮。但您仍然需要onOptionsItemSelected如上所述进行覆盖。

第二个选项

这比第一个选项更简洁。首先,您必须实现上面的侧节点以允许NavController自动控制/配置ActionBar.

因此,过去的旁注是该选项的强制性部分。

然后在允许支持正确向上导航的onSupportNavigateUp()活动中进行覆盖。NavigationUIActionBar

override fun onSupportNavigateUp(): Boolean {
    return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration)
}
Run Code Online (Sandbox Code Playgroud)

然后onOptionsItemSelected()在活动中重写,使导航 UI 处理 OptionsMenu/ActionBar 项目选择

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return item.onNavDestinationSelected(findNavController(R.id.my_nav_host_fragment)) 
            || super.onOptionsItemSelected(item)
}
Run Code Online (Sandbox Code Playgroud)

我想说选项 2 比选项 1 更简洁,因为您将所有代码写在一个地方(活动)而不接触片段,而且它会自动配置所有片段,无需手动或针对setDisplayHomeAsUpEnabled()activity.onBackPressed()想要 Home/ 的单个片段向上按钮显示。