Android 调用startActivityForResult的自定义视图
我创建了自定义复合视图,在其中我加入了拍照功能 我这样称呼它(从视图): 这部分很好用。我不知道如何在自定义视图中实现Android 调用startActivityForResult的自定义视图,android,android-layout,Android,Android Layout,我创建了自定义复合视图,在其中我加入了拍照功能 我这样称呼它(从视图): 这部分很好用。我不知道如何在自定义视图中实现onActivityResult 或者我应该抓住这个内在的活动,然后重新进入我的视野?看起来不是很好的解决方案。您需要从您的活动中了解这一点。在您的活动中会调用startractivityforresult,因此它将启动Intent并获得结果。我要说的是,直接从视图的代码启动它总体上是不好的。更好的解决方案是使用clickListener(或checkChangeListener
onActivityResult
或者我应该抓住这个内在的活动,然后重新进入我的视野?看起来不是很好的解决方案。您需要从您的活动中了解这一点。在您的活动中会调用
startractivityforresult
,因此它将启动Intent
并获得结果。我要说的是,直接从视图的代码启动它总体上是不好的。更好的解决方案是使用clickListener
(或checkChangeListener
,或任何您想要的),由您的活动设置,并调用类似“openImageCapture”的方法
当意图返回时,您的活动将处理结果并根据需要更新视图
视图仅用于在屏幕上显示内容和获取用户输入,活动用于实际工作。无法从视图中捕获活动结果,只能从
活动中捕获
假设上下文
对象是活动
,是不安全的。一般来说,你不应该依赖这个事实。即使在视图中似乎合理,您仍然应该只使用通过Context
接口可用的方法。这是因为当您调用活动
特定函数时,无法预测活动
的所有副作用 我的问题和第一个问题一样。我知道你们都发布了工作解决方案,但是,所有的解决方案都缺少一件事:封装。我的意思是-如果在一个活动中我有10个视图应该(在某个事件上)启动另一个活动,那么能够从需要该活动的视图启动该新活动应该是正常的。你们都在试图说服我们,从一开始就处理所有可能的新活动比为什么我们在每个视图中添加不同的逻辑更好。我们可能希望重用代码,并创建一个自定义视图,该视图可以独立于我们使用它的位置工作(例如,工作可能包括显示另一个活动以选择某些内容)
我知道这是不可能的(或者还没有),这清楚地证明了Android SDK还没有准备好处理真正的大型应用程序
如果你想举个例子:在任何真正的商业应用程序中,例如,客户列表(应该是一个视图),视图本身应该能够启动addcustomer活动、编辑customer活动等,而不依赖于您将客户列表视图(控件)放在何处,因为在大型应用程序中,您需要重复使用组件(您可能需要在订单产品活动、时间表活动等中显示客户列表控件。)
一种可能的解决办法是:
-启动新活动(使用视图上下文(通常应为父活动)。
-在新活动关闭事件上,直接调用调用视图中的方法(根据具体情况和可能性:要么是处理通常在activityresult上运行的代码的静态,要么是尝试将调用视图的实例传递给新活动,并执行相同的操作。这样,您就可以处理新活动,而不必让包含该活动的活动知道任何信息。我可以这样做:
@Override
public void onClick(View v) {
final FragmentManager fm = ((FragmentActivity) getContext()).getSupportFragmentManager();
Fragment auxiliary = new Fragment() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//DO WHATEVER YOU NEED
super.onActivityResult(requestCode, resultCode, data);
fm.beginTransaction().remove(this).commit();
}
};
fm.beginTransaction().add(auxiliary, "FRAGMENT_TAG").commit();
fm.executePendingTransactions();
auxiliary.startActivityForResult(new Intent(getContext(), ToStartActivity.class), 3333);
}
诀窍是使用一个辅助临时片段。这里有一个静态函数来实现@riwnodennyk的解决方案,同时克服片段必须是静态的,而不是匿名类中的错误:
public static void myStartActivityForResult(FragmentActivity act, Intent in, int requestCode, OnActivityResult cb) {
Fragment aux = new FragmentForResult(cb);
FragmentManager fm = act.getSupportFragmentManager();
fm.beginTransaction().add(aux, "FRAGMENT_TAG").commit();
fm.executePendingTransactions();
aux.startActivityForResult(in, requestCode);
}
public interface OnActivityResult {
void onActivityResult(int requestCode, int resultCode, Intent data);
}
@SuppressLint("ValidFragment")
public static class FragmentForResult extends Fragment {
private OnActivityResult cb;
public FragmentForResult(OnActivityResult cb) {
this.cb = cb;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (cb != null)
cb.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
}
}
用法示例:
Intent inPhonebook = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
myStartActivityForResult((FragmentActivity) getContext(),
inPhonebook, REQUEST_CODE_PICK_CONTACT, this::onContacts);
只需在自定义视图中使用相同的方法即可
在ActivitysOnActivityResult中调用yourView.onActivityResult(…),并在视图中处理结果。。
同样,正如大家提到的,你们不能总是以活动类的上下文结束,通常是从膨胀的角度。
但是,如果您仅在代码中构建视图,并且始终使用活动实例,那么您就很好。您的自定义视图显示在活动或其他任何位置,请指定一些我意识到的更多细节。.您是否有示例代码,我可以在其中了解如何在视图中设置自定义事件,以便在活动中设置侦听器?一旦您设置了v在iews中,您可以使用findViewById(int-id)在活动中获取对视图的引用。只需将其转换为正确的类型,然后对其调用setOnClickListener。它没有那么简单。视图是复合控件。使用5个以上按钮和文本/图像,simple OnClick将不起作用。我必须在视图的代码中执行某种委托,并在检测到内部按钮单击时将其触发。然后,此客户om事件需要在主活动中捕获。我从未在Java中编写过此类代码。findViewById方法可以找到使用给定ID显示的任何视图。如果将ID R.whater.button指定给按钮,则使用(button)findViewById(R.whater.button)将返回该按钮。如果您发布一些代码,我将添加所需的代码以使其工作。我明白您的意思,但仍然无法工作:)我在同一活动上有多个视图实例。不确定findViewById将返回哪个按钮哪个实例我最终使用了事件。我的自定义视图引发“NeedImage”事件和父活动处理它并将其传递回自定义视图。向后,我知道。但至少它是这样工作的。我100%同意,这种设计是个坏主意。我一直试图克服这一点,但运气不好。这就是创建碎片的原因。有关更多详细信息,请参阅此答案。问题是从2011年开始的,当时碎片还没有出现简介:)虽然它很好,但您假设上下文是FragmentActivity,这在大多数情况下都可能是错误的。这是一个非常好的解决方案!!!如果您的min API为11或更高,您可以轻松地使用普通片段执行此操作。此带有Fragment的抛出异常必须是
Intent inPhonebook = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
myStartActivityForResult((FragmentActivity) getContext(),
inPhonebook, REQUEST_CODE_PICK_CONTACT, this::onContacts);