Android基于ViewDragHelper仿QQ5.0侧滑界面效果
程序员文章站
2024-03-04 16:37:41
qq5.0侧滑效果实现方案有很多方式,今天我们使用viewdraghelper来实现一下。
先上效果图:
①自定义控件slidingmenu继承framelay...
qq5.0侧滑效果实现方案有很多方式,今天我们使用viewdraghelper来实现一下。
先上效果图:
①自定义控件slidingmenu继承framelayout,放在framelayout上面的布局一层叠着者一层,通过getchildat()可以很方便的获取到任意一层,进而控制此布局的变化。
public class slidingmenu extends framelayout { private viewdraghelper mviewdraghelper; private int mheight;// 当前控件的高度 private int mwidhth;// 当前控件的宽度 private int mrange; // 菜单移动的距离 private viewgroup mmenu;// 菜单内容 private viewgroup mcontent; // 主页面内容 private boolean isopen = false;// 判断是否打开菜单 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); // 初始化viewdraghelper mviewdraghelper = viewdraghelper.create(this, callback); } }
②接下来我们在布局文件中使用我们自定的slidingmenu,根据布局,我们一步一步实现slidingmenu.
<?xml version="1.0" encoding="utf-8"?> <com.yitong.myslidingmenu2.view.slidingmenu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main_slidingmenu" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/bg" android:orientation="horizontal" tools:context="com.yitong.myslidingmenu2.mainactivity"> <include layout="@layout/left_menu"/> <linearlayout android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/qq" android:orientation="horizontal"> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onclick="click" android:text="切换菜单"/> </linearlayout> </com.yitong.myslidingmenu2.view.slidingmenu>
③如果想实现侧滑,自定义控件中必须包含两个布局,在我们的slidingmenu中的onfinishinflate方法中加以判断,并且获取菜单和主页面。在onsizechanged获取到菜单滑出的宽和高。
@override protected void onfinishinflate() { super.onfinishinflate(); if (getchildcount() < 2) { throw new illegalstateexception("使用slidingmenu中必须包含两个view"); } if (!(getchildat(0) instanceof viewgroup && getchildat(1) instanceof viewgroup)) { throw new illegalstateexception("子view必须是viewgroup的子类"); } mmenu = (viewgroup) getchildat(0); mcontent = (viewgroup) getchildat(1); } @override 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); }
④使用viewdraghelper,需要把当前控件的时间交给viewdraghelper处理。
@override public boolean onintercepthoverevent(motionevent event) { // 把触摸事件传递给viewdraghelper return mviewdraghelper.shouldintercepttouchevent(event); } @override public boolean ontouchevent(motionevent event) { try { mviewdraghelper.processtouchevent(event);// 让viewdragehelper处理触摸事件 } catch (exception e) { e.printstacktrace(); } return true; }
⑤viewdraghelper的关键代码
private callback callback = new callback() { @override public boolean trycaptureview(view child, int pointerid) { return true;// child:当前被拖拽的view.返回true表示当前view可以被拖拽 } @override public int getviewhorizontaldragrange(view child) { return mrange;// 返回拖拽的距离,并不对拖拽进行限制,决定了动画的执行速度 } @override public int clampviewpositionhorizontal(view child, int left, int dx) { // 根据建议值,修订水平方向移动的距离 if (child == mcontent) { // ①滑动主页面内容,当超过屏幕预留宽度时,不再滑动。②向左滑动不能为负 left = fixcontentslidrange(left); } return left; } @override public void onviewpositionchanged(view changedview, int left, int top, int dx, int dy) {// 当view的位置改变时调用,可以在此方法中添加一些view特效 super.onviewpositionchanged(changedview, left, top, dx, dy); // 当我们滑动菜单内容时,保持菜单内容不动,转化为主页面内容移动 int movecontentleft = left;// 主页面内容左边的距离 if (changedview == mmenu) { movecontentleft = mcontent.getleft() + left; mmenu.layout(0, 0, mmenu.getheight(), mmenu.getheight());// 强制菜单不移动 } movecontentleft = fixcontentslidrange(movecontentleft); mcontent.layout(movecontentleft, 0, movecontentleft + mcontent.getwidth(), mcontent.getheight()); animshow(movecontentleft);// 菜单打开时,一些动画 invalidate();// 重绘界面,兼容低版本 } @override public void onviewreleased(view releasedchild, float xvel, float yvel) {// 当view松手时触发,处理自动平滑动画 super.onviewreleased(releasedchild, xvel, yvel); if (xvel > 0) { // 水平速度+ open(); } else if (xvel == 0 && mcontent.getleft() > mrange / 2.0f) { // 手指在菜单滑出一半多时抬起 open(); } else { close(); } } }; /** * 修订主页面的滑动距离 */ private int fixcontentslidrange(int left) { if (left > mrange) { return mrange; } else if (left < 0) { return 0; } return left; } /** 伴随动画 */ private void animshow(int movecontentleft) { float percent = movecontentleft * 1.0f / mrange;// 0~1 /** * 分析: * 菜单区域:位移动画,缩放动画,渐变动画 * 内容区域:缩放动画 * 背景区域:亮度变化 */ viewhelper.settranslationx(mmenu, evaluate(percent, -mrange / 1.2f, 0));// 位移动画 viewhelper.setscalex(mmenu, evaluate(percent, 0.6f, 1.0f));// 缩放动画 viewhelper.setscaley(mmenu, evaluate(percent, 0.6f, 1.0f)); viewhelper.setalpha(mmenu, evaluate(percent, 0.1f, 1.0f));// 渐变动画 viewhelper.setpivotx(mcontent, 0);// 缩放中心 viewhelper.setpivoty(mcontent, mheight / 2); viewhelper.setscalex(mcontent, evaluate(percent, 1.0f, 0.9f));// 缩放动画 viewhelper.setscaley(mcontent, evaluate(percent, 1.0f, 0.9f)); getbackground().setcolorfilter((integer)(colorevaluate(percent, color.black, color.transparent)), porterduff.mode.src_over);// 亮度变化 } /** 估值器,根据开始数字和结束数字,随着百分比的变化得到一个数值,详情见floatevaluator */ private float evaluate(float fraction, number startvalue, number endvalue) { float startfloat = startvalue.floatvalue(); return startfloat + fraction * (endvalue.floatvalue() - startfloat); } /** 颜色取值,根据初始颜色和结束颜色,随着百分的变化取出不同的颜色,详情见argbevaluator */ 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)))); }
⑥我们提供一个打开/关闭菜单方法,供使用者调用。
/** 菜单切换 */ public void toggle() { if(isopen) { close(); } else { open(); } } /** * 打开菜单 */ private void open() { if (mviewdraghelper.smoothslideviewto(mcontent, mrange, 0)) {// 判断主页面是否滑动到指定位置 viewcompat.postinvalidateonanimation(this);// 会触发computescroll } isopen = true; } /** * 关闭菜单 */ private void close() { if (mviewdraghelper.smoothslideviewto(mcontent, 0, 0)) {// 判断主页面是否滑动到指定位置 viewcompat.postinvalidateonanimation(this);// 会触发computescroll } isopen = false; } @override public void computescroll() { super.computescroll(); if (mviewdraghelper.continuesettling(true)) {// 持续执行动画,如果返回则表示动画还没有执行完 viewcompat.postinvalidateonanimation(this); } }
==================至此我们的slidingmenu就定义完毕=====================
我们在mainactivity中使用
public class mainactivity extends activity { private slidingmenu mslidingmenu; @override 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(); } }
更多学习内容,可以点击《android侧滑效果汇总》学习。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android基于ViewDragHelper仿QQ5.0侧滑界面效果
-
Android仿QQ6.0主页面侧滑效果
-
Android仿QQ6.0主页面侧滑效果
-
Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一)
-
Android使用ViewDragHelper实现QQ6.X最新版本侧滑界面效果实例代码
-
Android使用ViewDragHelper实现QQ6.X最新版本侧滑界面效果实例代码
-
Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一)
-
Android使用ViewDragHelper实现QQ6.X最新版本侧滑界面效果实例代码
-
基于Android实现仿QQ5.0侧滑
-
基于Android实现仿QQ5.0侧滑