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

常用方法及说明

  1. onSingleTapUp(MotionEvent e)

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

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

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

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

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

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

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

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

    • 当单击事件被确认时调用。
    • 示例用途:与 onSingleTapUp 区分,onSingleTapConfirmed 在确定不是双击时调用。
相关推荐
Kapaseker6 小时前
你不看会后悔的2025年终总结
android·kotlin
alexhilton9 小时前
务实的模块化:连接模块(wiring modules)的妙用
android·kotlin·android jetpack
专业开发者10 小时前
2020 年国际消费电子展上,蓝牙 ® 音频迎来重磅升级
音视频
ji_shuke10 小时前
opencv-mobile 和 ncnn-android 环境配置
android·前端·javascript·人工智能·opencv
专业开发者11 小时前
蓝牙低功耗音频(Bluetooth LE Audio)最具颠覆性的新功能,当属广播音频
音视频
sunnyday042612 小时前
Spring Boot 项目中使用 Dynamic Datasource 实现多数据源管理
android·spring boot·后端
幽络源小助理13 小时前
下载安装AndroidStudio配置Gradle运行第一个kotlin程序
android·开发语言·kotlin
inBuilder低代码平台13 小时前
浅谈安卓Webview从初级到高级应用
android·java·webview
豌豆学姐13 小时前
Sora2 短剧视频创作中如何保持人物一致性?角色创建接口教程
android·java·aigc·php·音视频·uniapp
白熊小北极14 小时前
Android Jetpack Compose折叠屏感知与适配
android