自定义 View 可以播放一段视频

请实现一个自定义 View 的核心代码,核心要求可以响应如下事件:

// - 要求自定义 View 可以播放一段视频

/ - 在 view 左侧区域上下滑动,可以提高减少音量 /

/ - 在 view 右侧区域上下滑动可以提高减少屏幕亮度

// - 在 view 左右滑动可以快进/快退播放 // - 在 view 区域点击屏幕可以暂停/继续播放

使用 VideoView 实现自定义 View

复制代码
public class CustomVideoView extends FrameLayout {
    private VideoView videoView;
    private GestureDetector gestureDetector;
    private float initialTouchX, initialTouchY;
    private int screenWidth, screenHeight;
    private AudioManager audioManager;
    private WindowManager.LayoutParams layoutParams;
    private float maxVolume;

    public CustomVideoView(Context context) {
        super(context);
        init(context);
    }

    public CustomVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CustomVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        // 初始化 VideoView
        videoView = new VideoView(context);
        addView(videoView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        // 获取屏幕宽高
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        screenWidth = size.x;
        screenHeight = size.y;

        // 初始化音频管理器
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

        // 获取当前窗口参数以调整亮度
        layoutParams = ((Activity) context).getWindow().getAttributes();

        // 初始化手势检测器
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                if (videoView.isPlaying()) {
                    videoView.pause();
                } else {
                    videoView.start();
                }
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                float deltaX = e2.getX() - initialTouchX;
                float deltaY = e2.getY() - initialTouchY;

                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    // 左右滑动快进/快退
                    if (deltaX > 0) {
                        // 快进
                        videoView.seekTo(videoView.getCurrentPosition() + 10000);
                    } else {
                        // 快退
                        videoView.seekTo(videoView.getCurrentPosition() - 10000);
                    }
                } else {
                    if (initialTouchX < screenWidth / 2) {
                        // 左侧区域,上下滑动调整音量
                        if (deltaY > 0) {
                            // 降低音量
                            audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0);
                        } else {
                            // 提高音量
                            audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0);
                        }
                    } else {
                        // 右侧区域,上下滑动调整亮度
                        if (deltaY > 0) {
                            // 降低亮度
                            layoutParams.screenBrightness = Math.max(layoutParams.screenBrightness - 0.1f, 0.1f);
                        } else {
                            // 提高亮度
                            layoutParams.screenBrightness = Math.min(layoutParams.screenBrightness + 0.1f, 1.0f);
                        }
                        ((Activity) getContext()).getWindow().setAttributes(layoutParams);
                    }
                }

                return true;
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        initialTouchX = event.getX();
        initialTouchY = event.getY();
        return gestureDetector.onTouchEvent(event);
    }

    public void setVideoPath(String path) {
        videoView.setVideoPath(path);
    }

    public void start() {
        videoView.start();
    }

    public void pause() {
        videoView.pause();
    }

    public boolean isPlaying() {
        return videoView.isPlaying();
    }

    public void seekTo(int millis) {
        videoView.seekTo(millis);
    }
}

GestureDetector.SimpleOnGestureListener 是 GestureDetector 的一个内部类,提供了各种手势检测回调方法。你可以通过继承 SimpleOnGestureListener 并重写它的方法来定制手势处理逻辑。下面是 SimpleOnGestureListener 内常用方法的详细说明及示例代码。

常用方法及说明

  1. onSingleTapUp(MotionEvent e)

    • 当用户轻轻点击屏幕后松开时调用。
    • 返回 true 表示该事件被处理。
    • 示例用途:处理单击事件。
  2. onLongPress(MotionEvent e)

    • 当用户长按屏幕时调用。
    • 示例用途:处理长按事件,如显示上下文菜单。
  3. onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

    • 当用户在屏幕上滑动时调用。
    • 参数 e1 表示滑动的起点,e2 表示滑动的终点,distanceX 和 distanceY 分别表示滑动的距离。
    • 示例用途:处理滚动事件,如滚动列表。
  4. onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

    • 当用户快速滑动并松开时调用。
    • 参数 e1 和 e2 表示滑动的起点和终点,velocityX 和 velocityY 分别表示滑动的速度。
    • 示例用途:处理快速滑动事件,如切换页面。
  5. onShowPress(MotionEvent e)

    • 当用户按下屏幕但还未松开或拖动时调用。
    • 示例用途:处理按压显示效果。
  6. onDown(MotionEvent e)

    • 当用户按下屏幕时调用。
    • 返回 true 表示该事件被处理。
    • 示例用途:通常用来初始化一些状态。
  7. onDoubleTap(MotionEvent e)

    • 当用户双击屏幕时调用。
    • 示例用途:处理双击事件,如放大图片。
  8. onDoubleTapEvent(MotionEvent e)

    • 当双击手势发生的过程中,按下、移动和抬起事件的任何一次调用。
    • 示例用途:处理双击过程中的事件。
  9. onSingleTapConfirmed(MotionEvent e)

    • 当单击事件被确认时调用。
    • 示例用途:与 onSingleTapUp 区分,onSingleTapConfirmed 在确定不是双击时调用。
相关推荐
独隅3 小时前
Claude API 实战教程:从入门到完整项目
android·java·数据库·claude·claude code
且随疾风前行.7 小时前
Paint Cavans高级绘制:[一]Paint画笔高级应用
android·ui
feasibility.8 小时前
不装Claude Code,WorkBuddy也能做视频,Remotion skill告别抽卡(含安装与使用)
人工智能·aigc·音视频·agi·skill·remotion·workbuddy
郑州光合科技余经理9 小时前
同城小程序开发:同一笔单在用户端和商家端各显示到哪
android·java·开发语言·前端·后端·uni-app·php
pigdreams10 小时前
Google 官方 Android CLI:让AI直接读布局结构而不是用adb截图验证
android·人工智能·adb
AI视频工具指南11 小时前
一个人能做 AI 短剧吗?实际要做哪些决定
人工智能·aigc·音视频·1024程序员节
开开心心就好12 小时前
本地文件搜索工具,双击Ctrl就能呼出搜索
java·服务器·前端·支持向量机·ffmpeg·音视频·模拟退火算法
小豆庄12 小时前
视频脱敏引擎的追踪难题:转场误判定、ID撞号和淡入窗口
qt·算法·目标检测·音视频·视频·敏捷流程
hunterandroid12 小时前
[Android 从零到一] Glide 图片加载原理:三级缓存、生命周期绑定与内存优化
android
法的空间13 小时前
AI 编程时代,为什么 Dart 分析会拖慢大型项目的开发
android·flutter·ios