A solution to the conflict in view gesture sliding in Android _android

Source: Internet
Author: User
Tags abs gety touch

The collision of the Android gesture event is closely related to the distribution of the Click event, which is accomplished by three important methods: Dispatchtouchevent, Onintercepttouchevent and Ontouchevent.

public boolean dispatchtouchevent (motionevent ev)

This method is used to distribute the event. If the event is passed to view, the method is bound to be invoked, and the result is affected by the ontouchevent of the current view and the Dispatchtouchevent method of the subordinate view, indicating whether the current event is consumed.

 public boolean onintercepttouchevent (Motionevent event)

Called inside the above method to determine that an event is intercepted, and if the current view intercepts an event, then in the same sequence of events, this method is not invoked again, and the result indicates whether the current event is blocked.

 public boolean ontouchevent (Motionevent event)

Called in the Dispathctouchevent method, which handles the Click event, returns whether the current event is consumed, and if not, the current view cannot be received again in the same sequence of events.

Cases:

  public boolean dispatchtouchevent (motionevent ev) {

       Boolean consume = false;

      if (onintercepttouchevent (EV)) {

          consume = ontouchevent (EV);

       }  else {

         consum = child.dispathctouchevent (EV);

      }

    return consume;

   }

The solution to the gesture conflict is to use the above three methods, mainly divided into two solutions: • 1 External intercept Method 2 internal interception method

1. Common sliding conflict scenarios

1.1 The direction of the external sliding direction is inconsistent with the internal slide

This situation we often meet, such as the use of viewpaper+listview, in this effect, you can slide through the left and right to switch pages, and each page is often a ListView, originally in this case there is conflict, But Viewpaper internal handling of this sliding conflict, so the use of viewpaper we do not need to pay attention to this problem, if we are not viewpaper but ScrollView, and so on, you must manually handle the sliding conflict, or both inside and outside can only have a layer of sliding, That's the sliding conflict. In addition, the internal and external sliding, the outer and lower sliding also belong to the class.

1.2 The external sliding direction and the internal sliding direction are the same

This situation is more complex, when both inside and outside the two layers in the same direction can be sliding, there is obviously a logic problem, because when the fingers start to slide, the system can not know what the user is trying to make that layer of movement, so when the fingers slide will be a problem, or only a layer of movement, or both inside and outside 20% moving are very cotton.

2. Give the solution

2.1 External interception method

For Scenario 1, we can see that the external and internal sliding directions are different, that is, if you judge the current dy and dx sizes, if DY>DX, then the current is vertical sliding, otherwise it is horizontal sliding. With that in hand, I can begin to intercept the current gesture.


From the previous section we analyzed the view event distribution, and we know that the distribution order of the Click events is distributed through the parent layout, and if the parent layout is not blocked, the Onintercepttouchevent returns false before it is passed to the child view. So we can use the Onintercepttouchevent () method to intercept the event. Take a look at the code:

 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: {
      intercepted = false;
      break;
    Case Motionevent.action_move: {
      if (rule blocked by parent container) {
        intercepted=true
      } else{
        intercepted=false;
      }
      break;
    Case MOTIONEVENT.ACTION_UP: {
      intercepted = false;
      break;
    Default: Break
      ;
    }
    mlastxintercept=x;
    mlastyintercept=y;
    return intercepted;
  }

The above code is much less than the general template for external interception, in the Onintercepttouchevent method,

The first is to action_down this event, the parent container must return false, that is, do not intercept the event, because once the parent container intercepts the Action_down event, subsequent Action_move and ACTION_UP events will be delivered directly to the parent container. This time the event cannot continue to pass to the child element;

Then it is action_move this event, which can be used to determine whether or not to intercept, return TRUE if the parent container needs to be intercepted, or false;

The last is Action_up this event, which must return false, because the event itself does not have much meaning.

Here we will do the interception of the operation, we need to slide horizontally when the parent container to intercept the event.

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: {
      intercepted = false;
      break;
    Case Motionevent.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;
    Default: Break
      ;
    }
    mlastxintercept=x;
    mlastyintercept=y;
    return intercepted;
  }

From the above code point of view, we just modified the interception conditions, so the external interception is very simple and convenient. In the process of sliding, horizontal sliding is determined when the horizontal distance is large.

We have always done experiments to prove the style of the theory, we come from the definition of a horizontalscrollview to reflect the use of external interception method to resolve the pleasure of conflict.

First the code:

Package com.gxl.viewtest;
Import Android.animation.Animator;
Import Android.animation.ObjectAnimator;
Import Android.content.Context;
Import Android.text.LoginFilter;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import Android.view.GestureDetector;
Import android.view.MotionEvent;
Import Android.view.VelocityTracker;
Import Android.view.View;
Import Android.view.ViewGroup;

Import Android.widget.Scroller;
 /** * S * Created by GXL on 2016/7/25 0025.
  * * public class Horizontalscrollview extends ViewGroup {private final String TAG = "Horizontalscrollview";
  Private Velocitytracker Mvelocitytracker;
  Private Scroller Mscroller;
  private int mchildrensize;
  private int mchildwidth;
  private int mchildindex;
  Last sliding coordinates private int mlastx = 0;
  private int mlasty = 0;
  The coordinates of the last interception slide, private int mlastxintercept = 0;

  private int mlastyintercept = 0;
    Public Horizontalscrollview {Super (context);
  Init (context); } public HorizonTalscrollview (context, AttributeSet attrs) {Super (context, attrs);
  Init (context); Horizontalscrollview (context, AttributeSet attrs, int defstyleattr) {Super (context, Attrs, defsty
    LEATTR);
  Init (context);
    public void init (context context) {Mvelocitytracker = Velocitytracker.obtain ();
  Mscroller = new Scroller (context);
    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: {intercepted = false;
      Break
        Case Motionevent.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
    } Default:break;
    } 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:break;
        Case MotionEvent.ACTION_MOVE:int deltax = X-MLASTX; if ((Getscrollx ()-deltax) >=0&& (GETSCROLLX ()-deltax) <= (Getmeasuredwidth ()-
        Screenutils.getscreenwidth (GetContext ())) {Scrollby (-deltax, 0);
      } break;
        Case MotionEvent.ACTION_UP:mVelocityTracker.computeCurrentVelocity (1000);
        float Xvelocitytracker = mvelocitytracker.getxvelocity ();
          if (Math.Abs (Xvelocitytracker) >) {if (Xvelocitytracker > 0) {log.i (TAG, "fast Right"); } else {log.i (TAG, "fast left Row");
        } mvelocitytracker.clear ();
    Break
    } MLASTX = x;
    Mlasty = y;
  return true; @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (widthmeasures
    PEC, Heightmeasurespec);
    int measuredwidth = 0;
    int measureheight = 0;
    Final int childcount = Getchildcount ();
    Measurechildren (Widthmeasurespec, Heightmeasurespec);
    int widthspacesize = measurespec.getsize (Widthmeasurespec);
    int widthspacemode = Measurespec.getmode (Widthmeasurespec);
    int heightspacesize = measurespec.getsize (Heightmeasurespec);

    int heightspacemode = Measurespec.getmode (Heightmeasurespec);
    if (ChildCount = = 0) {setmeasureddimension (0, 0); else if (Heightspacemode = = Measurespec.at_most && Widthspacemode = measurespec.at_most) {final View chi
      Ldview = Getchildat (0); Measuredwidth = Childview.getmeasuredwidth () * ChildcoUnt
      Measureheight = Childview.getmeasuredheight ();
    Setmeasureddimension (Measuredwidth, measureheight);
      else if (Heightspacemode = = measurespec.at_most) {measureheight = Getchildat (0). Getmeasuredheight ();
    Setmeasureddimension (Widthspacesize, measureheight);
      else if (Widthspacemode = = measurespec.at_most) {final View Childview = getchildat (0);
      Measuredwidth = Childview.getmeasuredwidth () * CHILDCOUNT;
    Setmeasureddimension (Measuredwidth, heightspacesize); } @Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) {log.i (TAG, "onlayout:" +
    Getmeasuredwidth ());
    int childleft = 0;
    Final int childcount = Getchildcount ();
    Mchildrensize = ChildCount;
      for (int i = 0; i < mchildrensize i++) {final View Childview = Getchildat (i);
        if (childview.getvisibility ()!= view.gone) {final int childwidth = Childview.getmeasuredwidth ();
Mchildwidth = Childwidth;        Childview.layout (childleft, 0, Childleft + mchildwidth, childview.getmeasuredheight ());
      Childleft + = Childwidth;
    }} private void Smoothscrollto (int destx,int desty) {int scrollx=getscrollx ();
    int delta=destx-scrollx;
  Mscroller.startscroll (scrollx,0,delta,0,1000); @Override public void Computescroll () {if (Mscroller.computescrolloffset ()) {Scrollto (Mscroller.getcurr
      X (), Mscroller.getcurry ());
    Postinvalidate ();

 }
  }
}

Look at the layout file again.

 <com.gxl.viewtest.horizontalscrollview
    android:layout_width= "wrap_content"
    android:layout_height= " Match_parent "
    android:background=" #00ff00 "
    >

    <listview
      android:id=" @+id/listview1
      " Android:layout_width= "600DP"
      android:layout_height= "match_parent"
      android:background= "@color Colorprimary "
      >
    </ListView>

    <listview
      android:id=" @+id/listview2 "
      Android : layout_width= "600DP"
      android:layout_height= "match_parent"
      android:background= "@color/coloraccent"
      >
    </ListView>

    <listview
      android:id= "@+id/listview3"
      android:layout_width = "600DP"
      android:layout_height= "match_parent"
      android:background= "#ff0000"
      >
    </ Listview>

  </com.gxl.viewtest.HorizontalScrollView>

The above is the external handle sliding conflict code, carefully look, the idea is very clear. It also involves a number of custom view knowledge, I will be in the back of the posting serious analysis of the code, you first look at the onintercepttouchevent handle sliding conflict section.
Look at the effect of the picture ha.

2.2 Internal interception method

Internal interception means that the parent container does not intercept any events, all events are passed to the child element, if the child element needs this event to consume directly, otherwise it will be handed to the parent container to deal with, this method and the event distribution mechanism in the Android is inconsistent, Need to cooperate with Requestdisallowintercepttouchevent method to work properly, the general explanation of this method is:

Requestdisallowintercepttouchevent is a common method in the ViewGroup class, and the argument is a Boolean value, as described in the official

Called when a child does not want this parent and its ancestors to intercept the touch of events with Viewgroup.onintercepttouche Vent (motionevent).
This parent should pass this is call onto its parents. This parent must obey this request for the duration of the touch (which, only clear the flag on this parent has RECEI Ved an up or a cancel.

In the Android system, a click event is passed from the parent view to the child view, and each level view determines whether the click event is intercepted and handled or passed to the next level, and if the child view does not handle the Click event, the event passes the parent view, It is up to the parent view to decide whether to handle the Click event. In child view You can set this method to tell the parent view not to intercept and handle the click event, and the parent view should accept the request until the Click event ends.

The external interception event is slightly more complex to use. Let me take a look at its generic template (note that the following code is defined in child view):

public boolean onintercepttouchevent (Motionevent event) {
    int x = (int) event.getx ();
    int y = (int) event.gety ();

    Switch (event.getaction ()) {case
    Motionevent.action_down: {
      parent.requestdisallowintercepttouchevent ( true); Parent layout do not block this event break
      ;
    Case Motionevent.action_move: {
      int deltax=x-mlastxintercept;
      int deltay=y=mlastyintercept;
      If (event that the parent container needs to intercept) {
        parent.requestdisallowintercepttouchevent (false);//parent layout needs to intercept this event
      } break
      ;
    }
    Case MOTIONEVENT.ACTION_UP: {
      intercepted = false;
      break;
    Default: Break
      ;
    }
    mlastxintercept=x;
    mlastyintercept=y;
    Return Super.dispathtouchevent (event);
  }

The above code is the internal interception of the typical code, when faced with a different sliding strategy only need to modify the conditions inside, others do not need to modify the changes and can not change.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.