Android自定义实现侧滑菜单效果
程序员文章站
2022-06-23 15:07:29
本文实例为大家分享了android自定义实现侧滑菜单的具体代码,供大家参考,具体内容如下
实现原理:继承viewgroup控件要显示到界面上需要重写onmeature()...
本文实例为大家分享了android自定义实现侧滑菜单的具体代码,供大家参考,具体内容如下
实现原理:继承viewgroup控件要显示到界面上需要重写onmeature()
onlayout(),因此在实现onlayout()的时候,将菜单界面划出到屏幕左侧,动态改变菜单界面距离scrollxto()左边界的距离就能实现滑动效果。
1.继承viewgroup
2.事件分发机制
3.状态监听
在主界面中添加两个子控件
<com.oblivion.ui.slidemenu xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/sliding_menu" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 在slidingmenu中的索引0 --> <include layout="@layout/menu" /> <!-- 在slidingmenu中的索引1 --> <include layout="@layout/main" /> </com.oblivion.ui.slidemenu>
menu菜单布局
<?xml version="1.0" encoding="utf-8"?> <scrollview xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="240dp" android:layout_height="match_parent" android:background="@drawable/menu_bg"> <linearlayout android:layout_width="240dp" android:layout_height="wrap_content" android:orientation="vertical"> <textview android:id="@+id/tv_news" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/select_menu" android:clickable="true" android:drawableleft="@drawable/tab_news" android:drawablepadding="10dp" android:text="新闻" /> <textview android:id="@+id/tv_read" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableleft="@drawable/tab_read" android:drawablepadding="10dp" android:text="订阅" /> <textview android:id="@+id/tv_local" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableleft="@drawable/tab_local" android:drawablepadding="10dp" android:text="本地" /> <textview android:id="@+id/tv_ties" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableleft="@drawable/tab_ties" android:drawablepadding="10dp" android:text="跟帖" /> <textview android:id="@+id/tv_pics" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableleft="@drawable/tab_pics" android:drawablepadding="10dp" android:text="图片" /> <textview android:id="@+id/tv_ugc" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableleft="@drawable/tab_ugc" android:drawablepadding="10dp" android:text="话题" /> <textview android:id="@+id/tv_vote" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableleft="@drawable/tab_vote" android:drawablepadding="10dp" android:text="投票" /> <textview android:id="@+id/tv_focus" style="@style/menu_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableleft="@drawable/tab_focus" android:drawablepadding="10dp" android:text="焦点" /> </linearlayout> </scrollview>
显示界面布局
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/top_bar_bg" android:orientation="horizontal"> <imageview android:id="@+id/iv_showmenu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/main_back" /> <view android:layout_width="1dp" android:layout_height="match_parent" android:background="@drawable/top_bar_divider"></view> <textview android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="新闻首页" android:textcolor="#ffffff" android:textsize="30sp" /> </linearlayout> <textview android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:text="我操,这么low" android:textcolor="#000000" android:textsize="20sp" /> </linearlayout>
实现原理:继承viewgroup控件要显示到界面上需要重写onmeature() onlayout(),因此在实现onlayout()的时候,将菜单界面划出到屏幕左侧,动态改变菜单界面距离scrollxto()左边界的距离就能实现滑动效果。
实现onmeasure()和onlayout()方法,对控件进行布局
/** * 测量布局中的控件 * * @param widthmeasurespec * @param heightmeasurespec */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec);//测量自身宽高 //得到menu界面 menuview = getchildat(0); menuviewwidth = menuview.getlayoutparams().width; //得到main界面 mainview = getchildat(1); //设定menuview的宽------不用setmeasure... menuview.measure(measurespec.makemeasurespec(menuviewwidth, measurespec.exactly), heightmeasurespec); //设定mainview的宽 mainview.measure(widthmeasurespec, heightmeasurespec); } @override protected void onlayout(boolean changed, int l, int t, int r, int b) { int menuleft = -menuviewwidth;//menu设定的left int menuright = 0;//menu设定的right int menutop = 0;//menu设定的top int menubottom = b - t;//menu设定的bottom //布局menuview 控件xx2 menuview.layout(menuleft, menutop, menuright, menubottom); int mainleft = 0;//main设定的left int mainright = r - l;//main设定的right int maintop = 0;//main设定的top int mainbottom = b - t;//main设定的bottom //布局mainview ---------------控件.....你妈逼方向---------方向是left,top,right,bottom mainview.layout(mainleft, maintop, mainright, mainbottom); system.out.println(menuviewwidth--);//原来这这里减减了; }
通过ontouch()方法,以及scrollx()和getscrollx()方法获取边界值,动态改变去实现滑动。
这里需要注意的是scrollx(),getscrollx()得到的值是相对于布局起始点的,所以需要重新封装;
平滑动画,需要在构造函数中创建一个scroll 类,然后通过complentscroll..方法,判断设定的平滑动画是否结束。
最后通过,动画结束后的边界值,判断是否打开,关闭状态。
/** * 由于系统scrollto是取反操作,所以需要封装一下 * * @param distance */ private void scrollto(int distance) { super.scrollto(-distance, 0); } public int getmyscrollx() { return -getscrollx(); } /** * 控件触莫状态 * * @param event * @return */ @override public boolean ontouchevent(motionevent event) { switch (event.getaction()) { case motionevent.action_down: //记录按下点 down_dot = (int) event.getx(); system.out.println(down_dot); break; case motionevent.action_move: int move_dot = (int) event.getx(); //动态的移动点和按下点的间距绝对值 move2down_distance = move_dot - down_dot; //移动间距与上次抬起的点 int lastup_dot = move2down_distance + up_dot; // 控制边界 if (lastup_dot >= menuviewwidth) { lastup_dot = menuviewwidth; } else if (lastup_dot <= 0) { lastup_dot = 0; } //设定移动后的距离 scrollto(lastup_dot); break; case motionevent.action_up: //当前抬起手指点 up_dot = (int) event.getx(); //设定最终的状态 setfinalscroll(); break; } return true;//将事件消费掉 } /** * 当手指抬起后,记录最终的状态; */ private void setfinalscroll() { //得到当前距离左边界的距离 currrentscroll = getmyscrollx(); if (currrentscroll >= menuviewwidth / 2) { //scrollto(menuviewwidth); rightanimation(); } else { leftanimation(); } } /** * 平滑向左的移动动画 */ private void leftanimation() { //scrollto(0); int dx = 0 - currrentscroll;//要移动的距离 //设定平滑动画 msscroller.startscroll(currrentscroll, 0, dx, 0, 300); invalidate(); //设定一下抬起点 up_dot = 0; //调用接口的关闭状态 mondragstatelistener.ondragclose(); } /** * 平滑向右移动的动画 */ private void rightanimation() { int dx = menuviewwidth - currrentscroll;//要移动的距离 //设定平滑动画 msscroller.startscroll(currrentscroll, 0, dx, 0, 300); invalidate(); //设定一下抬起点 up_dot = menuviewwidth; //调用接口的开启状态 mondragstatelistener.ondragopen(); } /** * 平滑移动动画是否结束 */ @override public void computescroll() { super.computescroll(); if (msscroller.computescrolloffset()) { int currx = msscroller.getcurrx();//模拟出来的数值 scrollto(currx); invalidate(); } }
创建监听,以及回调接口
/** * 拖拽的监听 */ public void setondragstatelistener(ondragstatelistener listener) { mondragstatelistener = listener; } /** * 回调修改状态 * * @param dragstate */ public void setstatechange(boolean dragstate) { if (dragstate) { currrentscroll = 0; rightanimation(); } else { currrentscroll = menuviewwidth; leftanimation(); } } /** * 创建拖拽的回调接口 */ public interface ondragstatelistener { /** * 被拖拽开 */ void ondragopen(); /** * 被关闭 */ void ondragclose(); }
主activity中实现监听效果
iv_showmenu.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { //图片点击后触发改变状态 sliding_menu.setstatechange(dragstate); } }); sliding_menu.setondragstatelistener(new slidemenu.ondragstatelistener() { @override public void ondragopen() { toastutils.settoast(getapplicationcontext(), "open"); dragstate = false; tv_news.setselected(true); tv_news.settextcolor(color.blue); } @override public void ondragclose() { toastutils.settoast(getapplicationcontext(), "close"); dragstate = true; tv_news.setselected(false); tv_news.settextcolor(color.white); } }); tv_news.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { toastutils.settoast(getapplicationcontext(), tv_news.gettext().tostring()); } }); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。