【Android】View 的基础知识

【Android】View 的基础知识

1. 什么是 View?

View 是 Android 中所有UI组件的基础类。它表示屏幕上的一个矩形区域,负责绘制内容和处理用户交互事件。所有的 UI 组件(如按钮、文本框等)都是 View 的子类,而 ViewGroup 是一种特殊的 View,它可以包含其他 View 或 ViewGroup,用于定义布局结构。View 的主要功能包括绘制内容、响应用户事件以及与父容器的交互。它可以显示文本、图片、视频等内容,并处理触摸、点击等操作。

2. View 的位置参数

View的位置主要由四个参数决定,这些参数都是相对其父容器的坐标:

  • left:View左边到父容器左边的距离
  • top:View顶部到父容器顶部的距离
  • right:View右边到父容器左边的距离
  • bottom:View底部到父容器顶部的距离

在Android中,x轴和y轴的正方向分别为右和下。

获取View宽高的方法:

java 复制代码
// 获取View的宽度
int width = view.getRight() - view.getLeft();
// 或者使用简便方法
int width = view.getWidth();

// 获取View的高度
int height = view.getBottom() - view.getTop();
// 或者使用简便方法
int height = view.getHeight();

从Android 3.0开始,View增加了额外的参数:

  • x 和y:View左上角的坐标,相对于父容器
  • translationX 和translationY:View左上角相对于父容器的偏移量

它们之间的关系为:

java 复制代码
x = left + translationX
y = top + translationY

3. MotionEvent 和 TouchSlop

3.1 MotionEvent

MotionEvent是触摸事件类,包含了触摸动作、位置等信息。常见的触摸事件类型包括:

  • ACTION_DOWN:手指按下屏幕
  • ACTION_MOVE:手指在屏幕上移动
  • ACTION_UP:手指从屏幕抬起
  • ACTION_CANCEL:触摸事件被取消

获取触摸点坐标的方法:

java 复制代码
@Override
public boolean onTouchEvent(MotionEvent event) {
    // 获取相对于当前View的x坐标
    float x = event.getX();
    // 获取相对于当前View的y坐标
    float y = event.getY();
    
    // 获取相对于屏幕的原始坐标
    float rawX = event.getRawX();
    float rawY = event.getRawY();
    
    return true;
}

3.2 TouchSlop

TouchSlop是系统识别的被认为滑动的最小距离,小于这个距离的移动不会被识别为滑动。这个常量由设备制造商定义,不同设备可能不同。

获取TouchSlop的方法:

java 复制代码
ViewConfiguration.get(context).getScaledTouchSlop()

在实际开发中,处理滑动时应考虑TouchSlop,以避免过于敏感的滑动检测:

java 复制代码
private int mTouchSlop;
private float mLastX;

public MyView(Context context) {
    super(context);
    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mLastX = x;
            break;
        case MotionEvent.ACTION_MOVE:
            float deltaX = Math.abs(x - mLastX);
            if (deltaX > mTouchSlop) {
                // 这是一个有效的滑动
            }
            break;
    }
    return true;
}

4. VelocityTracker、GestureDetector

4.1 VelocityTracker

VelocityTracker用于追踪手指滑动的速度,包括水平和垂直方向的速度。速度的计算单位通常是"每秒移动的像素数(px/s)"。

使用VelocityTracker的基本步骤:

java 复制代码
// 在View的onTouchEvent方法中
private VelocityTracker mVelocityTracker;

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (mVelocityTracker == null) {
        mVelocityTracker = VelocityTracker.obtain();
    }
    mVelocityTracker.addMovement(event);
    
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            // 处理按下事件
            break;
        case MotionEvent.ACTION_MOVE:
            // 处理移动事件
            break;
        case MotionEvent.ACTION_UP:
            // 计算速度
            mVelocityTracker.computeCurrentVelocity(1000); // 计算单位:1000ms内的像素数
            float xVelocity = mVelocityTracker.getXVelocity();
            float yVelocity = mVelocityTracker.getYVelocity();
            
            // 使用速度值进行相关处理
            
            // 回收VelocityTracker
            if (mVelocityTracker != null) {
                mVelocityTracker.recycle();
                mVelocityTracker = null;
            }
            break;
    }
    return true;
}

注意:获取速度值前必须先调用computeCurrentVelocity()方法,参数表示时间单位(毫秒)。

4.2 GestureDetector

GestureDetector用于辅助检测用户的单击、长按、滑动、双击等手势。它简化了复杂手势的识别过程。

使用GestureDetector的基本步骤:

  1. 创建GestureDetector实例
  2. 实现GestureDetector.OnGestureListener接口
  3. 在View的onTouchEvent()方法中转发触摸事件
java 复制代码
public class MyView extends View implements GestureDetector.OnGestureListener, 
        GestureDetector.OnDoubleTapListener {
    
    private GestureDetector mGestureDetector;
    
    public MyView(Context context) {
        super(context);
        mGestureDetector = new GestureDetector(context, this);
        // 解决长按后无法拖动的问题
        mGestureDetector.setIsLongpressEnabled(false);
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }
    
    // OnGestureListener方法
    @Override
    public boolean onDown(MotionEvent e) {
        // 按下动作
        return true; // 必须返回true,否则后续事件不会传递
    }
    
    @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) {
        // 滚动操作
        return false;
    }
    
    @Override
    public void onLongPress(MotionEvent e) {
        // 长按事件
    }
    
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        // 快速滑动后抬起
        return false;
    }
    
    // OnDoubleTapListener方法
    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        // 严格的单击确认(非双击中的第一次点击)
        return false;
    }
    
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        // 双击事件
        return false;
    }
    
    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        // 双击事件中的ACTION_DOWN、ACTION_MOVE和ACTION_UP
        return false;
    }
}

如果不需要处理所有手势,可以使用SimpleOnGestureListener类,它提供了所有方法的空实现,只需重写需要的方法。


相关推荐
Xudde.8 分钟前
CVE-2017-9993漏洞复现
笔记·学习·安全·web安全
程序员zgh25 分钟前
C++ erase() 函数用法
c语言·开发语言·c++·学习
mlidongfeng28 分钟前
【学习】 NVIDIA CFT(Compute Fabric Transport)特性分析
人工智能·学习·fabric
FakeOccupational30 分钟前
【电路笔记 STM32】Cortex-M7 UART 中断模式(串口接收中断+串口空闲中断)
笔记·stm32·单片机
小蒜学长39 分钟前
基于Java的公司采购系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·公司采购系统
lee_tianbai40 分钟前
Java SSM 电影票预定系统|完整前后端项目,开箱即用(源码分享)
java·开发语言·数据库
小李不想当小白41 分钟前
USART串口协议(STM32标准库学习笔记)
经验分享·笔记·stm32·单片机·嵌入式硬件·学习
小坏讲微服务1 小时前
Spring Boot 4 新特性全解析:从上手到生产实战
java·spring boot·后端·架构·springboot4
砚底藏山河1 小时前
python量化入门:多周期数据对齐统一时间轴
java·数据库·python·金融·maven
集智飞行1 小时前
解决mavros2 ros2版本cpu占用高的问题
java·服务器·前端