如何从View中获取Fragment?

65

我向一个TableLayout中添加了一些Fragment,然后我想从容器Activity中管理它们,所以我使用了这个:

Fragment fragment = (Fragment) tableLayout.getChildAt(i);

但是getChildAt(int)返回的是一个View,而View不能强制转换为Fragment


你如何添加Fragment?通过XML的<fragment>标签还是使用Java中的FragmentManager? - Nachi
我使用FragmentManager添加了它们。 - golkarm
3个回答

80

Fragment有时候会让初学者感到非常困惑。为了理解你的问题,你必须学习什么是Fragment以及它们如何使用。

首先,View是屏幕上存在的东西。例如:TextViewEditTextButton等。它们被放置在Xml或Java/Kotlin编写的“布局”中。这些布局使用Activity显示。

现在,Fragment不是一个View。它根本没有任何屏幕上的存在。相反,它是一个简单地管理布局的类——有点类似于Activity。如果你需要从你的Fragment的onCreateView()返回View,你可以直接在你的Activity中使用findViewById()

如果你需要引用你的Fragment,有两种可能的方法:

  1. 如果你像这样使用java/kotlin添加Fragment:
getFragmentManager()
  .beginTransaction()
  .replace(R.id.fragment_container_viewgroup, myFragment, FRAGMENT_TAG)
  .commit();

您可以使用:

MyFragment myFragment = (MyFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
  1. 如果您像这样将Fragment添加到XML布局中:
<fragment android:name="com.example.android.fragments.HeadlinesFragment"
  android:id="@+id/fragmentContainer"
  android:layout_weight="1"
  android:layout_width="0dp"
  android:layout_height="match_parent" />

你可以使用这个:
getFragmentManager().findFragmentById(R.id.fragmentContainer);

基本上,每个Activity都有一个FragmentManager类来维护所有活动的Fragments,并且有两种方法可以找到它们:使用您在显示片段时传递的唯一标记或传递添加片段的容器视图ID。

1
这个回答太棒了。我将片段添加到XML布局中,所以我不知道如何正确使用它们。 - dave o grady
1
根据您的上下文,您可能需要调用 getChildFragmentManager() 而不是 getFragmentManager() - Daniel F

35

对于想要从 View 中实际获取到 Fragment 对象的人,现在 FragmentManager 中有一个名为 findFragment(View) 的方法可用 (参考文献)

//in Java 
FragmentManager.findFragment(view)

//in Kotlin there is an extension function
view.findFragment()

注意 - 如果视图不是通过片段的 onCreateView 添加的,则会引发 IllegalStateException 异常。


我遇到了一个问题,即在RecyclerView的行中从网络加载图像的ImageView未在其资源准备就绪时添加到片段中。如何检查视图是否已添加到片段中,然后调用此扩展方法,以便我们不必尝试捕获findFragment()的IllegalStateException? - Android developer
如果该片段包含RecyclerView,我假设这不是访问它的正确方法,因为单元格永远不会在onCreateView中添加到片段中。我假设处理您的用例的最简单方法是将接口传递给您的ViewHolders,该接口知道如何访问RecyclerView之外需要的任何内容,并在特定单元格内使用它。 - ymindstorm
1
关于小心的注释是错误的:不需要通过onCreateView添加View,这才能正常工作。但是,对于要将 View 附加到 Fragment 视图树中,则必须这样做。您可以成功地为任何已“连接”(attached)的 View 找到最近的父级 Fragment。当一个View被"分离(detached)"或者附加到一个Activity(即不在Fragment中)时,会抛出例外。通过将 OnAttachStateChangeListener 添加到我们的 ViewHolderitemView,或者覆盖我们的 RecyclerView.Adapter 中的 onViewAttachedToWindow(ViewHolder) 方法,可以解决 RecyclerView 问题。 - Wes Alvaro
@WesAlvaro能否提供更多关于您的更改的上下文?链接的文档说明此属性会自动填充View视图和其子视图所返回的“onCreateView”方法中。除将视图添加到Fragment的视图树中外,还有哪些其他方式可以将视图与片段相关联,以使该方法不会抛出异常?仅仅将其添加到视图树中似乎行不通。 - ymindstorm
我正在审查代码,作者误认为以编程方式添加的视图或任何动态添加的视图(例如通过RecyclerView)在此处将返回空。这不是事实。是的,在onCreateView中必须返回一些View,但是从此“基本”View派生的任何View都将返回相同的Fragment。这是因为底层代码只是沿着视图树向上走。唯一的要求是View附加在Fragment的视图树中。 - Wes Alvaro

2
您无法获取这样的片段。您需要使用标签添加片段并通过该标签检索它。
要添加一个片段,请按照以下步骤进行:
getFragmentManager().beginTransaction().add(R.id.container, fragment, "tagTofindFragment");

获取片段:
fragment = getFragmentManager().findFragmentByTag("tagTofindFragment");

这里的 tagTofindFragment 是你的碎片中应该是唯一的标签。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接