
对于这个效果,我之前写过一种实现方法 仿QQ6.0主页面侧滑效果,这种方法跟手性不好,如果复现了的朋友应该能体会到,并且,还得自己处理很多 ontouch 事件,所以,这篇文章带大家体验一下另外一种实现方法,继承自 horizontalscrollview
实现步骤第一步:创建自定义类
package com.wust.myhorizontalscrollview;import androID.content.Context;import androID.util.AttributeSet;import androID.Widget.horizontalscrollview;public class mySlIDingMenu extends horizontalscrollview { public mySlIDingMenu(Context context) { this(context,null); } public mySlIDingMenu(Context context, AttributeSet attrs) { this(context, attrs,0); } public mySlIDingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }}第二步:引用布局
<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:app="http://schemas.androID.com/apk/res-auto" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:orIEntation="horizontal" tools:context=".MainActivity"> <com.wust.myhorizontalscrollview.mySlIDingMenu androID:layout_wIDth="match_parent" androID:layout_height="match_parent"> <TextVIEw androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:text="我是菜单" androID:background="#f00"/> <TextVIEw androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:text="我是内容" androID:background="#0f0"/> </com.wust.myhorizontalscrollview.mySlIDingMenu></linearLayout>如果大家在这一步试图去运行,就会发现报错,如下:
大概意思就是说 horizontalscrollview 里面只能包一个布局,所以,我们得把上面的布局文件修改一下,用一个线性布局把他们包起来
<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:app="http://schemas.androID.com/apk/res-auto" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:orIEntation="horizontal" tools:context=".MainActivity"> <com.wust.myhorizontalscrollview.mySlIDingMenu androID:layout_wIDth="match_parent" androID:layout_height="match_parent"> <linearLayout androID:layout_wIDth="match_parent" androID:orIEntation="horizontal" androID:layout_height="match_parent"> <TextVIEw androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:text="我是菜单" androID:background="#f00"/> <TextVIEw androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:text="我是内容" androID:background="#0f0"/> </linearLayout> </com.wust.myhorizontalscrollview.mySlIDingMenu></linearLayout>第三步:编写逻辑
这个时候当我们运行程序的时候就会发现,我们明明写的 match_parent 可是最后的结果不是铺满的,所以,我们得给我们的自定义组件赋值宽高。在 onMeasure() 方法里??我们不妨来试试
package com.wust.myhorizontalscrollview;import androID.content.Context;import androID.util.AttributeSet;import androID.util.displayMetrics;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.vIEw.WindowManager;import androID.Widget.horizontalscrollview;public class mySlIDingMenu extends horizontalscrollview { private int mScreenWIDth; private VIEw mMenu; private VIEw mContent; private int mMenuWIDth; private int mContentWIDth; private int mScrennHeight; public mySlIDingMenu(Context context) { this(context,null); } public mySlIDingMenu(Context context, AttributeSet attrs) { this(context, attrs,0); } public mySlIDingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取屏幕宽度 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); displayMetrics metrics = new displayMetrics(); wm.getDefaultdisplay().getMetrics(metrics); mScreenWIDth = metrics.wIDthPixels; mScrennHeight = metrics.heightPixels; } @OverrIDe protected voID onMeasure(int wIDthMeasureSpec, int heightmeasureSpec) { super.onMeasure(wIDthMeasureSpec, heightmeasureSpec); //初始化宽度、高度 int wIDth = 0; int height = 0; //获取子代 VIEwGroup ll_child = (VIEwGroup) getChildAt(0); mMenu = ll_child.getChildAt(0); mContent = ll_child.getChildAt(1); //设置菜单 内容的宽度 mMenuWIDth = mMenu.getLayoutParams().wIDth = mScreenWIDth - 400; mContentWIDth = mContent.getLayoutParams().wIDth = mScreenWIDth; //设置自定义组件的宽高 wIDth = mMenuWIDth + mContentWIDth; height = mScrennHeight; setMeasuredDimension(wIDth,height); }}我们发现布局结构的确出来了,但是划不动, 最大的可能就是我们设置宽高的时机不对,通过翻阅资料,我发现我们应该写在布局解析完成这个时间节点
package com.wust.myhorizontalscrollview;import androID.content.Context;import androID.util.AttributeSet;import androID.util.displayMetrics;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.vIEw.WindowManager;import androID.Widget.horizontalscrollview;public class mySlIDingMenu extends horizontalscrollview { private int mScreenWIDth; private VIEw mMenu; private VIEw mContent; private int mMenuWIDth; private int mContentWIDth; private int mScrennHeight; public mySlIDingMenu(Context context) { this(context,null); } public mySlIDingMenu(Context context, AttributeSet attrs) { this(context, attrs,0); } public mySlIDingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取屏幕宽度 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); displayMetrics metrics = new displayMetrics(); wm.getDefaultdisplay().getMetrics(metrics); mScreenWIDth = metrics.wIDthPixels; mScrennHeight = metrics.heightPixels; } @OverrIDe protected voID onFinishInflate() { super.onFinishInflate(); //获取子代 VIEwGroup ll_child = (VIEwGroup) getChildAt(0); mMenu = ll_child.getChildAt(0); mContent = ll_child.getChildAt(1); //设置菜单 内容的宽度 mMenuWIDth = mMenu.getLayoutParams().wIDth = mScreenWIDth - 400; //设置布局宽度的第二种方法 VIEwGroup.LayoutParams contentLayoutParams = mContent.getLayoutParams(); mContentWIDth = contentLayoutParams.wIDth = mScreenWIDth; mContent.setLayoutParams(contentLayoutParams); }}这个时候,你就会发现屏幕可以滑动了
第四步:优化
经过上面三步,侧滑菜单我们就做完了,下面所讲是为了优化用户体验
优化一:最初渲染页面的时候,菜单栏是关闭的在这一步中要注意 关闭菜单的时机,即到底写在那个函数里
package com.wust.myhorizontalscrollview;import androID.content.Context;import androID.util.AttributeSet;import androID.util.displayMetrics;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.vIEw.WindowManager;import androID.Widget.horizontalscrollview;public class mySlIDingMenu extends horizontalscrollview { private int mScreenWIDth; private VIEw mMenu; private VIEw mContent; private int mMenuWIDth; private int mContentWIDth; private int mScrennHeight; public mySlIDingMenu(Context context) { this(context,null); } public mySlIDingMenu(Context context, AttributeSet attrs) { this(context, attrs,0); } public mySlIDingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取屏幕宽度 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); displayMetrics metrics = new displayMetrics(); wm.getDefaultdisplay().getMetrics(metrics); mScreenWIDth = metrics.wIDthPixels; mScrennHeight = metrics.heightPixels; } @OverrIDe protected voID onFinishInflate() { super.onFinishInflate(); //获取子代 VIEwGroup ll_child = (VIEwGroup) getChildAt(0); mMenu = ll_child.getChildAt(0); mContent = ll_child.getChildAt(1); //设置菜单 内容的宽度 mMenuWIDth = mMenu.getLayoutParams().wIDth = mScreenWIDth - 400; //设置布局宽度的第二种方法 VIEwGroup.LayoutParams contentLayoutParams = mContent.getLayoutParams(); mContentWIDth = contentLayoutParams.wIDth = mScreenWIDth; mContent.setLayoutParams(contentLayoutParams); } @OverrIDe protected voID onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); closeMenu(); } private voID closeMenu(){ smoothScrollTo(mMenuWIDth,0); } private voID openMenu(){ smoothScrollTo(0,0); }}优化二:判断手指抬起时是否超过菜单宽度一半,超过即打开菜单,没有超过即关闭菜单在这一步中要区别于我们上讲 仿QQ6.0主页面侧滑效果 中的滑动正负观,在这我就不过多赘述,大家自己动手实践就知道了
@OverrIDe public boolean ontouchEvent(MotionEvent ev) { switch(ev.getAction()){ //自己处理 手指抬起事件 所以 return true case MotionEvent.ACTION_UP: { //就是这里要注意,因为最开始 getScrollX() 的值是 mMenuWIDth if (getScrollX() > mMenuWIDth/2){ closeMenu(); }else { openMenu(); } return true; } } return super.ontouchEvent(ev); }优化三:处理快速滑动手势在这个里面主要用到了一个类 GestureDetector
public mySlIDingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取屏幕宽度 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); displayMetrics metrics = new displayMetrics(); wm.getDefaultdisplay().getMetrics(metrics); mScreenWIDth = metrics.wIDthPixels; mScrennHeight = metrics.heightPixels; //第一步:在构造方法里创建 GestureDetector 类 mGestureDetector = new GestureDetector(context, new myGestureListener()); }@OverrIDe public boolean ontouchEvent(MotionEvent ev) { //第二步:在 ontouchEvent 中拦截快速滑动手势 if (mGestureDetector.ontouchEvent(ev)){ return mGestureDetector.ontouchEvent(ev); } switch(ev.getAction()){ //自己处理 手指抬起事件 所以 return true case MotionEvent.ACTION_UP: { //就是这里要注意,因为最开始 getScrollX() 的值是 mMenuWIDth if (getScrollX() > mMenuWIDth/2){ closeMenu(); }else { openMenu(); } return true; } } return super.ontouchEvent(ev); }//第三步:编写 myGestureListener private class myGestureListener extends GestureDetector.SimpleOnGestureListener { @OverrIDe public boolean onFling(MotionEvent e1, MotionEvent e2, float veLocityX, float veLocityY) { System.out.println("veLocityX ->" + veLocityX); if (menuIsOpen){ //菜单打开状态 if (veLocityX < -500){ closeMenu(); return true; } }else { //菜单关闭状态 if (veLocityX > 500){ openMenu(); return true; } } return false; } }//在下面两个方法中添加了菜单是否打开标志private voID closeMenu(){ smoothScrollTo(mMenuWIDth,0); menuIsOpen = false; }private voID openMenu(){ smoothScrollTo(0,0); menuIsOpen = true; }优化四:根据滑动给内容页添加阴影其实要实现这个有以下两种方法:
在 xml 中静态添加 VIEw 覆盖层
在 java 代码中动态添加 VIEw 覆盖层(复用性好,我们选择这一种)
@OverrIDe protected voID onFinishInflate() { super.onFinishInflate(); //获取子代 VIEwGroup ll_child = (VIEwGroup) getChildAt(0); mMenu = ll_child.getChildAt(0); mContent = ll_child.getChildAt(1); //设置菜单 内容的宽度 mMenuWIDth = mMenu.getLayoutParams().wIDth = mScreenWIDth - 400; //第一步:先把以前的内容 从线性布局中移除 ll_child.removeVIEw(mContent); //第二步:创建一个帧布局 FrameLayout contentFrameLayout = new FrameLayout(getContext()); //第三步:把以前的内容 加入到这个帧布局中 contentFrameLayout.addVIEw(mContent); //第四步:创建一个阴影 层 mShadeVIEw = new VIEw(getContext()); //给阴影层设置颜色 mShadeVIEw.setBackgroundcolor(color.parsecolor("#550000")); //第五步:将这个阴影层加入帧布局中,覆盖在内容之上 contentFrameLayout.addVIEw(mShadeVIEw); //第六步:给帧布局设置宽度 VIEwGroup.LayoutParams params = new VIEwGroup.LayoutParams(VIEwGroup.LayoutParams.MATCH_PARENT, VIEwGroup.LayoutParams.MATCH_PARENT); params.wIDth = mScreenWIDth; contentFrameLayout.setLayoutParams(params); //第七步:将这个帧布局添加进来 ll_child.addVIEw(contentFrameLayout); //第八步:将阴影层设为透明 mShadeVIEw.setAlpha(0.0f); } @OverrIDe protected voID onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); //计算比例因子 1 -> 0 float rate = l/(float)mMenuWIDth; //根据比例因子设置透明度 mShadeVIEw.setAlpha(1-rate); }最终效果
有偿提问如果大家觉得这篇文章帮助你了,可以支持一下。
有偿提问
总结以上是内存溢出为你收集整理的仿QQ6.0主页面侧滑效果(第二种实现方法)全部内容,希望文章能够帮你解决仿QQ6.0主页面侧滑效果(第二种实现方法)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)