首页 > 解决方案 > 使用导航抽屉创建一个简单的 Android 片段

问题描述

我是一位经验丰富的开发人员,但对 Android 编程很陌生,我有点难过。我从 Android Studio Navigation Drawer 标准项目模板开始。我设法在其中一个片段(Gallery Fragment)中实现了一个简单的项目列表,并在按下按钮时做一些事情。因此,当按下按钮时,我希望它向下钻取到一个新屏幕。应该很简单,但我已经阅读了十几个 Android 片段教程,但我什么也没有发生。

因此,我创建了要激活的新片段:

package tech.iconultra.ui.gallery

import android.content.Context
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import tech.iconultra.R

private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
class IconPackGalleryFragment : Fragment() {
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null
    private var listener: OnFragmentInteractionListener? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

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

    // TODO: Rename method, update argument and hook method into UI event
    fun onButtonPressed(uri: Uri) {
        listener?.onFragmentInteraction(uri)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
    }

    override fun onDetach() {
        super.onDetach()
        listener = null
    }

    interface OnFragmentInteractionListener {
        fun onFragmentInteraction(uri: Uri)
    }

    companion object {
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            IconPackGalleryFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
    }
}

还有一个简单的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/icon_pack_gallery"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

        <EditText
                android:id="@+id/editText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:inputType="textPersonName"
                android:text="Name" />

        <ScrollView
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                <TableLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">

                    <TableRow
                            android:layout_width="match_parent"
                            android:layout_height="match_parent" />

                    <TableRow
                            android:layout_width="match_parent"
                            android:layout_height="match_parent" />

                    <TableRow
                            android:layout_width="match_parent"
                            android:layout_height="match_parent" />

                    <TableRow
                            android:layout_width="match_parent"
                            android:layout_height="match_parent" />
                </TableLayout>
            </LinearLayout>
        </ScrollView>
    </LinearLayout>

</LinearLayout>

但我对什么化身可以激活它们感到困惑。我试过这个:

                                val fragmentManager: FragmentManager = activity!!.supportFragmentManager
                                fragmentManager?.beginTransaction()?.apply {
                                    add(0, IconPackGalleryFragment(), "aaaaa")
                                    commit()
                                }

什么也没有发生。我试过了:

                                val fragmentManager: FragmentManager = activity!!.supportFragmentManager
                                fragmentManager?.beginTransaction()?.apply {
                                    replace(R.id.installed_app_list, IconPackGalleryFragment(), "aaaaa")
                                    commit()
                                }

(R.id.installed_app_list 是我调用它的片段)。我已经尝试用各种其他布局替换 R.id.installed_app_list,但是对于标准导航抽屉模板项目,我应该在这里传递什么让我感到困惑。此代码使应用程序崩溃并出现以下错误:

java.lang.UnsupportedOperationException: addView(View) is not supported in AdapterView

----- 编辑 ------ 我发现这会使片段出现:

  fragmentManager?.beginTransaction()?.apply {
      add(android.R.id.content, IconPackGalleryFragment(), "aaaaa")
      addToBackStack("aaaaa")
      commit()
  }

但是有一些问题:1)片段似乎有一个不可见的背景,尽管片段本身说它的背景应该是白色的,具有 100% 的 alpha。2) 按返回不会将您带到上一个屏幕。相反,第一次按下会将您带到主导航屏幕(不是启动该片段的导航屏幕)并且该片段仍然出现在它的前面(!)。第二次按下后退按钮,然后移除片段。

我猜这是进步,但仍然感到困惑。

标签: androiduser-interfaceandroid-fragmentskotlin

解决方案


要回答我自己的问题,显然 android 导航抽屉模板使用导航组件,这意味着我必须学习如何在 mobile_navigation.xml 上使用导航设计器,在其中添加一个新屏幕,在我以前的屏幕和我的新屏幕,然后当我想激活它时,我调用以下命令,在我的屏幕之间传递链接的 ID。

findNavController().navigate(R.id.action_nav_gallery_to_iconPackGalleryFragment)

这样做之后,它就可以工作了。我仍然需要学习和理解何时使用片段管理器,何时使用导航控制器,但似乎在这种情况下,使用导航控制器,而不是片段管理器。


推荐阅读