Android实现网易新闻客户端侧滑菜单(2)
程序员文章站
2024-03-02 23:34:46
前面已经讲过通过三方开源库slidemenu来实现这种效果,请参考android实现网易新闻客户端侧滑菜单(一)
今天通过自定义view来实现这种功能。
代码如...
前面已经讲过通过三方开源库slidemenu来实现这种效果,请参考android实现网易新闻客户端侧滑菜单(一)
今天通过自定义view来实现这种功能。
代码如下:
slidemenu.java
package com.jackie.slidemenu.view; import android.content.context; import android.graphics.canvas; import android.util.attributeset; import android.view.motionevent; import android.view.view; import android.view.viewconfiguration; import android.view.viewgroup; import android.widget.scroller; public class slidemenu extends viewgroup { private int mmostrecentx; // 最后一次x轴的偏移量 private final int menu_screen = 0; // 菜单界面 private final int main_screen = 1; // 主界面 private int mcurrentscreen = main_screen; // 当前屏幕显示的是主界面 private scroller mscroller; private int touchslop; public slidemenu(context context, attributeset attrs) { super(context, attrs); mscroller = new scroller(context); touchslop = viewconfiguration.get(context).getscaledtouchslop(); } /** * 测量出所有子布局的宽和高 */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); measureview(widthmeasurespec, heightmeasurespec); } /** * 测量所有子布局的宽和高 * @param widthmeasurespec 父布局也就是viewgroup的宽度测量规格 * @param heightmeasurespec 父布局也就是viewgroup的高度测量规格 */ private void measureview(int widthmeasurespec, int heightmeasurespec) { // 测量菜单的宽和高 view menuview = getchildat(0); menuview.measure(menuview.getlayoutparams().width, heightmeasurespec); // 测量主界面的宽和高 view mainview = getchildat(1); mainview.measure(widthmeasurespec, heightmeasurespec); // 主界面的宽和高和父控件viewgroup的宽高一样 } @override protected void onlayout(boolean changed, int l, int t, int r, int b) { // 布置菜单的位置 view menuview = getchildat(0); menuview.layout(-menuview.getmeasuredwidth(), 0, 0, b); // 布置主界面的位置 view mainview = getchildat(1); mainview.layout(0, 0, r, b); } @override public boolean ontouchevent(motionevent event) { switch (event.getaction()) { case motionevent.action_down: mmostrecentx = (int) event.getx(); break; case motionevent.action_move: // 最新的x轴偏移量 int movex = (int) event.getx(); // 增量值 int deltax = mmostrecentx - movex; // 把最新的x轴偏移量赋值给成员变量 mmostrecentx = movex; // 得到x轴移动后的偏移量 int newscrollx = getscrollx() + deltax; if(newscrollx < -getchildat(0).getwidth()) { // 当前屏幕x轴的偏移量超过了菜单的左边界 // 回到菜单的左边界位置 scrollto(-getchildat(0).getwidth(), 0); } else if(newscrollx > 0) { // 超过了主界面的右边界 // 回到主界面的右边界 scrollto(0, 0); } else { scrollby(deltax, 0); } break; case motionevent.action_up: int scrollx = getscrollx(); // x轴最新的偏移量 int menuxcenter = -getchildat(0).getwidth() / 2; // 菜单x轴的中心点 if(scrollx > menuxcenter) { // 切换到主界面 mcurrentscreen = main_screen; } else { // 切换到菜单界面 mcurrentscreen = menu_screen; } switchscreen(); break; default: break; } return true; } /** * 根据mcurrentscreen切换屏幕 */ private void switchscreen() { int scrollx = getscrollx(); // 当前x轴的偏移量 int dx = 0; if(mcurrentscreen == main_screen) { // 切换到主界面 // scrollto(0, 0); dx = 0 - scrollx; } else if(mcurrentscreen == menu_screen) { // 切换到菜单界面 // scrollto(-getchildat(0).getwidth(), 0); dx = -getchildat(0).getwidth() - scrollx; } mscroller.startscroll(scrollx, 0, dx, 0, math.abs(dx) * 5); invalidate(); // invalidate -> drawchild -> child.draw -> computescroll } /** * invalidate出发此方法, 更新屏幕的x轴的偏移量 */ @override public void computescroll() { if(mscroller.computescrolloffset()) { // 判断是否正在模拟数据中, true 正在进行 false 数据模拟完毕 scrollto(mscroller.getcurrx(), 0); invalidate(); // 引起computescroll的调用 } } /** * 是否显示菜单 * @return */ public boolean isshowmenu() { return mcurrentscreen == menu_screen; } /** * 隐藏菜单 */ public void hidemenu() { mcurrentscreen = main_screen; switchscreen(); } /** * 显示菜单 */ public void showmenu() { mcurrentscreen = menu_screen; switchscreen(); } /** * 拦截事件的方法 */ @override public boolean onintercepttouchevent(motionevent ev) { switch (ev.getaction()) { case motionevent.action_down: mmostrecentx = (int) ev.getx(); break; case motionevent.action_move: int diffx = (int) (ev.getx() - mmostrecentx); if(math.abs(diffx) > touchslop) { return true; } break; default: break; } return super.onintercepttouchevent(ev); } }
mainactivity.java
package com.jackie.slidemenu; import com.jackie.slidemenu.view.slidemenu; import android.os.bundle; import android.app.activity; import android.view.menu; import android.view.view; import android.view.view.onclicklistener; import android.view.window; import android.widget.textview; import android.widget.toast; public class mainactivity extends activity implements onclicklistener { private slidemenu mslidemenu; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // 去除标题, 需要在setcontentview之前调用 requestwindowfeature(window.feature_no_title); setcontentview(r.layout.activity_main); mslidemenu = (slidemenu) findviewbyid(r.id.slidemenu); findviewbyid(r.id.iv_slidemenu_main_back).setonclicklistener(this); } @override public boolean oncreateoptionsmenu(menu menu) { // inflate the menu; this adds items to the action bar if it is present. getmenuinflater().inflate(r.menu.main, menu); return true; } @override public void onclick(view v) { if(mslidemenu.isshowmenu()) { mslidemenu.hidemenu(); } else { mslidemenu.showmenu(); } } public void click(view v) { textview tv = (textview) v; toast.maketext(this, tv.gettext(), 0).show(); } }
系列文章:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: .NET中STAThread的使用详解
下一篇: .NET中RDLC循环处理数据的应用分析