OK, or the usual, give first, here is to draw a simple framework, you crossing can add their own things.
Let me explain how to use our viewdraghelper to achieve this effect.
Give us the layout first.
<?xml version= "1.0" encoding= "UTF-8"? ><com.jeason.qqmenudemo.widget.sidesliplayout xmlns:android= "http:/ /schemas.android.com/apk/res/android "android:id=" @+id/main_frame "android:layout_width=" Match_parent "Android:la yout_height= "Match_parent" android:background= "@drawable/bg" > <framelayout android:id= "@+id/left_panel "Android:layout_width=" match_parent "android:layout_height=" match_parent "> <textview android:ems= "1" android:layout_height= "match_parent" android:layout_width= "Wrap_content" Android:textcolor= "#FFFFFF" android:layout_margintop= "56DP" android:textsize= "24DP" a ndroid:layout_gravity= "center" android:text= "@string/menu_block"/> </FrameLayout> &l T;com.jeason.qqmenudemo.widget.myframelayout android:id= "@+id/main_panel" android:background= "@drawable/bg_3 "Android:layout_width=" MaTch_parent "android:layout_height=" match_parent "> <linearlayout android:layout_width=" MATC H_parent "android:layout_height=" match_parent "android:orientation=" vertical "> <in Clude layout= "@layout/custom_actionbar"/> <framelayout android:id= "@+id/content" Android:layout_width= "Match_parent" android:layout_height= "Match_parent" > <com. Jeason.qqmenudemo.widget.MyTextView android:id= "@+id/content_block" Android:layout_ Width= "260DP" android:layout_height= "wrap_content" android:layout_gravity= "center" android:text= "@string/content_bolock" android:padding= "8DP" Androi D:textsize= "18DP"/> </FrameLayout> </LinearLayout> </com.jeason.qqmenudEmo.widget.myframelayout></com.jeason.qqmenudemo.widget.sidesliplayout>
Our layout file is simple enough to customize a side-by-side layout sidesliplayout, then we divide the contents into 2 Leftpanel (menu area) and Mainpanel (main content area).
We currently think that all the children's shoes for the viewdraghelper have a certain understanding, do not know can look at my last blog post.
Powerful viewdraghelper and the magical viewdraghelper of a
Here, we first give the code, and then give you a slow explanation.
Package Com.jeason.qqmenudemo.widget;import Com.jeason.qqmenudemo.r;import Com.jeason.qqmenudemo.view.ViewHelper; Import Android.annotation.suppresslint;import Android.content.context;import Android.support.v4.view.ViewCompat; Import Android.support.v4.widget.viewdraghelper;import Android.util.attributeset;import Android.util.Log;import Android.view.motionevent;import Android.view.view;import Android.widget.framelayout;public class SideslipLayout Extends framelayout{private static final String TAG = "Sidesliplayout"; @SuppressWarnings ("unused") private Context mcontext; Private Viewdraghelper Mdraghelper; Private Draglistener Mdraglistener; private int range; private int width; private int height; private int mainleft; Private Framelayout Mleftpanel; Private Myframelayout Mmainpanel; Private Status mdefaultstatus = Status.close; Private Status status = Mdefaultstatus; public enum Status {Drag, Open, Close} public SIdesliplayout (context context, AttributeSet Attrs) {Super (context, attrs); TODO auto-generated constructor stub mcontext = context; Mdraghelper = Viewdraghelper.create (this, mdraghelpercallback); } @Override protected void Onfinishinflate () {Mmainpanel = (myframelayout) Findviewbyid (R.id.main_panel); Mmainpanel.setdraglayout (this); Mleftpanel = (framelayout) Findviewbyid (R.id.left_panel); } @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (width Measurespec, Heightmeasurespec); width = Mleftpanel.getmeasuredwidth (); which meaning full_window height = mleftpanel.getmeasuredheight (); Range = (int) (width * 0.6f); } @Override public boolean onintercepttouchevent (Motionevent ev) {return mdraghelper.shouldintercept TouchEvent (EV); } @SuppressLint ("Clickableviewaccessibility")@Override public boolean ontouchevent (Motionevent e) {try {mdraghelper.processtouchevent (e); } catch (Exception ex) {ex.printstacktrace (); } return true; Public status GetStatus () {if (Mainleft = = 0) {status = Status.close; } else if (Mainleft = = range) {status = Status.open; } else {status = Status.drag; } return status; } public void Open () {open (true); public void Open (Boolean animate) {if (animate) {if (Mdraghelper.smoothslideviewto (Mmainpanel, RA Nge, 0)) {viewcompat.postinvalidateonanimation (this); }} else {mmainpanel.layout (range, 0, range * 2, height); Dispatchdragevent (range); }} public void Close () {close (true); public void Close (Boolean animate) {if (animate) {if (mdraghelper.smoothsLideviewto (mmainpanel, 0, 0)) {viewcompat.postinvalidateonanimation (this); }} else {mmainpanel.layout (0, 0, width, height); Dispatchdragevent (0); }} private void dispatchdragevent (int mainleft) {if (Mdraglistener = = null) {return; } Float percent = mainleft/(float) range; Animateview (percent); Mdraglistener.ondrag (percent); Status Laststatus = status; if (laststatus! = GetStatus () && status = = Status.close) {mdraglistener.onclose (); } else if (laststatus! = GetStatus () && status = = Status.open) {mdraglistener.onopen (); }} private void Animateview (float percent) {float F1 = 1-percent * 0.3F; Viewhelper.setscalex (Mmainpanel, F1); Viewhelper.setscaley (Mmainpanel, F1); Viewhelper.settranslationx (Mleftpanel,-mleftpanel.getwidth ()/2.3f + mleftpanel.getwidth()/2.3f * percent); Viewhelper.setscalex (Mleftpanel, 0.5f + 0.5f * percent); Viewhelper.setscaley (Mleftpanel, 0.5f + 0.5f * percent); Viewhelper.setalpha (Mleftpanel, percent); } @Override public void Computescroll () {if (mdraghelper.continuesettling (True)) {Viewcompat . postinvalidateonanimation (this); }} public interface Draglistener {public void OnOpen (); public void OnClose (); public void Ondrag (float percent); } public void Setdraglistener (Draglistener draglistener) {mdraglistener = Draglistener; } private Viewdraghelper.callback Mdraghelpercallback = new Viewdraghelper.callback () {@Override public int Clampviewpositionhorizontal (View-Child, int-left, int dx) {if (mainleft + DX < 0) { return 0; } else if (Mainleft + DX > Range) {return range; } else {returnLeft }} @Override public boolean trycaptureview (View child, int pointerid) {return true; } @Override public int getviewhorizontaldragrange (View child) {return range; } @Override public void onviewreleased (View releasedchild, float xvel, float yvel) {Super.onview Released (Releasedchild, Xvel, Yvel); if (Xvel > 0) {open (); } else if (Xvel < 0) {close (); } else if (Releasedchild = = Mmainpanel && mainleft > Range * 0.3) {open (); } else if (Releasedchild = = Mleftpanel && mainleft > Range * 0.7) {open (); } else {close (); }} @Override public void onviewpositionchanged (View changedview, int left, int top, I NT DX, int dy) {if (Changedview = = Mmainpanel) { Mainleft = left; } else {mainleft = Mainleft + left; } if (Mainleft < 0) {mainleft = 0; } else if (Mainleft > Range) {mainleft = range; } if (Changedview = = Mleftpanel) {mleftpanel.layout (0, 0, width, height); Mmainpanel.layout (mainleft, 0, Mainleft + width, height); } dispatchdragevent (Mainleft); } };}
with my previous article, we know that any special effects view is ultimately achieved through onintercepttouchevent and ontouchevent, So first we need to deliver our motionevent to our viewdraghelper.
@Override Public Boolean onintercepttouchevent (motionevent ev) { return Mdraghelper.shouldintercepttouchevent (EV); } @SuppressLint ("clickableviewaccessibility") @Override public boolean ontouchevent (Motionevent e) { try { mdraghelper.processtouchevent (e); } catch (Exception ex) { ex.printstacktrace (); } return true; }
here, we generally best use ontouchevent in return true, of course, if our childview may need to consume motionevent, then we need to action in Childview ontouchevent Return true in _down, (if Childview return false at Action_down, then motionevent goes to Parentview always return true; then Childview will not be able to get follow-up motionevent);
Of course, consider another situation, if we continue to let our Parentview return false, then we can assume that if this motionevent is not consumed (all Childview return False, Then our parentview will eventually get Action_down, but since we return to False;name in Action_down, we will not continue to get action_down after we get action_. Up (assuming that our parentview is the topmost viewGroup), then Dispatchtouchevent returns false and the event is canceled, then you will find that our Childview cannot be moved again. This can be said to be a logical question for viewdraghelper to consider.
If we want our childview may also need to action_move, then we need to strictly control the onintercepttouchevent, Because if we give our motionevent directly to our viewdraghelper, in this case, because our childview can be moved, Onintercepttouchevent returns true directly, Childview will have no chance. So what can we do about it? Like
@Override Public Boolean onintercepttouchevent (motionevent ev) { Boolean result; if (ev.getaction () = = Motionevent.action_move) { if (mchildview.requesttouchevent (EV)) { result = false; } else{ result = mdraghelper.shouldintercepttouchevent (EV); } } else{ result = mdraghelper.shouldintercepttouchevent (EV); } return result; }
Here are just a few instructions to avoid complicated situations where we find that our viewdraghelper are not so sensitive, or not so easy to control. Anyway here is to remind you must fully understand the onintercepttouchevent and Ontouchevent and dispatchtouchevent between the logical relationship.
Okay, we're done here. We gave our mobile processing logic to viewdraghelper. According to my last analysis of our mobile implementation to be handed over to our callback
Private Viewdraghelper.callback Mdraghelpercallback = new Viewdraghelper.callback () {@Override public int Clampviewpositionhorizontal (View child, int left, int dx) {if (mainleft + DX < 0) {//Calculate Childview return 0; } else if (Mainleft + DX > Range) {return range; } else {return left; }} @Override public boolean trycaptureview (View child, int pointerid) {//here means our left and main can be moved return true; } @Override public int getviewhorizontaldragrange (View child) {//Framed horizontal move range return range; } @Override public void onviewreleased (View releasedchild, float xvel, float yvel) {//Move end to determine auto-toggle status after closing Super.onviewreleased (Releasedchild, Xvel, Yvel); if (Xvel > 0) {open (); } else if (Xvel < 0) {close (); } else if (ReleaSedchild = = Mmainpanel && mainleft > Range * 0.3) {open (); } else if (Releasedchild = = Mleftpanel && mainleft > Range * 0.7) {open (); } else {close (); }} @Override public void onviewpositionchanged (View changedview, int left, int top, I NT DX, int dy) {if (Changedview = = Mmainpanel) {mainleft = left; } else {mainleft = Mainleft + left; } if (Mainleft < 0) {mainleft = 0; } else if (Mainleft > Range) {mainleft = range; if (Changedview = = Mleftpanel) {//move left, leave still to change main position mleftpanel.layout (0, 0, width, h eight); Mmainpanel.layout (mainleft, 0, Mainleft + width, height); } dispatchdragevent (Mainleft); Turn on the animation effect when moving the zoom, etc.}};
Analysis finished callback, as if there is nothing to say, source download
http://download.csdn.net/download/jaysong2012/8961751
The following continues to share a more complex viewdraghelper of the magical, interested people can try. Focus on The onintercepttouchevent in the processing, the opportunity to share the source code to everyone.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Viewdraghelper's Magical two--qq side-slip Menu implementation