自定义视图调用startActivityForResult

时间:2011-07-05 17:37:24

标签: android android-layout

我创建了自定义复合视图,其中包含拍摄照片的功能。

我这样称呼它(从视图中):

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
((Activity)mContext).startActivityForResult(intent, index);

这部分效果很好。我不知道怎么做的是如何在我的自定义视图中实现onActivityResult

或者我应该在Activity中捕获这个并重新路由到我的视图中?看起来不是很好的解决方案..

6 个答案:

答案 0 :(得分:13)

你实际上可以这样做:

@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);
}

诀窍是使用辅助临时片段。

答案 1 :(得分:8)

我遇到的问题与最初的问题相同。我知道你们都发布了工作解决方案,但是,所有解决方案都缺少一件事:封装。我的意思是 - 如果在一个活动中我有10个视图应该(在某些事件上)启动另一个活动,那么它应该是NORMAL,以便能够从需要该活动的视图中启动该新活动。你们都试图说服最好处理所有新的活动 - 比起为什么我们在每个视图中添加不同的逻辑。我们可能想要重新使用代码,并创建一个可以独立工作到我们使用它的自定义视图(工作可能包括显示另一个活动来选择某些东西)。

我知道这是不可能的(或者还没有),并且清楚地证明Android SDK还没有准备好处理真正的大型应用程序。

如果你想要一个例子:在任何具有例如客户列表(应该是视图)的真实商业应用中,视图应该能够自己启动addcustomer活动,编辑客户活动等,独立于您放置该客户列表视图(控件)的位置 - 因为在大型应用程序中您需要重新使用组件(您可能需要在订单产品活动,时间表活动等中显示客户列表控件。)。

一种可能的解决方案可能是:   - 启动新活动(使用视图上下文(通常应该是父活动)。   - 在新的活动关闭事件中,要么直接调用调用视图中的方法(取决于具体情况,还有可能性:要么处理通常在activityresult上运行的代码的静态,要么尝试传递调用的实例)查看新活动,并执行相同操作。通过这种方式,您可以处理新活动,而不会让包含活动知道任何相关内容。

答案 2 :(得分:1)

你需要从你的活动中捕捉到这一点。您的活动会调用startActivityForResult,因此它会启动Intent并获得结果。我要说直接从视图代码中启动它总体上是不好的。一个更好的解决方案是使用clickListener(或checkChangeListener,或任何你想要的),由你的活动设置,并调用像“openImageCapture”这样的方法。

当Intent返回时,您的活动将处理结果并根据需要更新您的视图。

视图只是用于在屏幕上显示内容并获得用户输入,活动就是在那里进行实际工作。

答案 3 :(得分:1)

无法从您的视图中捕获onActivityResult,只能从Activity抓取。{/ p>

假设Context对象为Activity并不安全。一般来说,你不应该依赖这个事实。即使在视图中看起来合理,您仍然应该只使用Context接口提供的方法。这是因为当您调用Activity特定函数时,无法预测Activity上的所有副作用。

答案 4 :(得分:1)

只需在自定义视图中使用相同的方法 在活动onActivityResult内部,调用yourView.onActivityResult(...)并在视图内部处理结果。 就像大家提到的那样,您不一定总是以Context为Activity类来结束。通常是从膨胀视图查看时。 但是,如果仅使用代码构造视图,并且始终使用活动实例,那么您会很好。

答案 5 :(得分:0)

这是实现@ riwnodennyk解决方案的静态功能,同时克服Fragment must be static and not in anonymous class错误:

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);