【问题标题】:Android: Can not get view from activity in fragment when starting up application [duplicate]Android:启动应用程序时无法从片段中的活动中获取视图[重复]
【发布时间】:2021-06-27 20:23:40
【问题描述】:

我正在使用 NavHostFragment 来显示片段。当我试图在片段应用程序崩溃中获取活动的 FloatingActionButton 时。

MainActivity.kt

class MainActivity : AppCompatActivity(), ImageDrawerListDialogFragment.OnImageClickListener {
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main) // <-- 
            ...
    }

}

SearchFragment.kt

class SearchFragment : Fragment(), ImageDrawerListDialogFragment.OnImageClickListener {
   
private lateinit var fab: FloatingActionButton
   ...
   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View {
      _binding = FragmentSearchBinding.inflate(inflater, container, false)
      return binding.root
   }

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

     fab = (requireActivity() as MainActivity).findViewById(R.id.floatingActionButton) // <-- 
     fab.setOnSafeClickListener { requestPermission() }
     ...
   }

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.AppName.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/Theme.AppName.PopupOverlay">

            <androidx.appcompat.widget.SearchView
                android:id="@+id/searchView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:focusable="true"
                android:imeOptions="actionDone"
                android:inputType="text"
                app:iconifiedByDefault="false" />

        </androidx.appcompat.widget.Toolbar>

    </com.google.android.material.appbar.AppBarLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:contentDescription="create new search request"
        app:layout_anchorGravity="bottom|end"
        app:srcCompat="@android:drawable/ic_input_add" />
    
    <include layout="@layout/content_main" />


</androidx.coordinatorlayout.widget.CoordinatorLayout>

content_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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

nav_graph.xml

<?xml version="1.0" encoding="utf-8"?>
<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/SearchFragment">

    ...
</navigation>

错误

原因:android.view.InflateException:com.dmytroa.appName:layout/activity_main 中的二进制 XML 文件第 36 行:com.dmytroa.appName:layout/content_main 中的二进制 XML 文件第 18 行:膨胀类片段时出错引起:android.view.InflateException:com.dmytroa.appName:layout/content_main 中的二进制 XML 文件第 18 行:膨胀类片段错误引起:java.lang.NullPointerException:requireActivity() as MainActivity).findViewById(R. id.floatingActionButton) 不能为空

【问题讨论】:

  • 从错误信息开始。它有答案
  • 您的 XML 中是否没有收到警告,提示您应该用 FragmentContainerView 替换 &lt;fragment&gt; 标记?您应该始终使用 FragmentContainerView 而从不使用&lt;fragment&gt; 标签。 (如果您在使用 FragmentContainerView 和 NavHostFragment 时遇到问题,请参阅 this answer
  • 谢谢,用 FragmentContainerView 替换 fragment 解决了问题。

标签: android kotlin android-fragments


【解决方案1】:

fab = (requireActivity() as MainActivity).findViewById(R.id.floatingActionButton) //

我建议您不要从 Fragment “伸手”到 Activity 来操作其布局中存在的视图。这会在您的 Fragment 中创建对该 Activity 的显式依赖,如果您每次尝试在其他任何地方使用该 Fragment,它都会中断。

执行在 Activity 本身内对 Activity 视图进行操作的逻辑。

MainActivity:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main) 
    
    fab = findViewById(R.id.floatingActionButton)
    fab.setOnSafeClickListener { requestPermission() }
    ...
}

【讨论】:

  • 这并不是说我要在其他任何地方使用这个片段,我只是最初在片段中有这个按钮(但使用 app:layout_scrollFlags="scroll|enterAlways" 和 把底部的按钮剪掉了),我就是不想改代码。
  • 当然,这是有道理的。 FAB 一般是一个activity级组件,属于顶层CoordinatorLayout。并且由于它存在于 Activity 布局中,它应该由 Activity 和/或 Activity 的视图模型来管理和控制。
猜你喜欢
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
相关资源
最近更新 更多