Android自定义view-弹性ScrollView(下)
来源:互联网 发布:ni 6229数据手册 编辑:程序博客网 时间:2024/06/02 18:03
前言:
继上篇博客Android自定义view-弹性ScrollView(上)介绍的一种实现弹性ScrollView的方法后,有没有觉得处理touch事件太过于麻烦了好吧,我也觉得麻烦,决定就用现在比较火的ViewDragHelper去实现事件的控制。这篇博文的重点不在于ViewDragHelper的介绍,而是利用ViewDragHelper,所以会在全篇穿插着介绍ViewDragHelper,至于详细的介绍,会有机会写博客来介绍的,当然你也可以多看google官方的文档,那可是权威。
正文:
构造和准备工作都和前篇的一样,没什么区别,最主要的是在dispatchTouchEvent(MotionEvent ev) 上,我们把事件的控制权交给了ViewDragHelper:
@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {boolean shouldInterceptTouchEvent = mViewDragHelper.shouldInterceptTouchEvent(ev);return shouldInterceptTouchEvent;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {mViewDragHelper.processTouchEvent(ev);return true;}通过mViewDragHelper.shouldInterceptTouchEvent(ev)去拦截分发touch事件,通过mViewDragHelper.processTouchEvent(ev)来处理touch事件。至于怎么处理的,目前你不需要清楚,肯定比你写的事件处理要全面。
现在我们把主要的精力放在如何去ViewDragHelper上。
mViewDragHelper = ViewDragHelper.create(this, 1.0f, new Callback() {// 控制移动的垂直范围@Overridepublic int clampViewPositionVertical(View child, int top, int dy) {return top;}// 捕获的childView@Overridepublic boolean tryCaptureView(View child, int pointerId) {return child == contentView;}/** * view位置改变时 */@Overridepublic void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {canPullDown = top > originalRect.top ? true : false;canPullUp = top < -1 * (originalRect.height() - getHeight()) ? true : false;}/** * 手指释放时view回到初始状态 */@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {if (releasedChild == contentView) {if (canPullDown) {mViewDragHelper.settleCapturedViewAt(originalRect.left, originalRect.top);}if (canPullUp) {mViewDragHelper.settleCapturedViewAt(originalRect.left, -(originalRect.height() - getHeight()));}invalidateView();}}});诺,这是我们的主要逻辑代码,和之前的相比是不是特别简单清晰。对,就是这么简单。
对于ViewDragHelper对象的获取我们是在onFinishInflate()中获取的,为什么不放在构造器里呢?自己去思考一下吧。
我们不难发现ViewDragHelper的callback回调接口中有很多方法
• onViewDragStateChanged
当ViewDragHelper状态发生变化时回调(IDLE,DRAGGING,SETTING[自动滚动时])
• onViewPositionChanged
当captureview的位置发生改变时回调
• onViewCaptured
当captureview被捕获时回调
• onViewReleased
• onEdgeTouched
当触摸到边界时回调。
• onEdgeLock
true的时候会锁住当前的边界,false则unLock。
• onEdgeDragStarted
• getOrderedChildIndex
改变同一个坐标(x,y)去寻找captureView位置的方法。(具体在:findTopChildUnder方法中)
• getViewHorizontalDragRange
• getViewVerticalDragRange
• tryCaptureView
• clampViewPositionHorizontal
clampViewPositionVertical
这里有个注意点,在onViewReleased方法中,调用mViewDragHelper.settleCapturedViewAt(originalRect.left, originalRect.top);此方法需要重写
@Overridepublic void computeScroll() {if (mViewDragHelper.continueSettling(true)) {invalidateView();}}大家可以试试把这个方法不复写,会不会有效果。还有一点就是invalidateView()是什么方法?怎么没有这个方法,哈哈,这是自己写的一个方法,主要是重绘view的,我们进行了一定的判断。
// 重绘viewprivate void invalidateView() {if (Looper.getMainLooper() == Looper.myLooper()) {invalidate();} else {postInvalidate();}}
有人一定有疑惑,为什么要这么写,其实大家不妨去查一下invalidate和postInvalidate的区别就明白了,你一定会收获另一个知识点的。
贴一下全部代码:
VHFlexibleScrollView.java:
package com.beyole.view;import android.content.Context;import android.graphics.Rect;import android.os.Looper;import android.support.v4.widget.ViewDragHelper;import android.support.v4.widget.ViewDragHelper.Callback;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.ScrollView;public class VHFlexibleScrollView extends ScrollView {private static final String TAG = "FLEXIBLESCROLLVIEW";// ScrollView唯一的一个子viewprivate View contentView;// 用于记录正常的布局位置private Rect originalRect = new Rect();// 记录手指按下时是否可以下拉private boolean canPullDown = false;// 记录手指按下时是否可以上拉private boolean canPullUp = false;private ViewDragHelper mViewDragHelper;public VHFlexibleScrollView(Context context) {this(context, null);}public VHFlexibleScrollView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public VHFlexibleScrollView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}/** * 在加载完xml后获取唯一的一个childview */@Overrideprotected void onFinishInflate() {if (getChildCount() > 0) {// 获取第一个childviewcontentView = getChildAt(0);mViewDragHelper = ViewDragHelper.create(this, 1.0f, new Callback() {// 控制移动的垂直范围@Overridepublic int clampViewPositionVertical(View child, int top, int dy) {return top;}// 捕获的childView@Overridepublic boolean tryCaptureView(View child, int pointerId) {return child == contentView;}/** * view位置改变时 */@Overridepublic void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {canPullDown = top > originalRect.top ? true : false;canPullUp = top < -1 * (originalRect.height() - getHeight()) ? true : false;}/** * 手指释放时view回到初始状态 */@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {if (releasedChild == contentView) {if (canPullDown) {mViewDragHelper.settleCapturedViewAt(originalRect.left, originalRect.top);}if (canPullUp) {mViewDragHelper.settleCapturedViewAt(originalRect.left, -(originalRect.height() - getHeight()));}invalidateView();}}});}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if (contentView == null)return;// scrollview唯一的一个子view的位置信息,这个位置信息在整个生命周期中保持不变originalRect.set(contentView.getLeft(), contentView.getTop(), contentView.getRight(), contentView.getBottom());}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {boolean shouldInterceptTouchEvent = mViewDragHelper.shouldInterceptTouchEvent(ev);return shouldInterceptTouchEvent;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {mViewDragHelper.processTouchEvent(ev);return true;}@Overridepublic void computeScroll() {if (mViewDragHelper.continueSettling(true)) {invalidateView();}}// 重绘viewprivate void invalidateView() {if (Looper.getMainLooper() == Looper.myLooper()) {invalidate();} else {postInvalidate();}}}MainActivity.java:
package com.beyole.flexiblescrollview;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}}activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.beyole.view.VHFlexibleScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:layout_width="match_parent" android:layout_height="200.0dip" android:scaleType="fitXY" android:src="@drawable/img1" /> <ImageView android:layout_width="match_parent" android:layout_height="200.0dip" android:scaleType="fitXY" android:src="@drawable/img2" /> <ImageView android:layout_width="match_parent" android:layout_height="200.0dip" android:scaleType="fitXY" android:src="@drawable/img3" /> </LinearLayout> </com.beyole.view.VHFlexibleScrollView></RelativeLayout>
下载地址:http://download.csdn.net/detail/smarticeberg/9439380
Github地址:https://github.com/xuejiawei/beyole_FlexibleScrollView,欢迎fork or star
题外话:
android交流群:279031247(广告勿入)
新浪微博:SmartIceberg
- Android自定义view-弹性ScrollView(下)
- Android自定义view-弹性ScrollView(上)
- Android自定义弹性ScrollView
- android自定义弹性ScrollVIew ,十分简单!
- 自定义ScrollView实现弹性ScrollView
- 自定义弹性的ScrollView
- 自定义弹性的ScrollView
- 自定义scrollview弹性布局
- Android 弹性ScrollView
- android 弹性ScrollView
- Android 弹性ScrollView
- 自定义View--弹性小球
- 自定义ScrollView实现弹性效果
- Android的ScrollView中添加自定义View
- Android自定义View--ScrollView实现回弹效果
- android 弹性ScrollView(已优化)
- Android上实现弹性ScrollView
- android 弹性ScrollView(已优化)
- 常用C字符串操作函数
- pc进入android手机shell的root权限(su: not found)
- 动态规划学习笔记一
- CentOS7安装iptables防火墙
- android跨进程启动service
- Android自定义view-弹性ScrollView(下)
- ionic android版APP tab
- iOS视图pop出栈
- popupwindow全屏幕显示被状态栏挡住如何解决+Android获取状态栏高度
- JS交互(js调oc,oc调js,js,oc互调,第三方库WebViewJavascriptBridge)
- FastDFS命令
- Spring-Task 创建定时任务
- React复合组件
- logback.xml 常用配置详解