Android Emitting touch events on a child view made outside the bounds of a view clip (ViewPager Page 1 - Page 2)

My Android ViewPager is set to draw views out of bounds (click limits set to false). I have a listener for touch events in all views that are displayed on a page. The custom view is rendered on page 1, drawn outside of its clipped borders and overflows on page 2. The touch event on page 1 works fine. Scrolling to the second page displays the remaining image. The problem is that the touch event on the custom view (added on page 1) is not called when clicked on page 2.

PageViewActivity.cs

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

      

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

Any suggestions?

+3


source to share


2 answers


From: http://shashikaonline.com/2012/12/13/android-viewpager-with-multiple-views/

But the problem is here. We can only use the middle view. This is because touch events occur outside of the bounds of the ViewPagers. We can override the onTouchEvent of the ViewPagerContainer and dispatch events to the ViewPager to solve this problem.



private ViewPager mPager;

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

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

      

0


source


You need to manually define touch events and see if they overlap within pages outside of boundaries. Therefore, when sending information about what Tatarize is, before sending touch events to the pager, you should check if the event is on one of the view pager pages.

Here is some sample code, I only check if x is in bounds and not y in childContains ().



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

      

0


source







All Articles