Android Imitation QQ list sliding delete operation _android

Source: Internet
Author: User
Tags gety

This cottage a new version of the list of QQ slide Delete, the last article on the slide to delete the QQ, speculated that the principle is ListView itself each item there is a button, but the general state of the hidden off, detect the left slide when the event pops up hidden button, However, when you switch button state, you give the button a show and hidden animation. This listview is implemented below.

The first difficulty is to get a view of its item through ListView, for ViewGroup, you can directly invoke the Getchildat () method to obtain the corresponding child view, but in ListView directly using Getchildat (), Will find that as long as the slide listview will report null pointer anomaly, it is obvious to ListView direct use of Getchildat () method is not feasible, although ListView is a viewgroup. It has been explained that the problem and the solution, presumably, is to understand that ListView, although it seems to have a lot of item, but this is just looking, in fact, ListView only constructs what you can see, is the screen can see so many item view, So to get a view of the item ListView a location position, you need to use the following code:

int firstvisiblepos = Getfirstvisibleposition ()-Getheaderviewscount ();
int factpos = Curpos-firstvisiblepos;
 Mitemview = Getchildat (Factpos);

is to get ListView the first visible item Firstvisiblepos, of course, but also remember to subtract the number of header view, Then use to get the item CurPos minus Firstvisiblepos is the corresponding item actually in listview position Factpos. This will not report null pointer exception.

Knowing the view of the item at a certain location, you now need to detect the slide event to determine which position's item is currently interacting with ListView. Use the following methods in ListView:

int curpos = pointtoposition ((int) CurX, (int) cury);

The next step is to intercept ListView's touch events, customize a Slidingdeletelistview, inherit from ListView, rewrite the Ontouchevent () method:

  @Override public boolean ontouchevent (Motionevent event) {if (!menablesliding) return false;
    if (mcancelmotionevent && event.getaction () = = Motionevent.action_move) {return true; else if (mcancelmotionevent && event.getaction () = = Motionevent.action_down) {event.setaction (motionevent.
    Action_cancel);  Switch (event.getaction ()) {case Motionevent.action_down: {if (mtracker = null) Mtracker =
        Velocitytracker.obtain ();

        else Mtracker.clear ();
        Mlastmotionx = Event.getx ();
      Mlastmotiony = Event.gety ();

      }break;
        Case Motionevent.action_move: {mtracker.addmovement (event);
        Mtracker.computecurrentvelocity (1000);

        int Curvelocityx = (int) mtracker.getxvelocity ();
        float CurX = Event.getx ();
        float Cury = event.gety ();
        int lastpos = pointtoposition ((int) Mlastmotionx, (int) mlastmotiony); int CurPos = Pointtoposition ((int) CurX, (int) cury);
        int Distancex = (int) (MLASTMOTIONX-CURX); if (Lastpos = = CurPos && (Distancex >= max_distance | | Curvelocityx <-max_fling_velocity)) {int F
          Irstvisiblepos = Getfirstvisibleposition ()-Getheaderviewscount ();
          int factpos = Curpos-firstvisiblepos;
          Mitemview = Getchildat (Factpos); if (Mitemview!= null) {if (Mbuttonid = 1) throw new Illegalbuttonidexception ("Illegal deletebu

            Tton resource ID, "+" ensure excute the function setbuttonid (int id));
            Mbutton = Mitemview.findviewbyid (Mbuttonid);
            Mbutton.setvisibility (view.visible);

            Mbutton.startanimation (Mshowanim);
            Mlastbuttonshowingpos = CurPos;  Mbutton.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (View v)
           {if (Mdeleteitemlistener!= null)       Mdeleteitemlistener.onbuttonclick (V, mlastbuttonshowingpos);

                Mbutton.setvisibility (View.gone);
              Mlastbuttonshowingpos =-1;

            }
            });
          Mcancelmotionevent = true;

      }}}break;
          Case MOTIONEVENT.ACTION_UP: {if (mtracker!= null) {mtracker.clear ();
          Mtracker.recycle ();
        Mtracker = null;

        } mcancelmotionevent = false;
        if (Mlastbuttonshowingpos!=-1) {event.setaction (motionevent.action_cancel);

      }}break;
      Case Motionevent.action_cancel: {Hideshowingbuttonwithanim ();
    }break;
  Return Super.ontouchevent (event);

 }

Explain the code of the Android touch event before explaining it first, mainly Motionevent.action_down this event is the most important, the distribution of the event has one back two parts, "Come" Refers to the Action_down event that ViewGroup acquires to the system, first calls the ViewGroup Onintercepttouchevent () method, which indicates whether the event ViewGroup wants to intercept, and if true, The Action_down event is distributed to the ViewGroup ontouchevent () method for processing, indicating that the event was intercepted by the parent view, and the child view will no longer get the event. If the Onintercepttouchevent () method of ViewGroup returns false, it means that ViewGroup does not intercept the event, and the next occurrence of the event has a child view, viewgroup the Action_ The down event is passed to the child view for processing. This process is the distribution process of the event, followed by "Back", "back" the process is the consumption of the event, the Ontouchevent () method of the child view returns True, indicating that the Action_down event was consumed by the child view, Then ViewGroup will not receive the event in the Ontouchevent () method because the event is consumed. If the Ontouchevent () method of the child view returns false that the child view does not consume the Action_down event (of course, the child view can still handle the event, but returning false will still throw the event back to ViewGroup. This can do a lot of things), and then the event is returned to the parent view. The final Motionevent.action_down event is consumed at which level of view, then subsequent touch events, such as Action_up, Action_move, Action_cancel, will be passed directly to the consumption ACTION View of the _down event, other layers of view will no longer be subject to subsequent events until the next Action_down event.  

The above code, temporarily concerned about the switch code block, to detect the Motionevent.action_down event, record the current touch event location, and we first get mtracker, this is a Velocitytracker object, The rate that Android provides to calculate the current sliding event; The Motionevent.action_move event is detected, we have two cases to be processed, one situation is that the user pops the button at a certain distance. This distance is the current sliding position and the Action_down record of the event position distance, the second situation is the user sliding speed over a threshold, pop-up button, the speed of the calculation is to use the previous mentioned Mtracker, the usage is very simple; Action_ detected The up event indicates that the current interaction is complete, and we can do some cleanup work; As for the Action_cancel incident, this place buys a story for the moment, this uses a cynical trick to bully the system ~

In the Action_move event above, if the event is handled, the button pops up, and the next time we detect the Action_down event, if the location of the event is not in the button's area, the user is not clicking the button that pops up, Then we need to gone the button and hide it here. So here we need to use the Onintercepttouchevent () method with the ViewGroup mentioned above to intercept the Action_down event before it is passed to the child view, and, of course, determine if this event is clicked button:
Private Boolean Isclickbutton (Motionevent ev) {

 Mbutton.getlocationonscreen (mshowingbuttonlocation);
    int left = mshowingbuttonlocation[0];
    int right = Mshowingbuttonlocation[0] + mbutton.getwidth ();
    int top = mshowingbuttonlocation[1];

    int bottom = mshowingbuttonlocation[1] + mbutton.getheight ();
        Return (EV.GETRAWX () >= left && ev.getrawx () <= right && Ev.getrawy () >= Top
  && Ev.getrawy () <= bottom); Next, override the Onintercepttouchevent () method: @Override public boolean onintercepttouchevent (motionevent ev) {if (menable Sliding && mlastbuttonshowingpos!=-1 && ev.getaction () = Motionevent.action_down &&!is
      Clickbutton (EV)) {ev.setaction (motionevent.action_cancel);

      Mcancelmotionevent = true;
    return true;
  return super.onintercepttouchevent (EV);  
}; 

To determine whether to intercept the Action_down event, first determine whether there is currently a button has a pop-up, because each pop-up button, will note the current pop-up item position Mlastbuttonshowingpos; Then is the current is not action_ Down event, and whether to click on the button that pops up. If all conditions are met, we intercept the Action_down event and return True in the Onintercepttouchevent () method. This action_down event is passed to the Ontouchevent () method of the Slidingdeletelistview, which explains the preceding Action_cancel event, in Ontouchevent () The method inside is judged to be the Action_down, and the Onintercepttouchevent () in front of the mark Mcancelmotionevent, which indicates that the Action_down event was intercepted, need special handling of this action _down event, and then look at how the Ontouchevent () method handles this Action_down event:

else if (mcancelmotionevent && event.getaction () = = Motionevent.action_down) {
      event.setaction ( Motionevent.action_cancel);
    

Is drops, cynical, the current Action_down event into Action_cancel event, in the Action_cancel event processing is gone off the current pop-up button, so that the two cases of Action_ Down to distinguish it from the extra processing.

At the same time we can see in the Action_up event, there is a judgment, when the current mlastbuttonshowingpos is not-1, it means that this is the user sliding pop-up button operation, this touch event we have to deal with, So we can't throw this action_up event back to ListView's own Default super.ontouchevent () logic, because the front action_down and the action_move we're all going to the default process, Now listview The original logic is waiting for the Action_up event to be distributed, so that is ListView itself Onitemclick or Onitemlongclick event triggered, think about, if we pop up the hidden button, ListView still deal with Onitemclick or onitemlongclick this is certainly not appropriate, so here we still have a little bit of deception system, the original action_up replaced Action_cancel, This way, when the button's popup is processed, the ListView original Onitemclick or Onitemlongclick event is not processed:

 if (Mlastbuttonshowingpos!=-1) { 
        event.setaction (motionevent.action_cancel); 
      }  

Finally, if we rewrite the Ontouchevent () method in this way, will it affect the Onitemclick () and Onitemlongclick () method of this custom ListView, the answer is this scenario is not because Ontouchevent ( Method for events not intercepted, all are returned to super.ontouchevent (EV), so that both handle the detection of sliding events, there is no interference to the system for this event processing process, and intercepted events, has given the full lifecycle of the event (I have forged a action_ Cancel event to end a touch interaction), let me just say the life cycle, with the Action_down event beginning, action_up or Action_cancel event ending, with a series of action_move events in between. My initial scenario was to use Listview.setontouchlistener () and implement the Touchlistener Ontouch () method, which is slightly more complex because the processing logic of this control is in Action_ Move inside the pop-up button, all the subsequent Action_move events are invalidated, because if not invalid then the subsequent Action_move event ListView will still be affected, the user can drag up and down ListView, Know that listview item is to reuse a few common view of the students should think of what will be the next bug, that is, the original did not eject the button item appears on the screen after unexpectedly will also pop-up button, Because this item reuses the view of the item that has disappeared. Then I use the Ontouchlistener.ontouch () method, when the button pops up directly return to true, that this event was Ontouchlistener handled, but here is a problem, because the front of the Action_ The down event is always returning false, which indicates that the most initial event of the touch's interaction is handled by the ListView default Ontouchevent () logic (and must return FALSE, otherwise all events are eaten by this and Ontouchlistener), Because we do not know the default ontouchevent () inside how to deal with this action_down, although in general the ListView consumes this action_down, Start a Onitemclick or Onitemlongclick event, because the item's click event is made up of ListView OntouchevENT (), Action_down is consumed by ListView's own ontouchevent (), but subsequent action_move and even action_up events are consumed by Ontouchlistener. Can not be passed to the default ontouchevent () inside processing, a original full touch life cycle has been cut into two parts to two places to deal with, which will certainly lead to a big push problem, The most obvious thing is that ListView itself onitemclicklistener the listener to handle the event conflicts with the code that handles the sliding event detection, such as when the button pops up after sliding, and the item that currently handles the slide event is highlighted in the selected state ( Android inside the pressed, even if the finger has left the screen. The last scheme is to maintain the logic of event processing within a method, which can do the normal distribution of system events and handle sliding events.

The last code was submitted to my GitHub: Https://github.com/YoungLeeForeverBoy/SlidingDeleteListView.

The following is a display of this control:

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.