简体   繁体   English

android传递在视图剪辑边界之外绘制的子视图的触摸事件(ViewPager第1页到第2页)

[英]android Passing touch events of a Child view drawn outside of view clip bounds (ViewPager Page 1 to Page 2)

My Android ViewPager has set to draw views outside of the bounds (Clip bounds set to false) . 我的Android ViewPager已设置为在边界之外绘制视图(剪辑边界设置为false)。 I have a touch event listener on all the views displayed on the page. 我在页面上显示的所有视图上都有一个触摸事件监听器。 The custom view is displayed on the page 1, drawn outside of its clipping Bounds and overflows to the page 2. The touch event on the page 1 works fine. 自定义视图显示在页面1上,在其剪切边界之外绘制并溢出到页面2.页面1上的触摸事件正常工作。 When scrolled to the second page, the remaining view is displayed. 滚动到第二页时,将显示剩余视图。 The issue is that the touch event on the custom view (added on the page 1) does not get called when clicked on the Page 2. 问题是单击第2页时,自定义视图上的触摸事件(在页面1上添加)不会被调用。

PageViewActivity.cs PageViewActivity.cs

ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setClipChildren(false);
mViewPager.setClipToPadding(false);

PageViewFragment.cs PageViewFragment.cs

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.page_layout, container, false);
    setHasOptionsMenu(true);

    View view1=(View)v.findViewById(R.id.view1);
    view1.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

        Toast.makeText(getActivity(), "View clicked",Toast.LENGTH_SHORT).show();    
        }
    });return v;    

} }

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:clipChildren="false" 
android:clipToPadding="false" >
<View
    android:id="@+id/view1"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_marginLeft="250dp"
    android:layout_marginTop="20dp"
    android:background="#ff0000" />

Fragment Layout - page_layout.xml 片段布局 - page_layout.xml

Any suggestions? 有什么建议么?

There's a problem here. 这里有一个问题。 We can swipe only the middle view. 我们只能刷中间视图。 This is because the touch events occur outside the ViewPagers bounds. 这是因为触摸事件发生在ViewPagers边界之外。 We can override the onTouchEvent of the ViewPagerContainer and dispatch the events to the ViewPager to solve this. 我们可以覆盖ViewPagerContainer的onTouchEvent并将事件分派给ViewPager来解决这个问题。

private ViewPager mPager;

@Override
protected void onFinishInflate() {
    mPager = (ViewPager) getChildAt(0);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    return mPager.dispatchTouchEvent(ev);
}

But the truth is you're better off using the more modern solutions to this stuff. 但事实是,你最好使用更现代的解决方案。

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.TabLayout
            android:id="@+id/result_tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/grey"
            app:tabIndicatorColor="@color/colorPrimary"
            app:tabMode="scrollable"
            app:tabSelectedTextColor="@color/colorPrimary"
            app:tabTextColor="@color/medium_grey" />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

So tabbed layout and a properly setup viewpager. 所以选项卡式布局和正确设置的viewpager。 Though even this is going to be kind of obsolete once Google finishes up their Navigation bit in their Architecture Components. 虽然谷歌在他们的架构组件中完成导航位后,即使这样也会过时了。

You have to manually detect the touch events, and see if it's coordinates lie within the bounds of the pages outside the bounds. 您必须手动检测触摸事件,并查看它的坐标是否位于边界外的页面范围内。 So going off of what Tatarize states, before dispatching touch events to the pager, you should check if the event is within one of the pages of the view pager. 因此,在将触摸事件发送到寻呼机之前,关闭Tatarize所述的内容,您应该检查事件是否在视图寻呼机的一个页面内。

Here is example code, I'm only checking if the x lies within the bounds and not the y in childContains(). 这是示例代码,我只检查x是否位于边界内而不是childContains()中的y。

@Override
public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                return pager.dispatchTouchEvent(event);
            case MotionEvent.ACTION_UP:
                int childCount = pager.getChildCount();
                int x = (int) event.getX();
                int y = (int) event.getY();
                for (int i = 0; i < childCount; i++) {
                    final View child = pager.getChildAt(i);
                    if (childContains(child, x)) {
                        // delay the click minimally in-case
                        // callOnClick performs mods on the pager
                        // 
                        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                child.callOnClick();
                            }
                        }, 100);
                        return true;
                    }
                }
                break;
        }

        return pager.dispatchTouchEvent(event);
    }

int[] loc = new int[2];
private boolean childContains(View child, final int x) {
        child.getLocationOnScreen(loc);
        int x1_child = loc[0];
        int x2_child = x1_child + child.getWidth();
        int x0 = x;
        boolean isInside = x0 >= x1_child && x0 < x2_child;

        Log.v("childContains()", String.format("x: %s x1_child: %s x2_child: %s isInside: %s",
                x0, x1_child, x2_child, String.valueOf(isInside)));
        return isInside;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM