【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增加了额外的参数:

  • xy:View左上角的坐标,相对于父容器
  • translationXtranslationY: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类,它提供了所有方法的空实现,只需重写需要的方法。


相关推荐
Java水解13 分钟前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
砖厂小工2 小时前
用 GLM + OpenClaw 打造你的 AI PR Review Agent — 让龙虾帮你审代码
android·github
张拭心3 小时前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
张拭心3 小时前
Android 17 来了!新特性介绍与适配建议
android·前端
SimonKing4 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean4 小时前
Jackson View Extension Spring Boot Starter
java·后端
Kapaseker5 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴6 小时前
Android17 为什么重写 MessageQueue
android
Seven976 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林55115 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java