Discussion on the solution of sliding conflict in the scrollview of Android practice _android

Source: Internet
Author: User
Tags gety

1. Foreword

In Android development, if it's a simple layout, it's easy to fix, but when it comes to complex pages, especially if you use ScrollView to be compatible with small-screen handsets, there's a lot of click-Event Conflicts, The most classic is the ScrollView nested in the ListView. I think most of the students who have just started to touch Android have stepped into the pit, and this article starts with a recent project, and then provides some ideas for resolving conflicts in the process.

2. Project initiation

Project has a page that involves Viewpager,mapview,listview, that is, in a page, there will be these three view, it is obvious that the screen can not be fully displayed, need ScrollView to do the support, The ScrollView is introduced as the outer container. But as the page's data show needs to be done manually by users to refresh, and then introduced the official swiperefreshlayout.

So the layout of the page becomes this way. The following figure (detail layout ignored).

Figure-1 layout diagram

After joining the ScrollView and Swiperefreshlayout, we introduced a new problem, that is, the event conflicts between the controls, the Viewpager, Mapview, ListView all need to be able to handle the Click event correctly, especially the ListView, the requirement that it can slide in ScrollView, the two kinds of sliding are confused together, not especially good to deal with.

The problem is put forward, the following directly look at the solution idea.

3. The idea of solving the sliding conflict

There is a method in ViewGroup called Requestdisallowintercepttouchevent (Boolean disallowintercept), which can be used to control whether the ViewGroup truncates the Click event. We solve the sliding conflict, in fact, is at a certain time to call this method, so that the parent layout does not truncate the Click event, the Click event passed to the child view, so that the relevant child view to deal with.

Here are some examples and reflections on dealing with various click-Event conflicts in a project. The approach is only to provide a way of thinking, may not be the best method, there must be other ideas of the solution.

The following scenarios for dealing with sliding conflicts are handled in the ontouchlistener of the child view, and there is no replication of the control's Click event Processing, which is more convenient in use.

3.1 Mapview Map page sliding conflict

The main conflict between Mapview and ScrollView is that when the user clicks on the Mapview map and slides, it is hoped that the map will handle the click events, including the subsequent slide events, the two-finger scaling map, and so on.

In ScrollView, is the default truncation click event, causing users to click on the map, the map is basically no response, not to mention the two hands to zoom map.

The user clicks the map on the finger, and sliding, it is difficult to determine whether the user is to scrollview up and down or manipulate the map content sliding, so I simply think, as long as the user finger click to map, it is to the map to operate; When the user's finger is lifted, the user does not need to operate the map.

The solution is also very simple, that is, when users click on the map or slide map, so that ScrollView do not truncate click events, and pass to the child view processing, that is, map to deal with Click events, when the user's finger is raised, the state of the ScrollView back to the previous state, That is, ScrollView can truncate the Click event.

I use the Baidu map, directly on the code, easier to understand.

Mmapview.getchildat (0). Setontouchlistener (New View.ontouchlistener () {
      @Override public
      boolean Ontouch ( View V, motionevent event) {
        if (event.getaction () = = motionevent.action_up) {
          //Allow ScrollView truncate click event, ScrollView can be sliding
          mscrollview.requestdisallowintercepttouchevent (false);
        else{
          //Do not allow ScrollView truncation Click event, click event Child View Processing
          mscrollview.requestdisallowintercepttouchevent (TRUE);
        }
        return false;
      }
    });

3.2 Viewpager Sliding conflict resolution

In this project, Viewpager at the top of the page, if only the ScrollView inside the Viewpager, because the two controls are in different directions of the sliding event, so the basic will not conflict.

However, due to the introduction of Swiperefreshlayout, I found that in the sliding viewpager, it is easy to trigger the swiperefreshlayout down to refresh, which may block the Viewpager left and right sliding effect, experience is very bad. And in the process of sliding viewpager, the user's sliding is certainly not always horizontal, there will be a certain degree of upward downward sliding.

Viewpager processing conflicts and map processing conflicts are somewhat different, because when users click on the Viewpager, in the sliding process, the basic can be guessed that the user is going to slide around the Viewpager or up and down ScrollView (or Drop-down refresh), which can not be like a map, When clicked to Viewpager, it is forbidden to ScrollView truncation Click event (or Swiperefreshlayout drop-down refresh function), it is necessary to make a judgment in the process of sliding.

The solution is to set a threshold, once the user in the x-axis is the horizontal sliding distance over this threshold, I think the user is to the left and right sliding viewpager, on the ban ScrollView truncation click events at the same time set swiperefreshlayout can not be pulled down to refresh. When the user lifts the finger, it is assumed that the user has completed the operation of the Viewpager, and the ScrollView and Swiperefreshlayout states are restored.

 Mviewpager.setontouchlistener (New View.ontouchlistener () {
  @Override public
  boolean Ontouch View V, Motionevent event) {
    int action = Event.getaction ();

    if (action = = Motionevent.action_down) {
      //record clicks to Viewpager, the finger's x-coordinate
      mlastx = Event.getx ();
    }
    if (action = = motionevent.action_move) {
      //exceed Threshold
      if (Math.Abs (Event.getx ()-MLASTX) > 60f) {
        Mrefreshlayout.setenabled (false);
        Mscrollview.requestdisallowintercepttouchevent (True);
      }
    if (action = = motionevent.action_up) {
      //the user lifts their fingers and restores the parent layout state
      Mscrollview.requestdisallowintercepttouchevent ( FALSE);
      Mrefreshlayout.setenabled (true);
    return false;
  }
});

The user clicks to Viewpager time, records clicks the position the x coordinates, when the user slides the process, if the slide above the x axis surpasses the threshold (I write is 60f, this can set the best threshold in the actual use), prohibits ScrollView truncation clicks the event, Settings cannot be pulled down at the same time. When the user's finger leaves the screen, the ScrollView and swiperefreshlayout states are restored.

3.3 ListView Sliding Conflict resolution

There are all kinds of strange problems with nesting listview in ScrollView. For example, ListView show that there is a problem, it may be only one or two item so high, and not fully expanded. There are two ways to solve this problem on the Internet.

    • According to the number of display data multiplied by the height of each item, calculate the overall height of the ListView, and then dynamically set the height of the listview
    • Replication ListView onmeasure (int widthmeasurespec, int heightmeasurespec) method, let ListView fully expand

Both of these methods can solve the problem of ListView display incomplete, but also can slide (in fact, the use of scrollview sliding effect), but there is one of the biggest regret is that the ListView inside the view can not be reused. Because both of these methods calculate the full height of the ListView and then set the height of the ListView control to this height, then ListView is equivalent to a linearlayout layout, losing the advantage of the reuse view, And in some scenes may not have linearlayout easy to use, what is more, if there are a large number of pictures, it is easy to oom, which is the most in the research and development process do not want to see.

can refer to the United States Regiment, the United States, the home page, is a scrollview, the decline will be found, and can not be infinite downward slide, to the bottom will be reminded to jump to a level two page to see all the purchase information. This is a solution that handles ScrollView nesting like a ListView list layout.
But in this project that I met, it can't be handled like this.

The two solutions mentioned above are very clear and it is important to determine the height of the listview if you want to listview the normal presentation.

So first, I need to set the height of the ListView in the layout file, which is a definite value. After setting the height, you can reuse view if the total item height of the data in the ListView exceeds the height set by ListView. But this only solves the ListView display Problem, ListView and ScrollView sliding conflict, and not resolved.

To resolve the sliding conflict, the main thing is to determine the time to prohibit ScrollView truncation of click events, and then to analyze the timing.

    • ScrollView is not sliding to the bottom, if the Click and Slide ListView time, ListView can not be sliding, not prohibited.
    • If the ScrollView sliding to the bottom, and ListView has been to the top, continue to pull ListView, in fact, will pull scrollview, not prohibited.
    • If the scrollview slides to the bottom, the user slides up, listview, and disables ScrollView truncation click event capability

Obviously, it's important to know if ScrollView is sliding to the bottom when judging the time to ban ScrollView truncation. Thus, the ScrollView scrollchanged () method is rewritten to determine if ScrollView is sliding to the bottom (in the SDK API 23 version ScrollView can set Setonscrollchangelistener () To monitor the sliding changes, but the previous version does not support, in order to be compatible, you need to rewrite it.

@Override
protected void onscrollchanged (int l, int t, int oldl, int Oldt) {
  super.onscrollchanged (L,t,oldl,oldt );
  The distance of the slide plus the height of the child view is compared to that of the
  if (T + getheight () >= getchildat (0). Getmeasuredheight ()) {
    //ScrollView slide to the bottom
    if (Monscrolltobottomlistener!= null) {
      monscrolltobottomlistener.onscrolltobottom ();
    }
  } else {
    if (Monscrolltobottomlistener!= null) {
      monscrolltobottomlistener.onnotscrolltobottom ();
    }
  }
} Public

void Setscrolltobottomlistener (Onscrolltobottomlistener listener) {
  This.monscrolltobottomlistener = Listener;
}

Public interface Onscrolltobottomlistener {
  void Onscrolltobottom ();
  void Onnotscrolltobottom ();
}

With the idea, and scrollview sliding to the bottom of the logo can also get, the following can be directly to solve the sliding conflict, directly look at the code.

Mscrollview.setscrolltobottomlistener (New Bottomscrollview.onscrolltobottomlistener () {@Override public void OnScro
  Lltobottom () {issvtobottom = true;
  @Override public void Onnotscrolltobottom () {issvtobottom = false;

}
}); Mlistview.setontouchlistener (New View.ontouchlistener () {@Override public boolean ontouch (View V, motionevent event)

    {int action = event.getaction ();
    if (action = = motionevent.action_down) {mlasty = Event.gety ();
      } if (action = = motionevent.action_move) {int top = Mlistview.getchildat (0). GetTop ();
      float Nowy = event.gety (); if (!issvtobottom) {//Allow ScrollView intercept Click event, ScrollView slide mscrollview.requestdisallowintercepttouchevent (FAL
      SE);
        else if (top = = 0 && nowy-mlasty > Threshold_y_list_view) {//Allow ScrollView intercept Click event, ScrollView Slide
      Mscrollview.requestdisallowintercepttouchevent (FALSE);
    else {//do not allow ScrollView intercept click event, ListView Slide    Mscrollview.requestdisallowintercepttouchevent (TRUE);
  return false;

 }
});

As opposed to other controls, the sliding conflict between ListView and ScrollView is more difficult to solve, but in practice it is not recommended in the actual use of ScrollView nested listview, once the business is complex, it is easy to have a variety of UI and business logic conflict errors.

4. Operation effect

Because the map to join more trouble, so in the demo did not introduce the map. Look at the effect of the operation.

Figure-2 Run effect

5. Summary

This article is just a way to provide a solution to the idea, in a specific scenario, the interaction is often tailored to the specific business needs. However, it is most important to find out the timing of the Click event truncation and processing, and the solution is always found around this key point.

Enclosed Demo Project Address: Demo

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.