本文共 18630 字,大约阅读时间需要 62 分钟。
相机活动返回时,承载此片段的活动将调用其onActivityResult
。
我的片段通过为相机发送照片的意图启动了一个结果活动。 图片应用程序可以正常加载,拍照并返回。 但是,永远不会点击onActivityResult
。 我已经设置了断点,但是什么也没有触发。 片段可以具有onActivityResult
吗? 我想是这样,因为它是提供的功能。 为什么不触发此操作?
ImageView myImage = (ImageView)inflatedView.findViewById(R.id.image);myImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent, 1888); }});@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { if( requestCode == 1888 ) { Bitmap photo = (Bitmap) data.getExtras().get("data"); ((ImageView)inflatedView.findViewById(R.id.image)).setImageBitmap(photo); }}
我想你叫getActivity().startActivityForResult(intent,111);
。 您应该调用startActivityForResult(intent,111);
。
如果有人仍然无法做到,我可以添加两个建议。 在Manifest.xml文件中,确保在回叫时托管活动未完成,并且要启动的活动具有标准的启动模式。 详细信息如下:
对于Hosting活动,如果有,将no history属性设置为false。
android:noHistory="false"
对于要启动的“活动”,如果有
android:launchMode="standard"
public class takeimage extends Fragment { private Uri mImageCaptureUri; private static final int PICK_FROM_CAMERA = 1; private static final int PICK_FROM_FILE = 2; private String mPath; private ImageView mImageView; Bitmap bitmap = null; View view; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.activity_send_image, container, false); final String[] items = new String[] { "From Camera", "From SD Card" }; mImageView = (ImageView)view.findViewById(R.id.iv_pic); ArrayAdapteradapter = new ArrayAdapter (getActivity(), android.R.layout.select_dialog_item, items); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle("Select Image"); builder.setAdapter(adapter, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { if (item == 0) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File file = new File(Environment.getExternalStorageDirectory(), "tmp_avatar_" + String.valueOf(System.currentTimeMillis()) + ".jpg"); mImageCaptureUri = Uri.fromFile(file); try { intent.putExtra( android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri); intent.putExtra("return-data", true); getActivity().startActivityForResult(intent, PICK_FROM_CAMERA); } catch (Exception e) { e.printStackTrace(); } dialog.cancel(); } else { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); getActivity().startActivityForResult( Intent.createChooser(intent, "Complete action using"), PICK_FROM_FILE); } } }); final AlertDialog dialog = builder.create(); Button show = (Button) view.findViewById(R.id.btn_choose); show.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Switch the tab content to display the list view. dialog.show(); } }); return view; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK) return; if (requestCode == PICK_FROM_FILE) { mImageCaptureUri = data.getData(); // mPath = getRealPathFromURI(mImageCaptureUri); //from Gallery if (mPath == null) mPath = mImageCaptureUri.getPath(); // from File Manager if (mPath != null) bitmap = BitmapFactory.decodeFile(mPath); } else { mPath = mImageCaptureUri.getPath(); bitmap = BitmapFactory.decodeFile(mPath); } mImageView.setImageBitmap(bitmap); } public String getRealPathFromURI(Uri contentUri) { String [] proj = {MediaStore.Images.Media.DATA}; Cursor cursor = managedQuery(contentUri, proj, null, null,null); if (cursor == null) return null; int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); }}
我在ChildFragmentManager
遇到了同样的问题。 管理器不会将结果传递给嵌套片段,您必须在基本片段中手动进行操作。
public void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); Fragment fragment = (Fragment) getChildFragmentManager().findFragmentByTag(childTag); if (fragment != null) { fragment.onActivityResult(requestCode, resultCode, intent); }}
选项1:
如果你调用startActivityForResult()
从片段,那么你应该调用startActivityForResult()
而不是getActivity().startActivityForResult()
因为它会导致片段onActivityResult()。
如果不确定在哪里调用startActivityForResult()
以及如何调用方法。
选项2:
由于Activity获得onActivityResult()
的结果,因此您将需要覆盖该活动的onActivityResult()
并调用super.onActivityResult()
以传播到未处理的结果代码或所有未处理结果的片段。
如果以上两个选项不起作用,请参考选项3,因为它肯定会起作用。
选项3:
从片段到onActivityResult函数的显式调用如下。
在父Activity类中,重写onActivityResult()方法,甚至重写Fragment类中的方法,并按以下代码进行调用。
在父类中:
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane); fragment.onActivityResult(requestCode, resultCode, data);}
在子班:
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { // In fragment class callback}
我只是一种解决方法:
public static Fragment _tempFragment = null;@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(_tempFragment != null) _tempFragment.onActivityResult(requestCode, resultCode, data);}
在您的片段中,在startActivityResult之前设置
MainActivity._tempFragment = this;
在片段中onActivityResult <-之后
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Do your job { } MainActivity._tempFragment = null;}
如果您不知道活动中的片段,只需将它们全部枚举并发送活动结果参数:
// In your activity@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); for (Fragment fragment : getSupportFragmentManager().getFragments()) { fragment.onActivityResult(requestCode, resultCode, data); }}
这些答案大多数都说您必须在主机Activity
为Fragment
调用super.onActivityResult(...)
。 但这似乎对我没有用。
因此,在您的主机Activity
您应该改为调用Fragments
onActivityResult(...)
。 这是一个例子。
public class HostActivity extends Activity { private MyFragment myFragment; protected void onActivityResult(...) { super.onActivityResult(...); this.myFragment.onActivityResult(...); }}
在HostActivity
某个时刻,您需要为this.myFragment
分配您正在使用的Fragment
。 或者,使用FragmentManager
获取Fragment
而不是在HostActivity
中保留对其的引用。 另外,在尝试调用this.myFragment.onActivityResult(...);
之前,请检查是否为null
this.myFragment.onActivityResult(...);
。
正如Ollie C所提到的,当您使用嵌套片段时,支持库存在一个活动的错误,该错误使用onActivityResult的返回值。 我刚刚打了它:-(。
请参阅 。
FragmentActivity
用修改后的代码替换了requestCode
。 此后,当将调用onActivityResult()
时, FragmentActivity
将解析较高的16位并恢复原始Fragment的索引。 看一下这个方案:
如果您在根级别上有一些片段,那就没有问题。 但如果你有嵌套的片段 ,例如Fragment
里面一些标签ViewPager
, 保证你将面临的一个问题 (或者已经面临的话)。
因为只有一个索引存储在requestCode
。 那是Fragment
内FragmentManager
索引。 当我们使用嵌套片段时,有子FragmentManager
,它们有自己的Fragments列表。 因此,有必要从根FragmentManager
开始保存整个索引链。
我们如何解决这个问题? 有常见的解决方法。
GitHub: :
简而言之,
在fragment中,声明Fragment fragment = this
;
之后,使用fragment.startActivityForResult
。
结果将返回到activityResult中。
我非常怀疑这里所有的答案都不过是黑客。 我已经尝试了所有其他方法,但都没有可靠的结论,因为始终存在某种愚蠢的问题。 我不能依靠不一致的结果。 如果您查看Fragments的官方Android API文档,您会看到Google明确声明以下内容:
从包含片段的Activity调用startActivityForResult(Intent,int)。
另请:
因此,似乎最正确和可靠的方法是从托管活动中实际调用startActivityForResult()并从那里处理生成的onActivityResult() 。
您的代码具有嵌套片段。 调用super.onActivityForResult不起作用
您不想修改可以从中调用片段的每个活动,也不想绕过调用片段链中的每个片段的工作。
这是许多可行的解决方案之一。 快速创建一个片段,并使用支持片段管理器将其直接连接到活动。 然后从新创建的片段中调用startActivityForResult。
private void get_UserEmail() { if (view == null) { return; } ((TextView) view.findViewById(R.id.tvApplicationUserName)) .setText("Searching device for user accounts..."); final FragmentManager fragManager = getActivity().getSupportFragmentManager(); Fragment f = new Fragment() { @Override public void onAttach(Activity activity) { super.onAttach(activity); startActivityForResult(AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null, null, null, null), REQUEST_CODE_PICK_ACCOUNT); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_PICK_ACCOUNT) { String mEmail = ""; if (resultCode == Activity.RESULT_OK) { if (data.hasExtra(AccountManager.KEY_ACCOUNT_NAME)) { mEmail = data .getStringExtra(AccountManager.KEY_ACCOUNT_NAME); } } if (mActivity != null) { GoPreferences.putString(mActivity, SettingApplication.USER_EMAIL, mEmail); } doUser(); } super.onActivityResult(requestCode, resultCode, data); fragManager.beginTransaction().remove(this).commit(); } }; FragmentTransaction fragmentTransaction = fragManager .beginTransaction(); fragmentTransaction.add(f, "xx" + REQUEST_CODE_PICK_ACCOUNT); fragmentTransaction.commit();}
解决方案1:
呼叫startActivityForResult(intent, REQUEST_CODE);
而不是getActivity().startActivityForResult(intent, REQUEST_CODE);
。
解决方案2:
当startActivityForResult(intent, REQUEST_CODE);
被称为活动的onActivityResult(requestCode,resultcode,intent)
,然后您可以从此处调用fragments onActivityResult()
,并传递requestCode, resultCode and intent
。
在片段内,致电
this.startActivityForResult(intent, REQUEST_CODE);
this
是指片段。 否则,按照@Clevester所说的那样做:
Fragment fragment = this;....fragment.startActivityForResult(intent, REQUEST_CODE);
我也不得不打电话
super.onActivityResult(requestCode, resultCode, data);
在父活动的onActivityResult
中进行操作。
(我改编自@Clevester的答案。)
我也在片段中遇到了这个问题。 我在DialogFragment
调用了startActivityForResult
。
但是现在这个问题已经解决了:
FragmentClassname.this.startActivityForResult
。 只需对片段使用以下代码。
@Overridepublic void onOtherButtonClick(ActionSheet actionSheet, int index) { if (index == 1) { Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setType("image/*"); startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1); }}public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == 1) { if (requestCode == 1) { Uri selectedImageUri = data.getData(); //selectedImagePath = getPath(selectedImageUri); } }}
onActivityResult将调用而不调用其父级。
您可以简单地在片段baseActivity.startActivityForResult
上重写BaseActivity onActivityResult
。
在BaseActivity上添加接口并覆盖onActivityResult。
private OnBaseActivityResult baseActivityResult; public static final int BASE_RESULT_RCODE = 111; public interface OnBaseActivityResult{ void onBaseActivityResult(int requestCode, int resultCode, Intent data); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(getBaseActivityResult() !=null && requestCode == BASE_RESULT_RCODE){ getBaseActivityResult().onBaseActivityResult(requestCode, resultCode, data); setBaseActivityResult(null); }
On Fragment实现OnBaseActivityResult
@Override public void onBaseActivityResult(int requestCode, int resultCode, Intent data) { Log.d("RQ","OnBaseActivityResult"); if (data != null) { Log.d("RQ","OnBaseActivityResult + Data"); Bundle arguments = data.getExtras(); } }
此解决方法可以解决问题。
如果在Facebook登录时遇到上述问题,则可以在片段的父活动中使用以下代码,例如:
Fragment fragment = getFragmentManager().findFragmentById(android.R.id.tabcontent);fragment.onActivityResult(requestCode, resultCode, data);
要么:
Fragment fragment = getFragmentManager().findFragmentById("fragment id here");fragment.onActivityResult(requestCode, resultCode, data);
并在片段中添加以下调用...
callbackManager.onActivityResult(requestCode, resultCode, data);
如果您使用的是嵌套片段,这也可以:
getParentFragment().startActivityForResult(intent, RequestCode);
除此之外,您还必须从父活动中调用super.onActivityResult
并填充片段的onActivityResult
方法。
在您的主要活动中:
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data);}
在您的主要顶层片段(ViewPager片段)中:
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { YourFragment frag = (YourFragment) getChildFragmentManager().getFragments().get(viewPager.getCurrentItem()); frag.yourMethod(data); // Method for callback in YourFragment super.onActivityResult(requestCode, resultCode, data);}
在YourFragment(嵌套片段)中:
public void yourMethod(Intent data){ // Do whatever you want with your data}
在我的情况下,这是一个Android错误( ),如果您使用受支持的FragmentActivity
,则必须使用getSupportFragmentManager
代替getChildFragmentManager
:
Listfragments = getSupportFragmentManager().getFragments();if (fragments != null) { for (Fragment fragment : fragments) { if(fragment instanceof UserProfileFragment) { fragment.onActivityResult(requestCode, resultCode, data); } }}
对于许多嵌套片段(例如,在片段中使用ViewPager时)
在您的主要活动中 :
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data);}
在您的片段中:
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { for (Fragment fragment : getChildFragmentManager().getFragments()) { fragment.onActivityResult(requestCode, resultCode, data); }}
在您的嵌套片段中
通话活动
getParentFragment().startActivityForResult(intent, uniqueInstanceInt);
uniqueInstanceInt-将其替换为嵌套片段中唯一的int,以防止另一个片段对待答案。
收到回应
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == uniqueInstanceInt ) { // TODO your code }}
注意
为避免错误,请在uniqueInstanceInt中使用0到65536之间的数字,以避免出现“只能将低16位用于requestCode”的情况。
最简单的方法之一是从片段开始活动。
startActivity(ActivityName);
然后,添加您调用startActivityForResult(intent,"1");
从您的活动中,然后在您的活动中添加onActivityResult
startActivityForResult(intent,"1");@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane); fragment.onActivityResult(requestCode, resultCode, data);// perform other activity result like fetching from Uris or handling cursorsfinish(); // finish the activity will get to back to your fragment.}
我的问题是关于主机活动,我发现它带有一组android:launchMode="standard"
我暂时将其删除了,并且可以正常工作!
这是最受欢迎的问题之一。 我们可以找到许多有关此问题的线索。 但是它们都不对我有用。
因此,我已经使用此解决方案解决了这个问题。
首先让我们了解为什么会这样。
我们可以直接从Fragment调用startActivityForResult
,但是实际上后面的机制都是由Activity处理的。
从Fragment调用startActivityForResult
后,requestCode将更改为将Fragment的身份附加到代码中。 一旦收到结果,Activity将能够追溯到谁发送了此请求。
将Activity导航回去后,结果将发送到带有修改后的requestCode的Activity的onActivityResult,并将其解码为原始requestCode + Fragment的身份。 之后,活动将通过onActivityResult将活动结果发送到该片段。 一切都完成了。
问题是:
活动可以将结果发送到仅直接附加到活动的片段,而不发送给嵌套的片段。 这就是为什么无论如何都不会调用嵌套片段的onActivityResult的原因。
解:
1)通过以下代码在片段中启动Intent:
/** Pass your fragment reference **/ frag.startActivityForResult(intent, REQUEST_CODE); // REQUEST_CODE = 12345
2)现在在您的父活动中覆盖** onActivityResult()
:**
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); }
您必须在父活动中调用它才能使其正常工作。
3)在您的片段呼叫中:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { }}
而已。 使用这种解决方案,它可以应用于任何单个片段,无论它是否嵌套。 是的,它也涵盖了所有情况! 而且,代码也很干净。
一旦将这段代码块从Fragment移到Utility类 ,并以parentActivity
作为参数传递,我也面临着同样的问题,
Intent intent = new Intent(parentActivity, CameraCaptureActivity.class);parentActivity.startActivityForResult(intent,requestCode);
然后,我在那个Fragment的 onActivityResult
方法中没有得到任何值,然后,我将参数更改为Fragment ,因此方法的修改后的定义如下所示:
Intent intent = new Intent(fragment.getContext(), CameraCaptureActivity.class);fragment.startActivityForResult(intent,requestCode);
之后,我能够在Fragment的 onActivityResult
获取值
其他答案中尚未描述的另一个用例:
使用exception.startResolutionForResult()
时,不会调用片段中声明的onActivityResult()
exception.startResolutionForResult()
:
if (exception is ResolvableApiException) { exception.startResolutionForResult(activity!!, MY_REQUEST_CODE)}
在这种情况下,将exception.startResolutionForResult()
替换为片段的startIntentSenderForResult()
:
if (exception is ResolvableApiException) { startIntentSenderForResult(exception.resolution.intentSender, MY_REQUEST_CODE, null, 0, 0, 0, null)}
Kotlin版本(在您的活动onActivityResult()中)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { //add following lines in your activity if(supportFragmentManager?.fragments!=null && supportFragmentManager?.fragments!!.size>0) for (i in 0..supportFragmentManager?.fragments!!.size-1) { val fragment= supportFragmentManager?.fragments!!.get(i) fragment.onActivityResult(requestCode, resultCode, data) } }
托管活动会覆盖onActivityResult()
,但不会为未处理的结果代码调用super.onActivityResult()
。 显然,即使该片段是调用startActivityForResult()
的片段,该活动也会在处理结果时获得第一炮。 当您考虑片段的模块化时,这很有意义。 一旦为所有未处理的结果实现了super.onActivityResult()
,该片段就可以处理结果了。
并且也来自@siqing答案:
要获得片段中的结果,请确保调用startActivityForResult(intent,111);
而不是getActivity().startActivityForResult(intent,111);
在您的片段中。
我通过编写扩展Fragment
的基类解决了这个问题,在活动的onactivityresult
中,我使用fragmenttag
标识了当前正在运行的fragmenttag
。 然后,我在fragmentbase类中调用用户定义的方法。 这将在当前正在运行的片段中触发一个事件。
转载地址:http://yeogj.baihongyu.com/