There are many ways to achieve the side effect of qq5.0.Today we use viewdraghelper to achieve it.

First on the effect map:

① The custom control slidingmenu inherits the framelayout, and the layout on the framelayout is layered on top of each otherYou can easily get to any layer through getchildat (),This in turn controls changes in this layout.

public class slidingmenu extends framelayout {
 private viewdraghelper mviewdraghelper;
 private int mheight;//the height of the current control
 private int mwidhth;//the width of the current control
 private int mrange;//distance the menu moves
 private viewgroup mmenu;//menu content
 private viewgroup mcontent;//main page content
 private boolean isopen=false;//determine whether to open the menu
 public slidingmenu (context context) {
 this (context, null);
 public slidingmenu (context context, attributeset attrs) {
 this (context, attrs, 0);
 public slidingmenu (context context, attributeset attrs, int defstyleattr) {
 super (context, attrs, defstyleattr);
 //initialize viewdraghelper
 mviewdraghelper=viewdraghelper.create (this, callback);

② Next we use our custom slidingmenu in the layout file. According to the layout,We implement slidingmenu step by step.

<?xml version="1.0" encoding="utf-8"?>
 android:id="@ + id/main_slidingmenu"
 android:background="@ mipmap/bg"
 <include layout="@ layout/left_menu" />
 android:id="@ + id/main_content"
 android:background="@ mipmap/qq"
  android:text="Toggle menu" />

③ If i want to achieve side slip,The custom control must contain two layouts,Judging in the onfinishinflate method in our slidingmenu,And get the menu and main page.Get the width and height of the menu slide out at onsizechanged.

protected void onfinishinflate () {
 super.onfinishinflate ();
 if (getchildcount ()&2;2) {
  throw new illegalstateexception ("You must include two views in the slidingmenu");
 if (! (getchildat (0) instanceof viewgroup &&getchildat (1) instanceof viewgroup)) {
  throw new illegalstateexception ("Subview must be a subclass of viewgroup");
 mmenu=(viewgroup) getchildat (0);
 mcontent=(viewgroup) getchildat (1);
 protected void onsizechanged (int w, int h, int oldw, int oldh) {
 super.onsizechanged (w, h, oldw, oldh);
 mheight=getmeasuredheight ();
 mwidhth=getmeasuredwidth ();
 mrange=(int) (mwidhth * 0.8);

④ To use viewdraghelper, you need to hand over the time of the current control to viewdraghelper.

public boolean onintercepthoverevent (motionevent event) {
 //Pass the touch event to viewdraghelper
 return mviewdraghelper.shouldintercepttouchevent (event);
public boolean ontouchevent (motionevent event) {
 try {
 mviewdraghelper.processtouchevent (event);//let viewdragehelper handle touch events
 } catch (exception e) {
 e.printstacktrace ();
 return true;

⑤ The key code of viewdraghelper

private callback callback=new callback () {
 public boolean trycaptureview (view child, int pointerid) {
 return true;//child:the currently dragged view. Returns true if the current view can be dragged
 public int getviewhorizontaldragrange (view child) {
 return mrange;//return the distance to drag,There are no restrictions on dragging,Determines the speed of the animation
 public int clampviewpositionhorizontal (view child, int left, int dx) {//According to the suggested value,Revised distance moved horizontally
 if (child == mcontent) {//① sliding the main page content,When the screen reserve width is exceeded,No more sliding.
② Swipe left cannot be negative
  left=fixcontentslidrange (left);
 return left;
 public void onviewpositionchanged (view changedview, int left, int top, int dx, int dy) {//Called when the position of the view changes,You can add some view effects in this method
 super.onviewpositionchanged (changedview, left, top, dx, dy);
 //When we slide the menu content,Keep the menu contents intact,Conversion to main page content movement
 int movecontentleft=left;//the distance to the left of the main page content
 if (changedview == mmenu) {
  movecontentleft=mcontent.getleft () + left;
  mmenu.layout (0, 0, mmenu.getheight (), mmenu.getheight ());//force the menu to not move
 movecontentleft=fixcontentslidrange (movecontentleft);
 mcontent.layout (movecontentleft, 0, movecontentleft + mcontent.getwidth (), mcontent.getheight ());
 animshow (movecontentleft);//When the menu opens,Some animation
 invalidate ();//redraw the interface,Compatible with earlier versions
 public void onviewreleased (view releasedchild, float xvel, float yvel) {//fired when the view releases,Handle automatic smooth animation
 super.onviewreleased (releasedchild, xvel, yvel);
 if (xvel>0) {//horizontal speed +
  open ();
 } else if (xvel == 0&&mcontent.getleft ()>mrange/2.0f) {//lift your finger when the menu slides out more than halfway
  open ();
 } else {
  close ();
 * Revised the sliding distance of the main page
 * /
 private int fixcontentslidrange (int left) {
 if (left > mrange) {
  return mrange;
 } else if (left<0) {
  return 0;
 return left;
/** Accompanying animation * /
private void animshow (int movecontentleft) {
 float percent=movecontentleft * 1.0f/mrange;//0 ~ 1
 * Analysis:
 * Menu area:displacement animation,Zoom animation,Gradient animation
 * Content area:zoom animation
 * Background area:brightness change
 * /
 viewhelper.settranslationx (mmenu, evaluate (percent, -mrange/1.2f, 0));//displacement animation
 viewhelper.setscalex (mmenu, evaluate (percent, 0.6f, 1.0f));//scale animation
 viewhelper.setscaley (mmenu, evaluate (percent, 0.6f, 1.0f));
 viewhelper.setalpha (mmenu, evaluate (percent, 0.1f, 1.0f));//gradient animation
 viewhelper.setpivotx (mcontent, 0);//zoom center
 viewhelper.setpivoty (mcontent, mheight/2);
 viewhelper.setscalex (mcontent, evaluate (percent, 1.0f, 0.9f));//zoom animation
 viewhelper.setscaley (mcontent, evaluate (percent, 1.0f, 0.9f));
 getbackground (). setcolorfilter ((integer) (colorevaluate (percent, color.black, color.transparent)), porterduff.mode.src_over);//brightness change
/** Estimator, based on the start and end numbers,Get a value as the percentage changes,See floatvaluator for details * /
 private float evaluate (float fraction, number startvalue, number endvalue) {
 float startfloat=startvalue.floatvalue ();
 return startfloat + fraction * (endvalue.floatvalue ()-startfloat);
 /** color value,Based on the initial and end colors,Take out different colors as the percentage changes,See argbevaluator for details * /
 private object colorevaluate (float fraction, object startvalue, object endvalue) {
 int startint=(integer) startvalue;
 int starta=(startint>>24)&0xff;
 int startr=(startint>>16)&0xff;
 int startg=(startint>>8)&0xff;
 int startb=startint&0xff;
 int endint=(integer) endvalue;
 int enda=(endint>>24)&0xff;
 int endr=(endint>>16)&0xff;
 int endg=(endint>>8)&0xff;
 int endb=endint&0xff;
 return (int) ((starta + (int) (fraction * (enda-starta)))<<24) |
  (int) ((startr + (int) (fraction * (endr-startr)))<<16) |
  (int) ((startg + (int) (fraction * (endg-startg)))<<8) |
  (int) ((startb + (int) (fraction * (endb-startb))));

⑥ We provide a method to open/close the menu,Called by the user.

/** Menu switch * /
 public void toggle () {
 if (isopen) {
  close ();
 } else {
  open ();
 * Open menu
 * /
 private void open () {
 if (mviewdraghelper.smoothslideviewto (mcontent, mrange, 0)) {//determine whether the main page slides to the specified position
  viewcompat.postinvalidateonanimation (this);//will trigger computescroll
 * Close menu
 * /
 private void close () {
 if (mviewdraghelper.smoothslideviewto (mcontent, 0, 0)) {//determine whether the main page slides to the specified position
  viewcompat.postinvalidateonanimation (this);//will trigger computescroll
 public void computescroll () {
 super.computescroll ();
 if (mviewdraghelper.continuesettling (true)) {//continuous animation,If it returns, it means the animation has not finished
  viewcompat.postinvalidateonanimation (this);

=================== At this point our slidingmenu has been defined ========================

We use in mainactivity

public class mainactivity extends activity {
 private slidingmenu mslidingmenu;
 protected void oncreate (bundle savedinstancestate) {
 super.oncreate (savedinstancestate);
 requestwindowfeature (window.feature_no_title);
 setcontentview (r.layout.activity_main);
 initview ();
 private void initview () {
 mslidingmenu=(slidingmenu) findviewbyid (r.id.main_slidingmenu);
 public void click (view view) {
 mslidingmenu.toggle ();
  • Previous Questions about the many-to-many relationship table cannot be updated and inserted
  • Next Method of Yii model operation criteria search database