VideoView 設置 android:clickable="true" 並綁定 OnClickListener 卻無響應,原因是 VideoView 內部消費了觸摸事件 用於播放控制 (播放/暫停/進度條)。
<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" 避免搶焦點// 自定義 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 原生支持點擊切換控制器顯示/隱藏,無此煩惱。