Knu*_*dna 76 android android-fragments android-nested-fragment
我一直在使用Android包含在支持库中的新嵌套片段 API.
我面对嵌套片段的问题是,如果嵌套片段(即通过FragmentManager返回的by 已经添加到另一个片段的片段getChildFragmentManager())调用startActivityForResult(),onActivityResult()则不会调用嵌套片段的方法.但是,父片段onActivityResult()和活动onActivityResult()都会被调用.
我不知道我是否遗漏了有关嵌套片段的内容,但我没想到所描述的行为.下面是重现此问题的代码.如果有人能指出我正确的方向并向我解释我做错了什么,我将非常感激:
package com.example.nestedfragmentactivityresult;
import android.media.RingtoneManager;
import android.os.Bundle;
import android.content.Intent;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends FragmentActivity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.getSupportFragmentManager()
.beginTransaction()
.add(android.R.id.content, new ContainerFragment())
.commit();
}
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// This is called
Toast.makeText(getApplication(),
"Consumed by activity",
Toast.LENGTH_SHORT).show();
}
public static class ContainerFragment extends Fragment
{
public final View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState)
{
View result = inflater.inflate(R.layout.test_nested_fragment_container,
container,
false);
return result;
}
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
getChildFragmentManager().beginTransaction()
.add(R.id.content, new NestedFragment())
.commit();
}
public void onActivityResult(int requestCode,
int resultCode,
Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// This is called
Toast.makeText(getActivity(),
"Consumed by parent fragment",
Toast.LENGTH_SHORT).show();
}
}
public static class NestedFragment extends Fragment
{
public final View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState)
{
Button button = new Button(getActivity());
button.setText("Click me!");
button.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
startActivityForResult(intent, 0);
}
});
return button;
}
public void onActivityResult(int requestCode,
int resultCode,
Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// This is NOT called
Toast.makeText(getActivity(),
"Consumed by nested fragment",
Toast.LENGTH_SHORT).show();
}
}
}
Run Code Online (Sandbox Code Playgroud)
test_nested_fragment_container.xml是:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
Run Code Online (Sandbox Code Playgroud)
pvs*_*nik 141
我用以下代码解决了这个问题(使用了支持库):
在容器片段中以这种方式覆盖onActivityResult:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,嵌套片段将接收对onActivityResult方法的调用.
此外,由于注意到 埃里克Brynsvold在类似的问题,嵌套的片段应该使用它的父片段,而不是简单的startActivityForResult()调用开始活动.因此,在嵌套片段启动活动中:
getParentFragment().startActivityForResult(intent, requestCode);
Run Code Online (Sandbox Code Playgroud)
fay*_*lon 58
是的onActivityResult(),嵌套片段不会以这种方式调用.
onActivityResult的调用序列(在Android支持库中)是
Activity.dispatchActivityResult().FragmentActivity.onActivityResult().Fragment.onActivityResult(). 在第3步中,片段位于FragmentMananger父级中Activity.所以在你的例子中,它是发现调度的容器片段onActivityResult(),嵌套片段永远不会收到事件.
我认为你必须实现自己的调度ContainerFragment.onActivityResult(),找到嵌套片段并调用将结果和数据传递给它.
这是我解决它的方式.
在活动中:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
List<Fragment> frags = getSupportFragmentManager().getFragments();
if (frags != null) {
for (Fragment f : frags) {
if (f != null)
handleResult(f, requestCode, resultCode, data);
}
}
}
private void handleResult(Fragment frag, int requestCode, int resultCode, Intent data) {
if (frag instanceof IHandleActivityResult) { // custom interface with no signitures
frag.onActivityResult(requestCode, resultCode, data);
}
List<Fragment> frags = frag.getChildFragmentManager().getFragments();
if (frags != null) {
for (Fragment f : frags) {
if (f != null)
handleResult(f, requestCode, resultCode, data);
}
}
}
Run Code Online (Sandbox Code Playgroud)
2019 年 9 月 2 日更新的答案
这个问题早在Androidx,当您使用一个活动,你有嵌套的片段内NavHostFragment,onActivityResult()不要求对孩子的片段NavHostFragment。
要解决此问题,您需要手动将调用路由到onActivityResult()来自onActivityResult()主机活动的子片段。
以下是如何使用 Kotlin 代码完成此操作。这在onActivityResult()您承载以下内容的主要活动中NavHostFragment:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.your_nav_host_fragment)
val childFragments = navHostFragment?.childFragmentManager?.fragments
childFragments?.forEach { it.onActivityResult(requestCode, resultCode, data) }
}
Run Code Online (Sandbox Code Playgroud)
这将确保onActivityResult()子片段的 被正常调用。
旧答案
此问题已在Android 支持库 23.2 及更高版本中得到修复。我们不再需要Fragment在 Android 支持库 23.2+ 中做任何额外的事情。onActivityResult()现在Fragment按预期在嵌套中调用。
我刚刚使用 Android 支持库 23.2.1 对其进行了测试,并且可以正常工作。终于我可以有更干净的代码了!
因此,解决方案是开始使用最新的 Android 支持库。
| 归档时间: |
|
| 查看次数: |
32711 次 |
| 最近记录: |