代码分析Android实现侧滑菜单
程序员文章站
2023-12-12 17:56:28
android 侧滑菜单的实现,参考网上的代码,实现侧滑菜单。最重要的是这个动画类ugcanimations,如何使用动画类来侧滑的封装flipperlayout。
1、...
android 侧滑菜单的实现,参考网上的代码,实现侧滑菜单。最重要的是这个动画类ugcanimations,如何使用动画类来侧滑的封装flipperlayout。
1、实现效果
2、动画类ugcanimations
package com.mmsx.base; import android.content.context; import android.view.view; import android.view.viewgroup.marginlayoutparams; import android.view.animation.alphaanimation; import android.view.animation.animation; import android.view.animation.animationset; import android.view.animation.anticipateinterpolator; import android.view.animation.overshootinterpolator; import android.view.animation.rotateanimation; import android.view.animation.scaleanimation; import android.view.animation.translateanimation; import android.widget.imageview; import android.widget.relativelayout; /** * path动画类 * */ public class ugcanimations { private static int xoffset = 15; private static int yoffset = -13; public static void initoffset(context context) { xoffset = (int) (15 * context.getresources().getdisplaymetrics().density); yoffset = -(int) (13 * context.getresources().getdisplaymetrics().density); } public static animation getrotateanimation(float fromdegrees, float todegrees, long durationmillis) { rotateanimation rotate = new rotateanimation(fromdegrees, todegrees, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f); rotate.setduration(durationmillis); rotate.setfillafter(true); return rotate; } public static animation getalphaanimation(float fromalpha, float toalpha, long durationmillis) { alphaanimation alpha = new alphaanimation(fromalpha, toalpha); alpha.setduration(durationmillis); alpha.setfillafter(true); return alpha; } public static animation getscaleanimation(long durationmillis) { scaleanimation scale = new scaleanimation(1.0f, 1.5f, 1.0f, 1.5f, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f); scale.setduration(durationmillis); return scale; } public static animation gettranslateanimation(float fromxdelta, float toxdelta, float fromydelta, float toydelta, long durationmillis) { translateanimation translate = new translateanimation(fromxdelta, toxdelta, fromydelta, toydelta); translate.setduration(durationmillis); translate.setfillafter(true); return translate; } public static void startopenanimation(relativelayout relativelayout, imageview background, imageview menu, long durationmillis) { background.setvisibility(view.visible); relativelayout.setvisibility(view.visible); background.startanimation(getalphaanimation(0f, 1f, durationmillis)); menu.startanimation(getrotateanimation(0, 90, durationmillis)); for (int i = 0; i < relativelayout.getchildcount(); i++) { imageview imageview = (imageview) relativelayout.getchildat(i); imageview.setvisibility(view.visible); marginlayoutparams params = (marginlayoutparams) imageview .getlayoutparams(); animationset set = new animationset(true); set.addanimation(getrotateanimation(-270, 0, durationmillis)); set.addanimation(getalphaanimation(0.5f, 1.0f, durationmillis)); set.addanimation(gettranslateanimation( -params.leftmargin + xoffset, 0f, params.bottommargin + yoffset, 0f, durationmillis)); set.setfillafter(true); set.setduration(durationmillis); set.setstartoffset((i * 100) / (-1 + relativelayout.getchildcount())); set.setinterpolator(new overshootinterpolator(1f)); imageview.startanimation(set); } } public static void startcloseanimation(final relativelayout relativelayout, final imageview background, imageview menu, long durationmillis) { background.startanimation(getalphaanimation(1f, 0f, durationmillis)); menu.startanimation(getrotateanimation(90, 0, durationmillis)); for (int i = 0; i < relativelayout.getchildcount(); i++) { final imageview imageview = (imageview) relativelayout .getchildat(i); marginlayoutparams params = (marginlayoutparams) imageview .getlayoutparams(); animationset set = new animationset(true); set.addanimation(getrotateanimation(0, -270, durationmillis)); set.addanimation(getalphaanimation(1.0f, 0.5f, durationmillis)); set.addanimation(gettranslateanimation(0f, -params.leftmargin + xoffset, 0f, params.bottommargin + yoffset, durationmillis)); set.setfillafter(true); set.setduration(durationmillis); set.setstartoffset(((relativelayout.getchildcount() - i) * 100) / (-1 + relativelayout.getchildcount())); set.setinterpolator(new anticipateinterpolator(1f)); set.setanimationlistener(new animation.animationlistener() { public void onanimationstart(animation arg0) { } public void onanimationrepeat(animation arg0) { } public void onanimationend(animation arg0) { relativelayout.setvisibility(view.gone); background.setvisibility(view.gone); } }); imageview.startanimation(set); } } public static animation clickanimation(long durationmillis) { animationset set = new animationset(true); set.addanimation(getalphaanimation(1.0f, 0.3f, durationmillis)); set.addanimation(getscaleanimation(durationmillis)); set.setduration(durationmillis); return set; } }
3、封装使用动画类flipperlayout
package com.mmsx.base; import android.content.context; import android.util.attributeset; import android.util.typedvalue; import android.view.motionevent; import android.view.velocitytracker; import android.view.view; import android.view.viewconfiguration; import android.view.viewgroup; import android.widget.scroller; /** * 自己重写的viewgroup,用与滑动切换界面使用,代码不详解,慢点看的话应该能看懂的... */ public class flipperlayout extends viewgroup { private scroller mscroller; private velocitytracker mvelocitytracker; private int mwidth; public static final int screen_state_close = 0; public static final int screen_state_open = 1; public static final int touch_state_restart = 0; public static final int touch_state_scrolling = 1; public static final int scroll_state_no_allow = 0; public static final int scroll_state_allow = 1; private int mscreenstate = 0; private int mtouchstate = 0; private int mscrollstate = 0; private int mvelocityvalue = 0; private boolean monclick = false; private onugcdismisslistener monugcdismisslistener; private onugcshowlistener monugcshowlistener; public flipperlayout(context context) { super(context); mscroller = new scroller(context); mwidth = (int) typedvalue.applydimension(typedvalue.complex_unit_dip, 54, getresources().getdisplaymetrics()); } public flipperlayout(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); } public flipperlayout(context context, attributeset attrs) { super(context, attrs); } protected void onlayout(boolean changed, int l, int t, int r, int b) { for (int i = 0; i < getchildcount(); i++) { view child = getchildat(i); int height = child.getmeasuredheight(); int width = child.getmeasuredwidth(); child.layout(0, 0, width, height); } } protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); int width = measurespec.getsize(widthmeasurespec); int height = measurespec.getsize(heightmeasurespec); setmeasureddimension(width, height); for (int i = 0; i < getchildcount(); i++) { getchildat(i).measure(widthmeasurespec, heightmeasurespec); } } public boolean dispatchtouchevent(motionevent ev) { obtainvelocitytracker(ev); switch (ev.getaction()) { case motionevent.action_down: mtouchstate = mscroller.isfinished() ? touch_state_restart : touch_state_scrolling; if (mtouchstate == touch_state_restart) { int x = (int) ev.getx(); int screenwidth = getwidth(); if (x <= mwidth && mscreenstate == screen_state_close && mtouchstate == touch_state_restart || x >= screenwidth - mwidth && mscreenstate == screen_state_open && mtouchstate == touch_state_restart) { if (mscreenstate == screen_state_open) { monclick = true; } mscrollstate = scroll_state_allow; } else { monclick = false; mscrollstate = scroll_state_no_allow; } } else { return false; } break; case motionevent.action_move: mvelocitytracker.computecurrentvelocity(1000, viewconfiguration.getmaximumflingvelocity()); if (mscrollstate == scroll_state_allow && getwidth() - (int) ev.getx() < mwidth) { return true; } break; case motionevent.action_up: releasevelocitytracker(); if (monclick) { monclick = false; mscreenstate = screen_state_close; mscroller.startscroll(getchildat(1).getscrollx(), 0, -getchildat(1).getscrollx(), 0, 800); invalidate(); } break; } return super.dispatchtouchevent(ev); } public boolean onintercepttouchevent(motionevent ev) { obtainvelocitytracker(ev); switch (ev.getaction()) { case motionevent.action_down: mtouchstate = mscroller.isfinished() ? touch_state_restart : touch_state_scrolling; if (mtouchstate == touch_state_scrolling) { return false; } break; case motionevent.action_move: monclick = false; mvelocitytracker.computecurrentvelocity(1000, viewconfiguration.getmaximumflingvelocity()); if (mscrollstate == scroll_state_allow && math.abs(mvelocitytracker.getxvelocity()) > 200) { return true; } break; case motionevent.action_up: releasevelocitytracker(); if (mscrollstate == scroll_state_allow && mscreenstate == screen_state_open) { return true; } break; } return super.onintercepttouchevent(ev); } public boolean ontouchevent(motionevent event) { obtainvelocitytracker(event); switch (event.getaction()) { case motionevent.action_down: mtouchstate = mscroller.isfinished() ? touch_state_restart : touch_state_scrolling; if (mtouchstate == touch_state_scrolling) { return false; } break; case motionevent.action_move: mvelocitytracker.computecurrentvelocity(1000, viewconfiguration.getmaximumflingvelocity()); mvelocityvalue = (int) mvelocitytracker.getxvelocity(); getchildat(1).scrollto(-(int) event.getx(), 0); break; case motionevent.action_up: if (mscrollstate == scroll_state_allow) { if (mvelocityvalue > 2000) { mscreenstate = screen_state_open; mscroller .startscroll( getchildat(1).getscrollx(), 0, -(getwidth() - math.abs(getchildat(1) .getscrollx()) - mwidth), 0, 250); invalidate(); } else if (mvelocityvalue < -2000) { mscreenstate = screen_state_close; mscroller.startscroll(getchildat(1).getscrollx(), 0, -getchildat(1).getscrollx(), 0, 250); invalidate(); } else if (event.getx() < getwidth() / 2) { mscreenstate = screen_state_close; mscroller.startscroll(getchildat(1).getscrollx(), 0, -getchildat(1).getscrollx(), 0, 800); invalidate(); } else { mscreenstate = screen_state_open; mscroller .startscroll( getchildat(1).getscrollx(), 0, -(getwidth() - math.abs(getchildat(1) .getscrollx()) - mwidth), 0, 800); invalidate(); } } break; } return super.ontouchevent(event); } public void open() { mtouchstate = mscroller.isfinished() ? touch_state_restart : touch_state_scrolling; if (mtouchstate == touch_state_restart) { mscreenstate = screen_state_open; mscroller.startscroll(getchildat(1).getscrollx(), 0, -(getwidth() - math.abs(getchildat(1).getscrollx()) - mwidth), 0, 800); invalidate(); } } //关闭当前的侧滑菜单,用view打开点击事件的页面 public void close(view view) { mscreenstate = screen_state_close; mscroller.startscroll(getchildat(1).getscrollx(), 0, -getchildat(1) .getscrollx(), 0, 800); invalidate(); setcontentview(view); } public void computescroll() { super.computescroll(); if (mscroller.computescrolloffset()) { getchildat(1).scrollto(mscroller.getcurrx(), mscroller.getcurry()); postinvalidate(); } else { if (mscreenstate == screen_state_open) { if (monugcdismisslistener != null) { monugcdismisslistener.dismiss(); } } else if (mscreenstate == screen_state_close) { if (monugcshowlistener != null) { monugcshowlistener.show(); } } } } private void obtainvelocitytracker(motionevent event) { if (mvelocitytracker == null) { mvelocitytracker = velocitytracker.obtain(); } mvelocitytracker.addmovement(event); } private void releasevelocitytracker() { if (mvelocitytracker != null) { mvelocitytracker.recycle(); mvelocitytracker = null; } } public int getscreenstate() { return mscreenstate; } public void setcontentview(view view) { removeviewat(1); addview(view, 1, getlayoutparams()); } public interface onopenlistener { public abstract void open(); } public interface oncloselistener { public abstract void close(); } public interface onugcdismisslistener { public abstract void dismiss(); } public interface onugcshowlistener { public abstract void show(); } public void setonugcdismisslistener( onugcdismisslistener onugcdismisslistener) { monugcdismisslistener = onugcdismisslistener; } public void setonugcshowlistener(onugcshowlistener onugcshowlistener) { monugcshowlistener = onugcshowlistener; } }
4、主界面mainactivity
package com.mmsx.activity; import com.mmsx.activity.sideslipmenu.onchangeviewlistener; import com.mmsx.activity.sideslipother.ondatalistener; import com.mmsx.base.flipperlayout; import com.mmsx.base.flipperlayout.onopenlistener; import com.mmsx.base.viewutil; import android.os.bundle; import android.app.activity; import android.view.viewgroup.layoutparams; import android.widget.toast; public class mainactivity extends activity implements onopenlistener{ //侧滑主要控制类,设置跟布局 private flipperlayout mroot; //侧滑的默认界面,主界面 private sidesliphome mhome; //侧滑的菜单,进行选择的 private sideslipmenu msideslipmenu; //其他菜单列表选择的效果 private sideslipother mother; //退出时间间隔变量 private long mexittime; //时间间隔2s private static final int interval = 2000; //侧滑菜单选中的item private int mviewposition; //侧滑传递的标题 private string mstrtitle; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); //创建容器,并设置全屏大小 mroot = new flipperlayout(this); //布局的参数 layoutparams params = new layoutparams(layoutparams.fill_parent, layoutparams.fill_parent); mroot.setlayoutparams(params); //创建菜单界面和内容首页界面,并添加到容器中,用于初始显示 mhome = new sidesliphome(this, this); msideslipmenu = new sideslipmenu(this); mroot.addview(msideslipmenu.getview(), params); mroot.addview(mhome.getview(), params); //设置跟布局 setcontentview(mroot); //设置监听 setlistener(); } //设置监听 private void setlistener() { mhome.setonopenlistener(this); //监听菜单界面切换显示内容(onchangeviewlistener接口在sideslipmenu中定义) msideslipmenu.setonchangeviewlistener(new onchangeviewlistener() { public void onchangeview(int arg0) { mviewposition = arg0; mother = new sideslipother(mainactivity.this); switch (arg0) { case viewutil.home: mroot.close(mhome.getview()); break; case viewutil.message: mstrtitle = "消息"; //设置数据接口监听 mother.setdatatitle(new datatitle()); mroot.close(mother.getview()); break; case viewutil.friends: mstrtitle = "好友"; mother.setdatatitle(new datatitle()); mroot.close(mother.getview()); break; case viewutil.photo: mstrtitle = "照片"; mother.setdatatitle(new datatitle()); mroot.close(mother.getview()); break; case viewutil.viewed: mstrtitle = "转帖"; mother.setdatatitle(new datatitle()); mroot.close(mother.getview()); break; case viewutil.gifts: mstrtitle = "礼物"; mother.setdatatitle(new datatitle()); mroot.close(mother.getview()); break; case viewutil.recommend: mstrtitle = "游戏"; mother.setdatatitle(new datatitle()); mroot.close(mother.getview()); break; case viewutil.lbs: mstrtitle = "附近 "; mother.setdatatitle(new datatitle()); mroot.close(mother.getview()); break; default: break; } } }); } //传递数据到侧滑选中的页面 private class datatitle implements ondatalistener{ @override public string getdatatitle() { return mstrtitle; } } @override public void open() { if (mroot.getscreenstate() == flipperlayout.screen_state_close) { mroot.open(); } } /** * 返回键监听 */ public void onbackpressed() { /** * 如果界面的path菜单没有关闭时,先将path菜单关闭,否则则判断两次返回时间间隔,小于两秒则退出程序 */ if (mroot.getscreenstate() == flipperlayout.screen_state_open) { if (msideslipmenu.getugcisshowing()) { msideslipmenu.closeugc(); } else { exit(); } } else { switch (mviewposition) { case viewutil.home: if (mhome.getugcisshowing()) { mhome.closeugc(); } else { exit(); } break; default: exit(); break; } } } /** * 判断两次返回时间间隔,小于两秒则退出程序 */ private void exit() { if (system.currenttimemillis() - mexittime > interval) { toast.maketext(this, "再按一次返回键,可直接退出程序", toast.length_short).show(); mexittime = system.currenttimemillis(); } else { finish(); android.os.process.killprocess(android.os.process.mypid()); system.exit(0); } } }
5、sidesliphome
package com.mmsx.activity; import com.mmsx.base.flipperlayout.onopenlistener; import android.app.activity; import android.content.context; import android.view.layoutinflater; import android.view.view; import android.widget.textview; public class sidesliphome { private context mcontext; private activity mactivity; private view mhomeview; private boolean mugcisshowing = false; private onopenlistener monopenlistener; public sidesliphome(context context, activity activity) { mcontext = context; mactivity = activity; mhomeview = layoutinflater.from(context).inflate(r.layout.sideslip_home, null); initui(); } private void initui() { textview ivtitlename = (textview)mhomeview.findviewbyid(r.id.ivtitlename); ivtitlename.settext("主页动态"); } public void setonopenlistener(onopenlistener onopenlistener) { monopenlistener = onopenlistener; } public view getview() { return mhomeview; } /** * 获取path菜单显示状态 */ public boolean getugcisshowing() { return mugcisshowing; } /** * 关闭path菜单 */ public void closeugc() { mugcisshowing = false; } }
好了,以上就是本文的全部叙述,希望大家喜欢。