android-fragments 如何通过操作栏中的后退按钮返回到上一个片段?(Kotlin)

jbose2ul  于 2022-11-14  发布在  Android
关注(0)|答案(7)|浏览(261)

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

private fun setupBackButton() {
        if (activity is AppCompatActivity) {
            (activity as AppCompatActivity?)?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
        }
    }

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

编辑

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

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

if (fragmentManager != null) {
    fragmentManager!!
      .beginTransaction()
      .replace(R.id.main_layout, fragment)
      .addToBackStack(null)
      .commit()
}

这是我的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)
        }
    }
}

下面是它的.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>
tcomlyy6

tcomlyy61#

为了在您点击Home/up按钮时获得响应,以下是解决此问题的几个选项:

第一个选项

在显示Home/UP按钮的片段中,重写onOptionsItemSelected()方法并调用Activity的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)
}

旁注:

不是使用下面的方法在ActionBar上显示Home/Up按钮,而是使用下面的方法为每个需要显示Home按钮的片段设置布尔值:

private fun setupBackButton() {
    if (activity is AppCompatActivity) {
        (activity as AppCompatActivity?)?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
    }
}

您可以改为在练习的onCreate()方法中使用AppBarConfiguration设置ActionBar,如下所示:

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)

}

这样做,up按钮将显示在所有片段中,但R.id.second_fragment, R.id.third_fragment除外,您不再需要为每个片段设置setDisplayHomeAsUpEnabled()来显示home/up按钮。但您仍然需要如上所述覆盖onOptionsItemSelected

第二个选项

这比第一个选项更简洁。首先,你必须实现上面的边节点,以允许NavController自动控制/配置ActionBar
因此,过去的附注是此选项的强制性部分。
然后覆盖活动中的onSupportNavigateUp(),使NavigationUI支持正确的ActionBar向上导航。

override fun onSupportNavigateUp(): Boolean {
    return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration)
}

然后在Activity中重写onOptionsItemSelected(),使“让导航UI处理OptionsMenu/ActionBar”项选择

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

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

yqhsw0fo

yqhsw0fo2#

在带导航的Kotlin碎片中

首先,在onCreate中添加setHasOptionsMenu(true)

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
}

然后覆盖onOptionsItemSelected,当R.id.home时,您可以控制返回按钮

override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.getItemId()) {
            android.R.id.home ->
                findNavController().navigate(R.id.action_FragmentTwo_to_FragmentOne)
        }
        return true
}
watbbzwu

watbbzwu3#

您需要将单击侦听器附加到工具栏,如下所示:

toolbar.setNavigationOnClickListener { requireActivity().onBackPressed() }
xriantvc

xriantvc4#

class StartActivity : FragmentActivity() {
    /**
     * The pager widget, which handles animation and allows swiping horizontally to access previous
     * and next wizard steps.
     */
    private lateinit var mPager: ViewPager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.start_activity)

        val loginButton = findViewById<Button>(R.id.login_button)
        loginButton.setOnClickListener {
            this.didTapLoginButton()
        }
    }

    private fun didTapLoginButton() {
        val i = Intent(this, LoginActivity::class.java)
        startActivity(i)
    }
}

class LoginActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.login_activity)

        //actionbar
        val actionbar = supportActionBar
        //set actionbar title
        actionbar!!.title = "New Activity"
        //set back button
        actionbar.setDisplayHomeAsUpEnabled(true)
        actionbar.setDisplayHomeAsUpEnabled(true)
    }

    override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return true
    }
    // it is important function, you need to write this function in which class/activity you want to show back arrow
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return super.onOptionsItemSelected(item)
    }
}
luaexgnf

luaexgnf5#

将此添加到NavigationClickListener中。

FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
    Log.i("MainActivity", "popping backstack");
    fm.popBackStack();
} else {
    Log.i("MainActivity", "nothing on backstack, calling super");
    super.onBackPressed();  
}
rggaifut

rggaifut6#

Zain'sSecond Option非常好,但我将以onCreate的用法,为使用DataBinding制作的部分展示一种不同的方法:

ActivityMainBinding.inflate(layoutInflater).run {
            
    setContentView(root)

    setSupportActionBar(toolbar)

    (supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment)
        as NavHostFragment).navController.let { navController ->

            val appBarConfiguration = AppBarConfiguration(navController.graph)

            toolbar.setupWithNavController(navController, appBarConfiguration)
    }
}
8aqjt8rx

8aqjt8rx7#

这是一个迟来的答案,但我希望它会帮助一些人。
我在Kotlin做的,我成功的方法是:
MainActivity中,我覆盖了onSupportNavigateUp

override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment_activity_main)
        return navController.navigateUp(appBarConfiguration)
                || super.onSupportNavigateUp()

}

并声明了onCreate()之外的AppBarConfiguration

相关问题