将DialogFragment视图中的Touch事件发送到父活动视图

时间:2014-06-03 20:27:09

标签: android android-fragments ontouchevent ontouchlistener android-dialogfragment

以下是我的布局:

enter image description here

我有一个父活动,它有一个自定义视图(view1可以自己处理onTouch事件)和2个按钮(view2和view3)。 DialogFragment显示了可见的布局,其余部分是透明的。 我的对话框片段如下所示:

public class FragmentText extends DialogFragment{

  public static FragmentText newInstance() {
        FragmentText frag = new FragmentText();

        frag.setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Translucent_NoTitleBar);
        return frag;
    }

  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);

        // instantiate the custom layout
        final View layout = inflater.inflate(R.layout.fragment_layout, null);

        .....
        }

}

,布局文件如下所示:

<com.TransparentView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layMain"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_marginBottom="70dp"
    android:background="@color/transparent"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="70dp" >

    <LinearLayout
        android:id="@+id/layContent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_margin="5dp"
        android:background="@drawable/bk_text_edit"
        android:orientation="vertical"
        android:padding="@dimen/margin" >

          all my layouts and buttons
    </LinearLayout>
</com.TransparentView>

public class TransparentView extends LinearLayout {

    @SuppressLint("NewApi")
    public TransparentView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public TransparentView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TransparentView(Context context) {
        super(context);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false; // event get propagated
    }

}

当用户按下DialogFragment的可见布局时,我想: 1.关闭对话框片段 2.将onTouch传递给父活动,并允许用户与视图进行交互。

所以基本上如果我将手指拖到View1上,我想要关闭对话框并继续对view1进行拖动交互。

这可能实现吗?

LE:这也行不通:

layMain.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            getActivity().dispatchTouchEvent(event);

            return false;
        }
    });

6 个答案:

答案 0 :(得分:2)

最后,正如Luksprog建议的那样,我最终放弃了DialogFragment。我使用简单的Fragment进行了测试,该片段托管在一个活动的FrameLayout中,所以它看起来就像我需要它的地方。通过这种方式,我仍然可以与其他视图进行所需的所有交互。

谢谢大家的支持。

答案 1 :(得分:0)

我会使用Alert对话框来获得所需的效果:

AlertDialog.Builder Dialog = new AlertDialog.Builder(this);
        Dialog.setMessage("Text you wish to enter in the dialog"));
//Use this if you would like to include a button at the bottom of the alert dialog. Otherwise just leave it blank.
        Dialog.setNeutralButton("Back to App", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        });
        Dialog.show();

希望这会有所帮助:)

答案 2 :(得分:0)

您可以在对话框的透明视图中覆盖boolean onInterceptTouchEvent(MotionEvent ev),抓住事件,将其发送到您需要的位置,关闭对话框并返回false(这意味着触摸事件未被消耗)。< / p>

或者,如果您不想覆盖View类,则可以在对话框中覆盖boolean dispatchTouchEvent (MotionEvent ev),并尝试通过分析MotionEvent对象来找出点击发生的位置。

答案 3 :(得分:0)

如果您已成功捕获LinearLayout中的触摸事件,我理解为Dialog周围的透明视图,那么您应该可以通过返回父级的界面来完成此操作Activity并在对话框类中调用公共方法。我会做出以下修改:

首先 - 在TransparentView中定义一个接口,并添加一个公共方法来建立对父活动的回调。

public class TransparentView extends LinearLayout {

   public interface TouchCallback{
       public void onMotionEvent(MotionEvent e);
   }

   private TouchCallback mCallback;

   @SuppressLint("NewApi")
   public TransparentView(Context context, AttributeSet attrs, int defStyle) {
       super(context, attrs, defStyle);
   }

    public TransparentView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TransparentView(Context context) {
        super(context);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        callback.onMotionEvent(ev);
        return false; // event get propagated
    }

    public setCallback(TouchCallback callback){
        mCallback = callback;
    }

}

我们的想法是捕捉动作事件并手动将其传递回您的托管活动。 将动作事件传递回活动后,您需要做的就是关闭对话框。 DialogFragment已内置dismiss method,只要您使用实例变量保留对话框的引用,就可以执行以下操作

@Override
public void onMotionEvent(MotionEvent e){
    mDialog.dismiss();
}

如果这不起作用,只需在对话框类中添加一个方法并调用它。从我的示例中我可以看出,我们甚至不需要对透明视图捕获的运动事件做任何事情,因为我们想要做的就是在触摸发生时关闭对话框。由于回调只应在触摸发生时激活,因此无需检查(尽管您可以稍后对其进行扩展以实现Handler,并且只有在触摸持续指定的时间后才关闭对话框)。

答案 4 :(得分:0)

即使您放弃了DialogFragment,这也可能对其他人有所帮助。

您需要获取实际的装饰视图并在其中拦截触摸事件:

 @Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);


    getDialog().getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            getActivity().dispatchTouchEvent(event);
            return false;
        }
    });

    return super.onCreateView(inflater, container, savedInstanceState);
}

答案 5 :(得分:0)

我在BottomSheetDialog上遇到了同样的问题。我解决了我的问题:

final BottomSheetDialog dialog = getDialog();
final View touchOutside = dialog.findViewById(R.id.touch_outside);
touchOutside.setOnTouchListener((v, event) -> {
    getActivity().dispatchTouchEvent(event);
    return false;
});

看来Finn的解决方案应该可以正常工作。