首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android VideoView 點擊事件不響應:觸摸事件被內部消費,用 FrameLayout 包裹轉發

     編輯:程式設計綜合問答

VideoView 設置 android:clickable="true" 並綁定 OnClickListener 卻無響應,原因是 VideoView 內部消費了觸摸事件 用於播放控制 (播放/暫停/進度條)。

解決方案:FrameLayout 包裹層轉發點擊

<FrameLayout
    android:id="@+id/video_container"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:clickable="true"
    android:focusable="true">

    <VideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="false"
        android:clickable="false" />
</FrameLayout>
FrameLayout container = findViewById(R.id.video_container);
VideoView videoView = findViewById(R.id.video_view);

container.setOnClickListener(v -> {
    // 這裡處理點擊:切換播放/暫停、顯示控制器等
    if (videoView.isPlaying()) {
        videoView.pause();
    } else {
        videoView.start();
    }
});

// 長按、雙擊同理
container.setOnLongClickListener(v -> {
    // 進入全屏等
    return true;
});

原理解析

  • VideoView 繼承 SurfaceView,內部有 MediaController 處理觸摸
  • OnTouchEvent 返回 true 表示消費事件,不再向上傳遞
  • 外層 FrameLayout 不消費觸摸,OnClickListener 正常觸發
  • VideoView 設置 focusable="false" clickable="false" 避免搶焦點

進階:同時支持 VideoView 原生控制器與自定義點擊

// 自定義 FrameLayout 分發觸摸
public class VideoContainer extends FrameLayout {
    private VideoView videoView;
    private GestureDetector gestureDetector;
    
    public VideoContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
        setClickable(true);
        setFocusable(true);
        gestureDetector = new GestureDetector(context, new GestureListener());
    }
    
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // 單擊、雙擊由容器處理,滑動傳給 VideoView 內部控制器
        if (gestureDetector.onTouchEvent(ev)) return true;
        return super.onInterceptTouchEvent(ev);
    }
    
    class GestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            // 單擊切換播放
            togglePlay();
            return true;
        }
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            // 雙擊全屏
            enterFullscreen();
            return true;
        }
    }
}

替代方案對比

方案優點缺點
FrameLayout 包裹 (推薦)簡單、不侵入、兼容性好需額外 View 層級
繼承 VideoView 重寫 onTouchEvent邏輯內聚易破壞內部播放控制、版本兼容風險
用 TextureView + MediaPlayer 自己寫完全可控工作量大、易踩坑 (生命周期、旋轉、DRM)
ExoPlayer + PlayerView現代、功能強、官方推薦依賴庫大、API 不同

簡單項目用 FrameLayout 包裹 最省事;新項目建議直接上 ExoPlayer,PlayerView 原生支持點擊切換控制器顯示/隱藏,無此煩惱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved