关于SlidingMenu的一些改进写法,仿QQ5.0侧拉缩进
来源:互联网 发布:dkms linux 编辑:程序博客网 时间:2024/06/13 02:07
SlidingMenu的使用教程很多,如果只需要简单的侧拉,使用如下的办法简单加载
点击SlidingMenu下载
首先下载完毕导入项目中,导入方式如图
这时还没有玩,slidingMenu在文件夹下另一个包中,包名为library如图(点击确定)
完成后开始记得看下app > build.gradle 是不是有这个项目的引用,么有就自己写,有就当这句话不存在。
之后开始配置menu的初始信息
private void loadMenu() { //获取屏幕的宽度 int with = ScreenUtils.getScreenWidth(this); //初始化侧边栏 menu = new SlidingMenu(this); menu.setMode(SlidingMenu.LEFT); // 设置触摸屏幕的模式 menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); //设置SlidingMenu菜单的宽度 menu.setBehindWidth(with / 2); // menu.setShadowDrawable(R.drawable.shadow);//设置阴影图片 // menu.setShadowWidthRes(R.dimen.shadow_width);//设置阴影图片的宽度 menu.setBackgroundColor(Color.BLACK); // 设置渐入渐出效果的值 menu.setFadeDegree(0.35f); menu.attachToActivity(MainActivity.this, SlidingMenu.SLIDING_CONTENT); //为侧滑菜单设置布局 menu.setMenu(R.layout.slidingmenuleft);}
ScreenUtils 是我自己的工具类,代码如下,主要是设置menu拉出来的宽度的
/** * @product: QCY_Sport * @Description: 屏幕相关辅助类 (用一句话描述该文件做什么) * @author: 朱亮(171422696@qq.com) * Date: 2016-11-22 * Time: 15:58 * @company:蓝米科技 version V1.0 */public class ScreenUtils { /** * 获得屏幕相关的辅助类 */ private ScreenUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } /** * 获得屏幕高度 * * @param context * @return */ public static int getScreenWidth(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } /** * 获得屏幕宽度 * * @param context * @return */ public static int getScreenHeight(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.heightPixels; } /** * 获得状态栏的高度 * * @param context * @return */ public static int getStatusHeight(Context context) { int statusHeight = -1; try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } /** * 获取当前屏幕截图,包含状态栏 * * @param activity * @return */ public static Bitmap snapShotWithStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, 0, width, height); view.destroyDrawingCache(); return bp; } /** * 获取当前屏幕截图,不包含状态栏 * * @param activity * @return */ public static Bitmap snapShotWithoutStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); view.destroyDrawingCache(); return bp; } }
slidingmenuleft.xml布局是自己定义的一个圆形头像CircleImageView还有自己的一些颜色配置colors, 这些都是需要你自己根据个人情况来设置的,里面有个自定义view的头像,这里改成自己的。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <com.org.zl.slidingmenudemo.myView.CircleImageView android:id="@+id/circleImageView" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/headportrait" android:layout_gravity="center" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="二狗子" android:textSize="20dp" android:layout_gravity="center" android:layout_marginLeft="10dp" android:textColor="@color/colorWhite" android:id="@+id/textView"/> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="2dp" android:layout_margin="10dp" android:background="@color/colorAccent" /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/setSound" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="音效设置" android:drawableLeft="@drawable/back" android:drawablePadding="20dp" android:layout_marginLeft="10dp" android:layout_marginBottom="25dp" android:textColor="@color/colorWhite" /> <TextView android:id="@+id/skinCenter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="皮肤中心" android:drawableLeft="@drawable/back" android:drawablePadding="20dp" android:layout_marginLeft="10dp" android:layout_marginBottom="25dp" android:textColor="@color/colorWhite" /> <TextView android:id="@+id/mySongList" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我的歌单" android:drawableLeft="@drawable/back" android:drawablePadding="20dp" android:layout_marginLeft="10dp" android:layout_marginBottom="25dp" android:textColor="@color/colorWhite" /> <TextView android:id="@+id/feedBack" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="意见反馈" android:drawableLeft="@drawable/back" android:drawablePadding="20dp" android:layout_marginLeft="10dp" android:layout_marginBottom="25dp" android:textColor="@color/colorWhite" /> <TextView android:id="@+id/about" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关于" android:drawableLeft="@drawable/back" android:drawablePadding="20dp" android:layout_marginLeft="10dp" android:layout_marginBottom="25dp" android:textColor="@color/colorWhite" /> <TextView android:id="@+id/search" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="搜索" android:drawableLeft="@drawable/back" android:drawablePadding="20dp" android:layout_marginLeft="10dp" android:layout_marginBottom="25dp" android:textColor="@color/colorWhite" /> </LinearLayout></LinearLayout>
最后别忘记,在onDestroy()中加上一句代码
@Override protected void onDestroy() { if(menu.isSlidingEnabled()){ menu.showContent(); } super.onDestroy(); }
任务完成,运行图片为
这是SlidingMenu的最简单的加载,现在需求变了需要变成侧拉缩进如下图
查看代码可以知道menu中有个方法setBehindCanvasTransformer()
这个方法是用在menu拉出来和缩回去的效果配置的,我们根据这个方法来达到自己的需求
menu.setBehindCanvasTransformer( new SlidingMenu.CanvasTransformer() { @Override public void transformCanvas(Canvas canvas, float percentOpen) { //percentOpen的值(0~1)之间 float scale = 0.75f + 0.25f * percentOpen; canvas.scale(scale, scale, -canvas.getWidth() / 2, canvas.getHeight() / 2); } });
这时,percentOpen 会在menu拉到最大的时候达到1,侧拉框完全显现,如果设置 float scale = 0.75f ;固定值时,效果如下
可以查看源码 SlidingMenu下
public void setBehindCanvasTransformer(CanvasTransformer t) { mViewBehind.setCanvasTransformer(t); }
这里面传入了一个CanvasTransformer 观察者,这个观察者在什么时候被调用呢,继续点进mViewBehind.setCanvasTransformer(t);中发现观察者被传入了setCanvasTransformer方法中,查找引用最终在
dispatchDraw找到,这是ViewGroup的绘制方法,有背景就调用onDraw方法,同时里面包含dispatchDraw方法,无背景时,直截调用dispatchDraw方法,所以….
@Override protected void dispatchDraw(Canvas canvas) { if (mTransformer != null) { canvas.save(); //绘制的过程中回调观察者 mTransformer.transformCanvas(canvas, mViewAbove.getPercentOpen()); super.dispatchDraw(canvas); canvas.restore(); } else super.dispatchDraw(canvas); }
但是在这里没有找到invalidate()啊,于是继续找,在本类中找到
@Override public void scrollTo(int x, int y) { super.scrollTo(x, y); if (mTransformer != null) invalidate(); }
scrollTo又被scrollBehindTo调用,scrollBehindTo又被CustomViewAbove的scrollTo调用
@Override public void scrollTo(int x, int y) { super.scrollTo(x, y); mScrollX = x; mViewBehind.scrollBehindTo(mContent, x, y); ((SlidingMenu)getParent()).manageLayers(getPercentOpen()); }
CustomViewAbove的scrollTo又被本类的onSizeChanged调用,
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // Make sure scroll position is set correctly. if (w != oldw) { // [ChrisJ] - This fixes the onConfiguration change for orientation issue.. // maybe worth having a look why the recomputeScroll pos is screwing // up? completeScroll(); scrollTo(getDestScrollX(mCurItem), getScrollY()); } }
最终CustomViewAbove被SlidingMenu初始化进addView中,明白了左边的拉框的原理,相同的道理,改变右边推框的也应该没问题
SlidingMenu加载了两个ViewGroup 一个是 CustomViewBehind,一个是CustomViewAbove,侧拉框在CustomViewBehind被处理,我们只需要改变CustomViewAbove的代码即可,代码和CustomViewBehind相同,逆推回去,添加相同的观察者即可,在SlidingMenu中添加一句代码
public void setAboveCanvasTransformer(CanvasTransformer t) { mViewAbove.setCanvasTransformer(t); }
这时必然会报错,因为CustomViewAbove没有setCanvasTransformer方法,需要自己添加进入一个观察者
public void setCanvasTransformer(SlidingMenu.CanvasTransformer t) { mTransformer = t; }
同时类上要声明观察者
private SlidingMenu.CanvasTransformer mTransformer;
观察者传入之后,需要确定在什么地方观察,这里可以参考CustomViewBehind里的观察者代码,发现有几个地方需要观察的
第一个是scrollTo 方法
@Override public void scrollTo(int x, int y) { super.scrollTo(x, y); mScrollX = x; mViewBehind.scrollBehindTo(mContent, x, y); ((SlidingMenu)getParent()).manageLayers(getPercentOpen()); if (mTransformer != null) invalidate(); }
第二个是dispatchDraw方法
@Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); // Draw the margin drawable if needed. mViewBehind.drawShadow(mContent, canvas); mViewBehind.drawFade(mContent, canvas, getPercentOpen()); mViewBehind.drawSelector(mContent, canvas, getPercentOpen()); if (mTransformer != null) { canvas.save(); mTransformer.transformCanvas(canvas, getPercentOpen()); super.dispatchDraw(canvas); canvas.restore(); } else super.dispatchDraw(canvas); }
还有一点,尽量将CustomViewAbove类中的FloatMath 改成 Math
float distanceInfluenceForSnapDuration(float f) { f -= 0.5f; // center the values about 0. f *= 0.3f * Math.PI / 2.0f; //这里改成Math. return (float) Math.sin(f); }
观察者写完了,进行最后一步,实现它
//设置activity层内容UI移动效果 //此方法为slidingmenu中自己增加的方法 menu.setAboveCanvasTransformer(new SlidingMenu.CanvasTransformer() { @Override public void transformCanvas(Canvas canvas, float percentOpen) { float scale = 1f - 0.25f * percentOpen; canvas.scale(scale, scale, 0, canvas.getHeight() / 2); } });
设置完毕准备运行,最后运行发现activity重叠,如图
这里真的发了很长时间找问题,各种比较,最后找到这里
CustomViewAbove下的dispatchDraw()除了问题,因为我们改过里面的代码,而CustomViewBehind里的super.dispatchDraw(canvas);是经过逻辑的,而CustomViewAbove是直接返回的,所以,注释掉就好
复制下面代码黏贴:
@Override protected void dispatchDraw(Canvas canvas) { // super.dispatchDraw(canvas); // Draw the margin drawable if needed. mViewBehind.drawShadow(mContent, canvas); mViewBehind.drawFade(mContent, canvas, getPercentOpen()); mViewBehind.drawSelector(mContent, canvas, getPercentOpen()); if (mTransformer != null) { canvas.save(); mTransformer.transformCanvas(canvas, getPercentOpen()); super.dispatchDraw(canvas); canvas.restore(); } else super.dispatchDraw(canvas); }
最后运行的结果图片为
项目下载地址
- 关于SlidingMenu的一些改进写法,仿QQ5.0侧拉缩进
- 修改slidingmenu仿QQ5.0侧滑菜单
- 仿QQ5.0的侧滑菜单
- 高仿QQ5.0的侧滑菜单的实现
- Android实现仿QQ5.0的侧滑效果
- 仿QQ5.0缩放式侧滑栏的实现
- 仿QQ5.0侧滑菜单【AndroidResideMenu】
- 仿QQ5.0侧滑菜单ResideMenu
- 仿QQ5.0侧滑效果
- 高仿qq5.0侧滑效果
- 仿QQ5.0侧滑菜单实现
- 仿QQ5.0侧栏源码
- 仿QQ5.0侧滑菜单ResideMenu
- 仿QQ5.0侧滑菜单ResideMenu
- 仿QQ5.0侧滑先行版
- 仿QQ5.0侧滑
- binbinyang---关于开发中用到的侧拉---SlidingMenu
- Android自定义控件(三) 高仿QQ5.0 侧滑面板 侧拉删除 视差特效等效果
- phpize找不到怎么办
- dubbo+zookeeper+Spring 单机配置步骤---【基础实践篇】
- [leetcode-485]Max Consecutive Ones
- [CloudReader]Android - 仿网易云音乐歌单详情页
- java设计模式——单例设计模式
- 关于SlidingMenu的一些改进写法,仿QQ5.0侧拉缩进
- Codeforces 8VC Venture Cup 2017 - Elimination Round D.PolandBall and Polygon
- html的map热力图(二)——热区样式
- PID调节参数的作用
- python 3-4 如何进行反向迭代以及如何实现反向迭代 __reversed__ yield
- Jquery中一款DataTimePicker日期选择器
- C++中的long long和__int64类型
- 单元测试
- 分页效果