Android 自定义滑动容器View(2)
来源:互联网 发布:深圳壹基金知乎 编辑:程序博客网 时间:2024/06/07 03:59
书接上回,上次我们实现了一个能滑动的view ,这次我们来改造下,允许他快速滑动的时候 可以 花很多个
快速向上向下滑动 这个 明显是个 “手势”,然而android 提供了一个 很爽的 辅助类来处理这种手势
android.view.GestureDetector
配合 scroller使用 简直无敌
GestureDetector 使用需要 配合 GestureDetector.OnGestureListener 来处理各种手势操作
使用方法
1. 初始化 GestureDetector
2. 实现 GestureDetector.OnGestureListener
3. 在 View 的onTouchEvent( 当然 也可以是 dispatchTouchEvent,这个看你需要) 方法中调用 GestureDetector.onTouchEvent 方法来分发事件
4. 在需要的处理的手势动作方法上实现对应的方法,比如调用scroller 去滑动
基本上,从GestureDetector.OnGestureListener 接口方法名都可以知道这个接口就是通过 GestureDetector 来处理 touch event 然后分发到 OnGestureListener 的各个方法。
下面来改造下之前的 滑动View
之前我们 都在 dispatchTouchEvent 里面判断event类型 ,然后手工计算 滑动的距离,然后调用scroll去滑动,这些通过 GestureDetector 现在把事件分发给 OnGestureListener 了,所以我们现在在这个OnGestureListener 的对应 的方法里面实现,刚好 OnGestureListener 里面就有个onScroll方法,这个特么的还帮你算好距离,爽!!!
根据GestureDetector 使用方式,把我们之前的View 实现 OnGestureListener ,重写里面 dispathTouchEvent 和实现onScroll 方法
int mScrollableHeight = 0; protected void init() { mScroller = new Scroller(getContext()); mGestureDetector = new GestureDetector(getContext(), this); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { .....省略布局代码 //计算出可滑动的距离,因为 算到是Y坐标 所以 要减去 当前view的height 来算出 允许垂直滑动的距离 mScrollableHeight = (layoutBottom - getHeight()); } /** * 获取允许滑动的距离 * @param y * @return */ private int getScrollableHeight(int y) { return Math.max(0, Math.min(mScrollableHeight, y)); } @Override public boolean dispatchTouchEvent(MotionEvent event) { //分发事件到 GestureDetector return mGestureDetector.onTouchEvent(event) || super.dispatchTouchEvent(event); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { //把之前在dispatchTouchEvent里面的逻辑搬到这里来 int tx = (int) (getScrollX() + distanceX); int ty = (int) (getScrollY() + distanceY); //计算可滑动距离 ty = getScrollableHeight(ty); scrollTo(0, ty); return false; }
好了,这些改造完滑动的了。
下面我们来改动他可以快速滑动 一次滑动多个 ,这里面用到 fling 这个手势,也就是说 在重写 onFling 的方法即可
@Override public boolean onDown(MotionEvent e) { //按下的时候 停止 滑动 mScroller.abortAnimation(); return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (Math.abs(velocityY) > 200) { //调用快速滑动 mScroller.fling(getScrollX(), getScrollY(), (int) -velocityX, (int) -velocityY, 0, 0, 0, mScrollableHeight); } return false; }
啊?mScroller.fling 是什么鬼?这个是 Scroller 专门提供出来方便这个使用的方法,直接使用他的方法即可,而且 在onDown里面 把滑动停下,因为如果不做这个 在滑动的时候,必须等待到他滑动完毕才能下次再滑,所以这里就把他手工停掉。
好了 下面放出完整代码
/** * 滑动 */public class MyScrollerView extends ViewGroup implements GestureDetector.OnGestureListener { GestureDetector mGestureDetector; Scroller mScroller; int mScrollableHeight = 0;//允许滑动最大距离 public MyScrollerView(Context context) { super(context); init(); } public MyScrollerView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MyScrollerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public MyScrollerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } protected void init() { mScroller = new Scroller(getContext()); mGestureDetector = new GestureDetector(getContext(), this); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) {//判断是否有滑动过 int y = getScrollableHeight(mScroller.getCurrY()); scrollTo(mScroller.getCurrX(), y); postInvalidate();//重画 } super.computeScroll(); } public void smoothScrollTo(int y) { //TODO 检测y的边界 mScroller.abortAnimation();//标志上次 的滑动结束 mScroller.startScroll(getScrollX(), getScrollY(), 0, getScrollableHeight(y));//移动到xy postInvalidate();//让view重画 } @Override public boolean dispatchTouchEvent(MotionEvent event) { return mGestureDetector.onTouchEvent(event) || super.dispatchTouchEvent(event); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); child.measure(widthMeasureSpec, 0);//child 的 height 必须是 wrapcontent,由于此view允许滑动,所以子view都要计算出来 } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** * 获取允许滑动的距离 * @param y * @return */ private int getScrollableHeight(int y) { return Math.max(0, Math.min(mScrollableHeight, y)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //垂直布局 int layoutLeft = 0; int layoutTop = 0; int layoutRight = r; int layoutBottom = 0; int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); layoutBottom = layoutTop + child.getMeasuredHeight(); child.layout(layoutLeft, layoutTop, layoutRight, layoutBottom); layoutTop = layoutBottom; } //计算出可滑动的距离,因为 算到是Y坐标 所以 要减去 当前view的height 来算出 允许垂直滑动的距离 mScrollableHeight = (layoutBottom - getHeight()); } @Override public boolean onDown(MotionEvent e) { //按下的时候 停止 滑动 mScroller.abortAnimation(); return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { int tx = (int) (getScrollX() + distanceX); int ty = (int) (getScrollY() + distanceY); //计算可滑动距离 ty = getScrollableHeight(ty); scrollTo(0, ty); return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (Math.abs(velocityY) > 200) { //调用快速滑动 mScroller.fling(getScrollX(), getScrollY(), (int) -velocityX, (int) -velocityY, 0, 0, 0, mScrollableHeight); } return false; }}
告一段落
- Android 自定义滑动容器View(2)
- Android 自定义滑动容器View
- Android:View滑动与自定义
- android自定义滑动开关控件,自定义view
- android自定义view之自定义容器
- android view 自定义viewgroup 实例--屏幕滑动
- android自定义View之滑动开关SlideButton
- Android 自定义View 实现垂直滑动页
- Android 自定义View字母滑动索引
- android自定义View之滑动删除
- Android自定义View之滑动取值条
- Android 试题滑动刻度尺--自定义View
- Android自定义view 滑动开关 支持左右滑动 适用于listview
- Android 自定义View 实现手势监听,左右滑动,上下滑动
- Android 自定义View:实现View的滑动效果
- Android 自定义View:实现View的滑动效果
- Android开发自定义View之滑动按钮与自定义属性
- Android开发自定义View之滑动按钮与自定义属性
- utilities(C++)——单例(Singleton) (使用智能指针 shared_ptr)
- 操作系统可变分区用C语言实现按最佳适应算法分配内存
- Android查找方法所在的包快捷键
- Android获取SD卡上所有图片、视频缩略图和音乐专辑封面
- 第三周项目-委派任务
- Android 自定义滑动容器View(2)
- ubuntu操作系统安装(二) curses
- http://zh.visualgo.net/mst.html
- perl 实现微信简版<2>
- 尝试在数据库5 中提取逻辑页() 失败。该逻辑页属于分配单元xxx而非xxx
- Android LayoutInflater详解
- 【动态规划】rual1017
- vm之youCompleteMe大坑篇
- C++静态库与动态库