Sliding conflict of views in Android-Android development art exploration notes

Source: Internet
Author: User

Sliding conflict of views in Android-Android development art exploration notes
Introduction

I believe that Android Developers will have this experience: the demo downloaded from the Internet runs well, but as long as there is a sliding conflict, the Demo will not work properly. But don't worry. There is a fixed solution to sliding conflicts. There are two common methods: internal interception and external interception, which can be solved smoothly.

Common slide conflicts

Example

Processing rules

For scenario 1, the processing rule is: when the user slides left and right, let the external View intercept click events. When the user slides up and down, let the internal View intercept click events. When a slide occurs, based on the starting point and the End Point Coordinate Position of the slide, if the vertical sliding distance is large, it is regarded as vertical sliding; otherwise, it is determined as horizontal sliding. The other two situations are handled in a similar way,The rules are derived from the business needs.

Solution external Interception

All click events are intercepted by the parent container first. If the parent container needs to be intercepted, It is intercepted and transmitted to the internal View without any need. The pseudocode is as follows:

Public boolean onInterceptTouchEvent (MotionEvent event) {boolean intercepted = false; switch (event. getAction () {case MotionEvent. ACTION_DOWN: {intercepted = false; break;} case MotionEvent. ACTION_MOVE: {if (meeting the interception requirements of the parent container) {intercepted = true;} else {intercepted = false;} break;} case MotionEvent. ACTION_UP: {intercepted = false; break;} default: break;} mLastXIntercept = x; mLastYIntercept = y; return intercepted ;}

Note:
The ACTION_DOWN event cannot be intercepted, because the parent container will process the subsequent events once they are intercepted.

Internal Interception Method

The parent container does not intercept any events. All events are transmitted to sub-elements. If the child element requires this event, it will be directly consumed; otherwise, it will be handed over to the parent container for processing. To complete this function, you must use the requestDisallowInterceptTouchEvent () method. This method indicates whether to allow the parent container to intercept events. The pseudocode is as follows:

Public boolean dispatchTouchEvent (MotionEvent event) {int x = (int) event. getX (); int y = (int) event. getY (); switch (event. getAction () {case MotionEvent. ACTION_DOWN: {parent. requestDisallowInterceptTouchEvent (true); break;} case MotionEvent. ACTION_MOVE: {if (meeting the interception requirements of the parent container) {parent. requestDisallowInterceptTouchEvent (false);} break;} case MotionEvent. ACTION_UP: {break;} default: break;} mLastX = x; mLastY = y; return super. dispatchTouchEvent (event );}

Note
The parent container intercepts events other than ACTION_DOWN by default, so that when the element calls parent. requestDisallowInterceptTouchEvent (false), the parent element can intercept the required events.

There are two methods to solve the sliding conflict. We recommend the external interception method, which is easy to implement. This article uses scenario 1 as an example to explain how scenario 2 and 3 are similar to scenario 1. processing rules are developed based on business needs. Source code of the sample effect Activity
public class DemoActivity_1 extends Activity {    private static final String TAG = "DemoActivity_1";    private HorizontalScrollViewEx mListContainer;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.demo_1);        Log.d(TAG, "onCreate");        initView();    }    private void initView() {        LayoutInflater inflater = getLayoutInflater();        mListContainer = (HorizontalScrollViewEx) findViewById(R.id.container);        final int screenWidth = MyUtils.getScreenMetrics(this).widthPixels;        final int screenHeight = MyUtils.getScreenMetrics(this).heightPixels;        for (int i = 0; i < 3; i++) {            ViewGroup layout = (ViewGroup) inflater.inflate(                    R.layout.content_layout, mListContainer, false);            layout.getLayoutParams().width = screenWidth;            TextView textView = (TextView) layout.findViewById(R.id.title);            textView.setText("page " + (i + 1));            layout.setBackgroundColor(Color.rgb(255 / (i + 1), 255 / (i + 1), 0));            createList(layout);            mListContainer.addView(layout);        }    }    private void createList(ViewGroup layout) {        ListView listView = (ListView) layout.findViewById(R.id.list);        ArrayList
  
    datas = new ArrayList
   
    ();        for (int i = 0; i < 50; i++) {            datas.add("name " + i);        }        ArrayAdapter
    
      adapter = new ArrayAdapter
     
      (this,                R.layout.content_list_item, R.id.name, datas);        listView.setAdapter(adapter);        listView.setOnItemClickListener(new OnItemClickListener() {            @Override            public void onItemClick(AdapterView
       parent, View view,                    int position, long id) {                Toast.makeText(DemoActivity_1.this, "click item",                        Toast.LENGTH_SHORT).show();            }        });    }}
     
    
   
  
Horizontally Sliding View
Public class HorizontalScrollViewEx extends ViewGroup {private static final String TAG = "HorizontalScrollViewEx"; private int mChildrenSize; private int mChildWidth; private int mChildIndex; // respectively record the coordinate private int mLastX = 0; private int mLastY = 0; // respectively record the coordinate of the last sliding (onInterceptTouchEvent) private int mLastXIntercept = 0; private int mLastYIntercept = 0; private Scroller mScroller; private Veloc ItyTracker mVelocityTracker; public HorizontalScrollViewEx (Context context) {super (context); init ();} public HorizontalScrollViewEx (Context context, AttributeSet attrs) {super (context, attrs ); init ();} public HorizontalScrollViewEx (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); init ();} private void init () {mScroller = new Scroller (getContext (); mVeloc ItyTracker = VelocityTracker. obtain () ;}@ Override public boolean onInterceptTouchEvent (MotionEvent event) {boolean intercepted = false; int x = (int) event. getX (); int y = (int) event. getY (); switch (event. getAction () {case MotionEvent. ACTION_DOWN: {Log. d (TAG, "onInterceptTouchEvent: ACTION_DOWN"); intercepted = false; if (! MScroller. isFinished () {mScroller. abortAnimation (); intercepted = true;} break;} case MotionEvent. ACTION_MOVE: {Log. d (TAG, "onInterceptTouchEvent: ACTION_MOVE"); int deltaX = x-mLastXIntercept; int deltaY = y-mLastYIntercept; if (Math. abs (deltaX)> Math. abs (deltaY) {intercepted = true;} else {intercepted = false;} break;} case MotionEvent. ACTION_UP: {intercepted = false; break;} de Fault: break;} Log. d (TAG, "intercepted =" + intercepted); mLastX = x; mLastY = y; mLastXIntercept = x; mLastYIntercept = y; return intercepted ;} @ Override public boolean onTouchEvent (MotionEvent event) {mVelocityTracker. addMovement (event); int x = (int) event. getX (); int y = (int) event. getY (); switch (event. getAction () {case MotionEvent. ACTION_DOWN: {Log. d (TAG, "onTouchEvent: ACTION_DOWN "); If (! MScroller. isFinished () {mScroller. abortAnimation ();} break;} case MotionEvent. ACTION_MOVE: {Log. d (TAG, "onTouchEvent: ACTION_MOVE"); int deltaX = x-mLastX; int deltaY = y-mLastY; Log. d (TAG, "onTouchEvent: deltaX" + deltaX); scrollBy (-deltaX, 0); break;} case MotionEvent. ACTION_UP: {int scrollX = getScrollX (); int scrollToChildIndex = scrollX/mChildWidth; mVelocityTracker. computeCurrent Velocity (1000); float xVelocity = mVelocityTracker. getXVelocity (); // when the sliding speed reaches the threshold, it is deemed that the next page needs to be entered if (Math. abs (xVelocity)> = 100) {mChildIndex = xVelocity> 0? MChildIndex-1: mChildIndex + 1;} else {// If the sliding distance exceeds half, mChildIndex = (scrollX + mChildWidth/2)/mChildWidth ;} // ensure that mChildIndex = Math will not cross the border when sliding on the 0 and last pages. max (0, Math. min (mChildIndex, mChildrenSize-1); // failed to reach the next page, restored to the original int dx = mChildIndex * mChildWidth-scrollX; smoothScrollBy (dx, 0); Log. d (TAG, "onTouchEvent: dx =" + dx); mVelocityTracker. clear (); break;} default: break;} mLastX = X; mLastY = y; return true;} @ Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, interval); int measuredWidth = 0; int measuredHeight = 0; final int childCount = getChildCount (); measureChildren (widthMeasureSpec, interval); int widthSpaceSize = MeasureSpec. getSize (widthMeasureSpec); int widthSpecMode = MeasureSpec. GetMode (widthMeasureSpec); int heightSpaceSize = MeasureSpec. getSize (heightMeasureSpec); int heightSpecMode = MeasureSpec. getMode (heightMeasureSpec); if (childCount = 0) {setMeasuredDimension (0, 0);} else if (heightSpecMode = MeasureSpec. AT_MOST) {final View childView = getChildAt (0); measuredHeight = childView. getMeasuredHeight (); setMeasuredDimension (widthSpaceSize, childView. getMeasuredHe Ight ();} else if (widthSpecMode = MeasureSpec. AT_MOST) {final View childView = getChildAt (0); measuredWidth = childView. getMeasuredWidth () * childCount; setMeasuredDimension (measuredWidth, heightSpaceSize);} else {final View childView = getChildAt (0); measuredWidth = childView. getMeasuredWidth () * childCount; measuredHeight = childView. getMeasuredHeight (); setMeasuredDimension (measuredWidth, MeasuredHeight) ;}@override protected void onLayout (boolean changed, int l, int t, int r, int B) {int childLeft = 0; final int childCount = getChildCount (); mChildrenSize = childCount; for (int I = 0; I <childCount; I ++) {final View childView = getChildAt (I); if (childView. getVisibility ()! = View. GONE) {final int childWidth = childView. getMeasuredWidth (); mChildWidth = childWidth; childView. layout (childLeft, 0, childLeft + childWidth, childView. getMeasuredHeight (); childLeft + = childWidth ;}} private void smoothScrollBy (int dx, int dy) {mScroller. startScroll (getScrollX (), 0, dx, 0,500); invalidate () ;}@ Override public void computeScroll () {if (mScroller. computescroloffset () {scrollTo (mScroller. getCurrX (), mScroller. getCurrY (); postInvalidate () ;}@ Override protected void onDetachedFromWindow () {mVelocityTracker. recycle (); super. onDetachedFromWindow ();}}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.