自定义控件-侧拉菜单
来源:互联网 发布:编程工具与编程 编辑:程序博客网 时间:2024/05/16 13:42
手机版qq有一个挺不错的效果是侧拉菜单,在主界面向右滑动就会在左侧出现关于自己qq的一些信息;
实现侧滑效果目前知道有三种:
一是SlidingDrawer,谷歌在Android4.2之后已经不建议使用
二是DrawerLayout,谷歌提供的挺好用的控件,只需在布局文件中加载即可
三是第三方提供的开源控件,更加的灵活;下面就来简单介绍一下原理
一、需求
1.定义两个布局,菜单和主内容,然后整合在一个自定义的控件中
2.分别测量出菜单和主内容的宽和高
3.主内容全屏显示在屏幕上,那么左侧的菜单就会看不到,达到了隐藏菜单的效果
4.处理屏幕的onTouchEvent()事件,实现左右滑动控制菜单的隐藏与显示
二、具体实现
1.定义布局文件菜单和主内容,然后整合在自定义的SlideMenu控件中
2.在SlideMenu中通过onMeasure测量布局文件的宽和高
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //测量菜单的宽和高,宽为240dip,高为父窗体高度 //0代表菜单 View menuView = getChildAt(0); menuView.measure(menuView.getLayoutParams().width, heightMeasureSpec); //测量内容正文的宽和高,与父窗体一致 //1代表正文内容 View contentView = getChildAt(1); contentView.measure(widthMeasureSpec, heightMeasureSpec); }
在系统底层measure调用了onMeasure(定义了宽高的约束)
onMeasrue调用了setMeasureDimension(真实的宽高信息)
3.通过onLayout方法绘制布局
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //把测量出菜单和内容绘制屏幕上 View menuView = getChildAt(0); //设置菜单在屏幕的左侧显示(即隐藏) menuView.layout(-menuView.getMeasuredWidth(), t, 0, b); //主内容的绘制 View contentView = getChildAt(1); contentView.layout(l, t, r, b); }
4.处理屏幕的onTouchEvent事件实现菜单的隐藏与显示
@Override public boolean onTouchEvent(MotionEvent event) { int scrollX; switch (event.getAction()) { //按下 case MotionEvent.ACTION_DOWN: downX = (int) event.getX(); break; //移动 case MotionEvent.ACTION_MOVE: int moveX = (int) event.getX(); //偏移量 int deltax = downX - moveX; scrollX = getScrollX() + deltax; //根据当前位置确定屏幕的显示 if (scrollX < -getChildAt(0).getMeasuredWidth()) { scrollTo(-getChildAt(0).getMeasuredWidth(), 0); } else if (scrollX > 0) { scrollTo(0, 0); } else { scrollBy(deltax, 0); } downX = moveX; break; //抬起 case MotionEvent.ACTION_UP: int center = -getChildAt(0).getMeasuredWidth() / 2; scrollX = getScrollX(); if (scrollX < center) { currentState = SCREEN_CONTENT; } else { currentState = SCREEN_MAIN; } switchScreen(); break; } return true; } /** * 根据currentState的状态来更改屏幕的显示 */ private void switchScreen() { int startX = getScrollX(); //当前屏幕的X位置 int dX = 0; //增量=目的位置-当前位置 switch (currentState) { case SCREEN_CONTENT:// scrollTo(-getChildAt(0).getMeasuredWidth(),0); dX = -getChildAt(0).getMeasuredWidth() - startX; break; case SCREEN_MAIN:// scrollTo(0,0); dX = 0 - startX; break; } int duration = Math.abs(dX) * 10; if (duration > 1000) { duration = 1000; } scroller.startScroll(startX, 0, dX, 0, duration); invalidate(); } @Override public void computeScroll() { //当不在模拟数据时候跳出递归 if (scroller.computeScrollOffset()) { //获取当前模拟的数据 int currX = scroller.getCurrX(); //更新位置 scrollTo(currX, 0); invalidate(); } }
滑动的分析:
1.当点击屏幕时记录下当前的位置downX,在移动的过程中根据当前位置moveX和downX计算偏移量
根据偏移量的值不断的修正菜单和主内容在屏幕的显示位置;
2.当抬起时,如果菜单显示出来的内容是否大于二分之一,那么滑动显示菜单,反之显示主内容
3.currentState用来记录当前屏幕显示的是菜单还是主内容,并且是屏幕固定时偏移量计算的依据
4.scroller.startScroll(startX,0,dX,0,duration)
用来模拟X轴从startX到偏移dX经过duration时间的过程,但是这个方法只是模拟,并不会改变
屏幕的显示,还需要通过invalidate()来修改屏幕的显示
5.invalidate()在ViewGroup中通过调用DrawChild()->再调view.draw->computeScroll修改屏幕
显示的内容,由于startScroll的数据是缓慢变化的,因此需要用递归不断的更新当前的显示,就
实现了松手后菜单缓慢移动的效果
三、回调简介
Android回调方法用的特别多,其原理类似于设计模式中的观察者模式,回调通过自身提供一个内部
接口,在接口定义统一的方法,那么不管是谁调用我,只要实现我接口中定义的方法,使代码有了很
好的封装性
四、个人总结
写自定义控件一定要有的步骤:
1.分析控件的实现都有什么状态
2.找出状态之间转换的临界条件
3.实现即可
0 0
- 自定义控件-侧拉菜单
- 自定义控件--侧拉菜单
- 自定义控件之侧拉菜单SlidingMenu
- 自定义侧拉控件
- Android自定义侧拉菜单-做一个为自己定制的侧拉控件
- 自定义控件:侧拉删除
- 自定义控件:侧滑菜单
- 自定义控件-侧滑菜单
- 自定义SwipeLayout侧拉删除控件
- UITableView 侧拉菜单 原生+自定义 详解
- Android:自定义侧滑菜单控件
- 自定义控件--QQ侧滑菜单
- 自定义控件之侧滑菜单
- android自定义控件 侧滑菜单
- 自定义控件菜单
- android控件-自定义菜单
- android 自定义菜单控件
- 自定义控件 防优酷菜单
- LeetCode 38 : Count and Say (Java)
- 多线程编程-线程的创建和终止
- 什么是性能测试?
- 一步一步教你Socket编程
- 初识RMAN2:12C中数据文件和归档日志的保留策略
- 自定义控件-侧拉菜单
- 华为的模式
- Oracle ROWID详解
- UI基础-XML、JSON 数据结构解析
- 运算符重载
- 关于Handler 使用This Handler class should be static or leaks might occur 警告处理
- 手册下载
- 09_Java运算符
- C++学习网站