仿QQ侧滑效果
来源:互联网 发布:淘宝二类医疗器械申请 编辑:程序博客网 时间:2024/05/22 06:59
仿QQ侧滑效果
我们经常使用QQ,感觉QQ的侧滑效果还是不错的,虽然网上有侧滑的包,或者V4包中带的DrawerLayout,但是使用起来不太满意,所以我们就会自己手写侧滑效果,今天我们就来写一下仿QQ侧滑效果。
先上图:
写侧滑功能的思路有很多,就我本人而言,就写个两种:
1.ViewGroup + ViewDragHelper + onTouch事件处理
2.HorizontalScrollView + GestureDetector + onTouch事件处理
第二种现对第一种简单的多,所以今天我们就使用第二种来实现侧滑效果。
看代码前我们需要知道几个小知识:
- HorizontalScrollView 水平滑动布局
- GestureDetector 手势处理类
- onTouch 事件的分发和拦截以及处理
上面三点可以百度,网上太多了,这里就不一一介绍了。
直接上代码:
public class SlidingMenu extends HorizontalScrollView {/** * 滑动界面状态改变时回调接口 * @author root * */public interface OnSlidingMenuStatusChangeListenter { /** * 界面关闭时调用 */ void close(); /** * 界面完全打开时调用 */ void open();}//滑动界面状态改变时回调接口private OnSlidingMenuStatusChangeListenter mListenter=null;/** * 滑动界面状态改变时回调接口 * @param listenter */public void setOnSlidingMenuStatusChangeListenter(OnSlidingMenuStatusChangeListenter listenter){ this.mListenter=listenter;}//菜单viewprivate View mMenuView;//内容viewprivate View mContentView;//菜单宽度private int mMenuWidth;//菜单和内容宽度的差值private float right_padding=0;//菜单是否被打开private boolean isMenuOpen=false;//手势处理类private GestureDetector mGestureDetector=null;//最小fling速度private int minimumFlingVelocity=0;//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); //解析自定义属性 TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); if(typedArray!=null){ right_padding = typedArray.getDimension(R.styleable.SlidingMenu_right_padding, dip2px(50)); typedArray.recycle(); } //获取fling的最小速度 ViewConfiguration configuration = ViewConfiguration.get(context); minimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); //初始化手势处理器 mGestureDetector=new GestureDetector(context,new MyGestureListener());}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(changed){ //布局改变,则调用 scrollTo(mMenuWidth,0); }}//事件分发@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) { //当前点击位置 float current = ev.getX(); //如果菜单打开且当前点击位置>菜单宽度,则停止分发事件 if(isMenuOpen && current>mMenuWidth){ //关闭菜单 closeMenu(); //阻止事件分发 return false; } return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent ev) { //拦截触摸事件 //将触摸事件交给手势处理器 if(mGestureDetector.onTouchEvent(ev)){ return false; } switch (ev.getAction()){ case MotionEvent.ACTION_UP: int scrollX = getScrollX(); if(scrollX>mMenuWidth/2){ closeMenu(); }else { openMenu(); } return false; } return super.onTouchEvent(ev);}/** * 关闭菜单 */private void closeMenu() { smoothScrollTo(mMenuWidth,0); isMenuOpen=false; if(mListenter!=null){ mListenter.close(); }}//打开菜单private void openMenu() { smoothScrollTo(0,0); isMenuOpen=true; if(mListenter!=null){ mListenter.open(); }}//布局加载完毕,执行@Overrideprotected void onFinishInflate() { super.onFinishInflate(); //1.获取菜单和内容的布局 ViewGroup childAt = (ViewGroup) getChildAt(0); if(childAt==null){ throw new IllegalArgumentException("SlidingMenu must contain child view!"); } //1.1菜单 mMenuView = childAt.getChildAt(0); if(mMenuView==null){ throw new IllegalArgumentException("SlidingMenu must contain menu view!"); } //1.2内容 mContentView = childAt.getChildAt(1); if(mContentView==null){ throw new IllegalArgumentException("SlidingMenu must contain content view!"); } //2.设置宽高 //2.1菜单宽度 mMenuWidth = (int) (getScreenWidth() - right_padding); mMenuView.getLayoutParams().width=mMenuWidth; //2.2内容的宽度 mContentView.getLayoutParams().width=getScreenWidth();}/** * 屏幕宽度 * @return */private int getScreenWidth(){ DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); return displayMetrics.widthPixels;}/** * dip转px * @param dp * @return */private int dip2px(int dp){ DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); return (int) (displayMetrics.density*dp);}//手势监听private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //如果是纵向滑动,则直接返回,防止横向滑动 if(Math.abs((velocityY)) > Math.abs(velocityX)){ return super.onFling(e1,e2,velocityX,velocityY); } //向左----velocityX < 0 if(velocityX<0 && isMenuOpen && Math.abs(velocityX) > minimumFlingVelocity){ toggleMenu(); return true; } //向右-----velocityX > 0 if(velocityX > 0 && !isMenuOpen && Math.abs(velocityX) > minimumFlingVelocity){ toggleMenu(); return true; } return super.onFling(e1,e2,velocityX,velocityY); }}/** * 切换状态 * 提供给用户调用 */public void toggleMenu() { if(isMenuOpen){ closeMenu(); }else { openMenu(); }}//位置滑动时,调用@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); //滑动时,给菜单设置默认位置 mMenuView.setTranslationX(l*0.8f); //l (0-->mMenuWidth) //percent (0--->1) float percent = l * 1f / mMenuWidth; //percent (0.4->1) percent=evaluate(percent,0.4,1); //给内容添加阴影(0.4-1) mContentView.getBackground().setColorFilter((Integer)evaluateColor(percent, Color.BLACK,Color.TRANSPARENT), android.graphics.PorterDuff.Mode.SRC_OVER);}/** * 评估值 * @param fraction * @param startValue * @param endValue * @return */public Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat);}/** * 颜色变化过度 * @param fraction * @param startValue * @param endValue * @return */public Object evaluateColor(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))));}
上面代码没什么好说的,因为注释很清晰。
如果给内容添加阴影,不是太了解,可以使用其他方法,比如:在内容的布局上面添加一层ImageView,然后在onScrollChanged中对ImageView背景透明度进行调整就ok了。
上面有个自定义属性,我们来看下代码:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="SlidingMenu"> <attr name="right_padding" format="dimension"></attr> </declare-styleable></resources>
很简单吧!
下面我们来看下使用:
<?xml version="1.0" encoding="utf-8"?><github.com.sldingmenu.view.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" app:right_padding="80dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <!-- 菜单 --> <include layout="@layout/menu_layout"></include> <!--内容--> <include layout="@layout/content_layout"></include> </LinearLayout></github.com.sldingmenu.view.SlidingMenu>
如果要代码中进行侧滑,只要调用 SlidingMenu的toggleMenu() 就行了 。
如果需要监听侧滑栏状态,只要调用SlidingMenu的setOnSlidingMenuStatusChangeListenter
我们看到使用很简单吧!
直接给出地址:点击下载
代码查看地址:查看
阅读全文
0 0
- 仿QQ侧滑效果
- 仿QQ新版本侧滑效果
- 仿QQ侧滑效果,DragLayout使用方法
- 仿QQ侧滑效果(swifit)
- Android仿QQ侧滑效果
- 仿QQ侧滑菜单效果
- 仿QQ侧滑效果ViewDragHelper
- 仿QQ侧滑菜单效果
- 仿QQ侧滑和酷狗侧滑效果
- 高仿 QQ 侧滑删除 Item 的效果
- 最简单的基于SlidingMenu仿QQ侧滑效果
- 仿(现QQ)首页侧滑(抽屉)效果
- 仿QQ侧滑删除Item效果Demo
- DrawerLayout 仿QQ侧滑抽屉的效果
- 仿QQ列表左滑删除效果
- 仿QQ圆点拖拽效果
- 漂亮的侧滑主页(仿QQ、腾讯QQ首页侧滑效果)
- 简单实现界面的侧滑效果(Swift)仿QQ侧滑效果
- JavaScript经典案例
- Lintcode55 Compare Strings solution 题解
- kotlin在Android studio3.0上的配置问题
- java 创建多线程两种方法比较
- finalize的作用
- 仿QQ侧滑效果
- Image magnifier
- Shell echo命令
- java用poi实现对word读取和修改操作
- order by与group by区别
- 【原】MIT在线课程学习笔记之《Introduction to C Memory Management and C++ Object-Oriented Programming》
- 深入理解java虚拟机读书笔记(二): 运行时数据区域
- Oracle SQL分析函数lag、lead解决相邻记录比较问题
- 关于算法