IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android开发学习之Scroll分析 -> 正文阅读

[移动开发]Android开发学习之Scroll分析

(学习参考书:Android群英传)

一、滑动效果的产生

滑动一个View本质上就是一移动一个View,改变当前其当前所处的位置。因要实现View的滑动,就必须监听用户的触摸事件,并根据事件传入的坐标,动态且不断的改变View的坐标,从而实现View跟随用户触摸的滑动而滑动。Android中的窗口坐标体系和触控事件MotionEvent

二、Android坐标系

在Android中,将屏幕的左上角的顶点作为Android坐标系的原点,从该点向左为X轴正方向,向下为Y轴正方向。系统提供了getLocationOnScreen(intlocation[])这样的方法来获取Android坐标系中点的位置,即该视图左上角在Android坐标系中的坐标,另外在触控事件中使用getRawX()、getRawY()方法所获得的坐标同样是Android坐标系中的坐标。

三、MotionEvent

MotionEvent中封装的一些常用的事件常量,它定义了触控事件的不同类型

public static final int ACTION_DOWN = 0; 单点触摸按下动作
public static final int ACTION_UP = 1; 单点触摸离开动作
public static final int ACTION_MOVE = 2; 触摸点移动动作
public static final int ACTION_CANCEL = 3; 触摸动作取消
public static final int ACTION_OUTSIDE = 4; 触摸动作超出边界
public static final int ACTION_POINTER_DOWN = 5; 多点触摸按下动作
public static final int ACTION_POINTER_UP = 6; 多点离开动作

通常情况下,会在onTouchEvent(MotionEvent event)方法中通过event.getAction()方法来获取触控事件的类型,并使用switch-case方法来进行筛选。该代码模式基本固定:

@Override
public boolean onTouchEvent(MotionEvent event) {
    //获取当前输入点的XY坐标(视图坐标)
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            //处理输入的按下事件
            break;
        case MotionEvent.ACTION_MOVE:
            //处理输入的移动事件
            break;
        case MotionEvent.ACTION_UP:
            //处理输入的离开事件
            break; 
    }
    return true;
}

三、常用系统API

系统提供了很多方法来获取坐标值和相对距离,可以分为两个类别:
View提供的获取坐标方法:

getTop() 获取到的是View自身的顶边到父布局边界的距离
getLeft() 获取到的是View自身的左边到父布局边界的距离
getRight() 获取到的是View自身的右边到父布局边界的距离
getBottom() 获取到的是View自身的底边到父布局边界的距离

MotionEvent提供的方法:

getX() 获取点击事件距离控件左边的距离,即视图坐标
getY() 获取点击事件距离控件顶边边的距离,即视图坐标
getRawX() 获取点击事件距离控件左边的距离,即绝对坐标
getRawY() 获取点击事件距离控件顶边的距离,即绝对坐标

四、实现滑动的其中方法

实现滑动效果即修改View的坐标,其基本思想是当触摸View时,系统记下当前触摸点的坐标;当手指移动时,系统记下移动后的触摸点坐标,从而获取到相对于前一次坐标点的偏移量,并通过偏移量来修改View的坐标,这样不断重复,从而实现滑动过程。

(1)layout方法

View进行绘制时,会调用onLayout()方法来设置显示的位置。同样也可以通过修改View的left、top、right、bottom四个属性来控制View的坐标。与前面提供的代码模板一样,每次回调onTouchEvent的时候,都获取一下触摸点的坐标。
除了使用视图坐标,还可以使用绝对坐标来计算偏移量。

@Override
public boolean onTouchEvent(MotionEvent event) {
    //获取当前输入点的XY坐标(视图坐标)
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            //处理输入的按下事件
            lastX = x;
            lastY = y;
            break;
        case MotionEvent.ACTION_MOVE:
            //处理输入的移动事件
            int offsetX = x-lastX;
            int offsetY = y-lastY;
            layout(getLeft()+ offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
            break;
        case MotionEvent.ACTION_UP:
            //处理输入的离开事件
            break;
    }
    return true;
}

(2)offsetLeftAndRight( )与offsetTopAndBottom( )

这个方法相当于系统提供的一个对左右、上下移动的API的封装。当计算出偏移量后,只需要使用如下代码就可以完成View的重新布局,效果与layout方法一样:

offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);

(3)LayoutParams

LayoutParams保存了一个View的布局参数。因此可以在程序中,通过改变LayoutParams来动态修改一个布局的位置参数,从而达到改变View位置的效果。可以在程序中很方便的使用getLayoutParams()来获取一个View的LayoutParams。获取到偏移量后,就可以通过setLayoutParams来改变其LayoutParams:

LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft()+offsetX;
layoutParams.topMargin = getTop()+offsetY;
setLayoutParams(layoutParams);

(4)scrollTo和scrollBy

scrollTo(x,y)表示移动到某个具体的坐标点,scrollBy(x,y)表示移动的增量。但是这两个方法移动的是View的内容,如文本、图片;如果在ViewGroup中使用这两个方法,移动的将是其所有子View。

scrollBy(offsetX,offsetY); //移动内容
((View) getParent()).scrollBy(-offsetX,-offsetY); //移动子View

(5)Scroll类

Scroller类与scrollTo和scrollBy方法非常相似。但是Scroller类的移动实现了平滑移动的动画,而不是上述两种方法的瞬间移动。

  1. 创建一个Scroller对象实例,传入参数Context
  2. 重写computeScroll()方法,实现模拟滑动;Scroller提供了computeScrollOffset判断是否完成滑动,也提供了getCurrX()getCurrY()获取当前坐标。模板如下
@Override
public void computeScroll() {
    super.computeScroll();
    if(scroller.computeScrollOffset()){
        ((View) getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
        invalidate();
    }
}

  1. startScroll开启滑动过程:
View viewGroup = (View) getParent();
scroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY());
invalidate();
//获取View移动的距离——getScrollX()、getscrollY()
//并将偏移量设置为相反数

(6)ViewDragHelper

ViewDragHelper基本可以实现各种不同的滑动、拖放需求、因此这个方法也是各种滑动解决方法中的终极绝招。

  1. 初始化ViewDragHelper:通常定义在一个ViewGroup的内部,并使用其静态方法进行初始化:ViewDragHelper.create(this,callback);第一个参数是要监听的View,通常是需要一个ViewGroup;第二个参数是一个Callback回调,这个回调就是整个ViewDragHelper的逻辑核心。
  2. 拦截事件:重写事件拦截方法,将事件传递给ViewDragHelper进行处理。在onTouchEvent()方法中调用ViewDragHelper的processTouchEvent (event)方法
  3. 处理computeScroll():因为ViewDragHelper内部也是通过Scroll来实现平滑移动的,因此也需要重写computeScroll()方法,模板如下:
public void computeScroll() {
    if(helper.continueSettling(true)){
        ViewCompat.postInvalidateOnAnimation(this);
    }
}

  1. 处理回调Callback:最关键的Callback实现,通过下面的代码来创建一个ViewDragHelper.Callback。并通过tryCaptureView()方法指定在创建ViewDragHelper时,参数parentView中的哪一个子View可以被移动
private ViewDragHelper.Callback callback  = new ViewDragHelper.Callback() {
    @Override
    public boolean tryCaptureView(@NonNull View child, int pointerId) {
        return targetVeiw==child;
    }
};

  1. 如果需要实现基本滑动效果,必须要在回调接口中重写clampViewPositionHorizontal和clampViewPositionVertical方法。如垂直方法中的top代表垂直方向上child移动的距离,dy表示比较前一次的增量,水平方法中参数同理。
@Override
public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
    return left;
}                                                             

@Override
public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
    return top;
}

除了此对ViewDragHelper简单的应用外,ViewDragHelper.Callback中,系统定义了大量的监听事件来帮助处理各种事件:

onViewCaptured() 该事件在用户触摸到View后回调
onViewDragStateChanged() 该事件在拖拽状态改变时回调
onViewPositionChanged() 该事件在位置改变时回调
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-09 11:53:22  更:2021-09-09 11:53:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:54:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码