视频播放器的屏幕手势适配

该博客介绍了如何在视频播放器中实现屏幕手势适配,包括左右滑动调节进度,左侧上下滑动调节亮度,右侧上下滑动调节音量。在滑动过程中,播放器暂停,停止滑动后继续播放。点击屏幕则显示/隐藏控制栏。通过设置View.OnTouchListener并转换成特定的回调接口,确保手势识别的准确性,并防止手势冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

视频播放器的屏幕手势适配

做视频播放器的时候,经常需要对于屏幕的不同手势操作进行适配。

一般来说,是左右滑动可以调节进度,左侧上下滑动调节亮度,右侧上下滑动调节声音。一般调节进度的时候还有个需求就是一边滑动一边可以预览画面,所以正在滑动的时候,其实视频播放器是暂停状态,停止滑动的时候,播放器继续播放。另外,点击而不滑动会显示/隐藏控制栏。

按照这个需求,实际上应该是把View.OnTouchListener传过来的坐标和事件,转换成以下的回调:

  1. 左右滑动
  2. 左右滑动结束
  3. 左侧上下滑动
  4. 右侧上下滑动
  5. 点击

其实除了这些,还有些潜在的需求,比如一旦确定一个滑动事件,在手离开屏幕前是不能改变的。比如,一旦做出了左右滑动的判断开始调节进度,在手离开屏幕结束这次事件前,是不能再判断为上下滑动的。

预定了这些目标后,就可以做一个适配,获取承载SurfaceView或TextureView的父布局。设置其OnTouchListener为这里的VideoPlayerTouchAdapter对象,然后匿名实现其回调接口VideoPlayerTouchListener,就可以适配我们定的新回调了。

代码参考

import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by Jax on 2016/10/24.
 */
public class VideoPlayerTouchAdapter implements View.OnTouchListener {

    private static final String TAG = "VideoPlayerTouchAdapter";
    private boolean isClick;
    private float xBegin;
    private float yBegin;
    // 有效移动距离
    final float VALID_MOVE_DISTANCE = 50;
    private int moveDirection = 0;
    final int MOVE_DIRECTION_HORIZONTAL = 1;
    final int MOVE_DIRECTION_VERTICAL_LEFT = 2;
    final int MOVE_DIRECTION_VERTICAL_RIGHT = 3;

    // 事件回调
    private VideoPlayerTouchListener listener;

    public VideoPlayerTouchAdapter(VideoPlayerTouchListener listener) {
        assert listener != null;
        this.listener = listener;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "ACTION_DOWN");
            isClick = true;
            moveDirection = 0;
            xBegin = event.getX();
            yBegin = event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            float horizontalMoveDistance = event.getX() - xBegin;
            float verticalMoveDistance = event.getY() - yBegin;
            Log.i(TAG, "ACTION_MOVE " + horizontalMoveDistance + "," + verticalMoveDistance);
            if (moveDirection == 0 && (Math.pow(horizontalMoveDistance, 2) + Math.pow(verticalMoveDistance, 2) < Math
                    .pow(VALID_MOVE_DISTANCE, 2))) {
                // 移动距离小于有效距离,判断为点击事件
                break;
            }
            // 判断不是点击事件
            isClick = false;
            // 判断位移方向,优先执行左右位移
            int nextMoveDirection;
            if (Math.abs(horizontalMoveDistance) > VALID_MOVE_DISTANCE) {
                // 左右
                nextMoveDirection = MOVE_DIRECTION_HORIZONTAL;
            } else {
                if (isLeftSide(xBegin, v.getWidth())) {
                    // 左侧上下滑动,调节明暗
                    nextMoveDirection = MOVE_DIRECTION_VERTICAL_LEFT;
                } else {
                    // 右侧上下滑动,调节声音
                    nextMoveDirection = MOVE_DIRECTION_VERTICAL_RIGHT;
                }
            }
            move(nextMoveDirection, horizontalMoveDistance, verticalMoveDistance);
            // 如果发生位移,则更新开始计算的位置
            xBegin = event.getX();
            yBegin = event.getY();
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "ACTION_UP");
            if (isClick) {
                listener.onClick();
                v.performClick();
            } else if (moveDirection == MOVE_DIRECTION_HORIZONTAL) {
                listener.onHorizontalMoveEnd();
            }
            break;
        }
        return true;
    }

    private boolean isLeftSide(float x, float playerWidth) {
        return x < playerWidth / 2;
    }

    private void move(int nextMoveDirection, float horizontalMoveDistance, float verticalMoveDistance) {
        // 如果未确定方向,则按照nextMoveDirection确定方向,如果已经确定方向,则按照之前确定的方向
        if (this.moveDirection == 0) {
            this.moveDirection = nextMoveDirection;
        }
        switch (this.moveDirection) {
        case MOVE_DIRECTION_HORIZONTAL:
            listener.onHorizontalMove(horizontalMoveDistance);
            break;
        case MOVE_DIRECTION_VERTICAL_LEFT:
            listener.onLeftVerticalMove(verticalMoveDistance);
            break;
        case MOVE_DIRECTION_VERTICAL_RIGHT:
            listener.onRightVerticalMove(verticalMoveDistance);
            break;
        }
    }

    interface VideoPlayerTouchListener {
        // 大于0则向右滑动
        void onHorizontalMove(float horizontalMoveDistance);

        // 大于0则向下滑动
        void onLeftVerticalMove(float verticalMoveDistance);

        void onRightVerticalMove(float verticalMoveDistance);

        // 判断点击
        void onClick();

        // 判断横向位移已经结束
        void onHorizontalMoveEnd();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值