如何为VideoView添加滑动/快滑手势以平滑控制视频播放进度
问题原因与修复方案
你目前代码的问题集中在手势事件处理规则、进度换算逻辑两方面,按下面的步骤修改就能实现平滑滑动调整进度:
核心问题说明
onDown返回值错误:Android的手势检测器要求onDown方法返回true才会继续分发后续的滑动、长按等事件,你现在返回false会导致大部分滑动事件被直接丢弃,所以进度跳转无规律。- 单位不匹配:
distanceY的单位是像素,视频进度的单位是毫秒,直接相加会导致灵敏度极高,滑动很小的距离进度就跳非常多,看起来非常突兀。 - 缺少边界校验:如果调整后的进度小于0或者超过视频总长度,
seekTo方法会出现异常跳转。 - 事件未正常消费:
onScroll方法需要返回true表示你已经处理了当前滑动事件,避免事件被其他逻辑拦截。
修改后的完整代码
public class MainActivity extends AppCompatActivity implements View.OnTouchListener, GestureDetector.OnGestureListener { GestureDetector mgestureDetector; VideoView videoView; // 滑动灵敏度:每滑动1像素对应调整10毫秒进度,数值越大滑动越灵敏,可自行修改 private static final int SCROLL_STEP = 10; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mgestureDetector = new GestureDetector(this, this); videoView = findViewById(R.id.video_view); String videoPath = "android.resource://" +getPackageName() +"/" + R.raw.video; Uri uri = Uri.parse(videoPath); videoView.setVideoURI(uri); videoView.setOnTouchListener(this); // 可选:视频加载完成后自动播放 videoView.setOnPreparedListener(mp -> videoView.start()); } @Override public boolean onTouch(View v, MotionEvent event) { // 把触摸事件交给手势检测器处理,返回处理结果表示是否消费事件 return mgestureDetector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // 必须返回true才能接收后续的手势事件 return true; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { // 可选:单击暂停/播放 if (videoView.isPlaying()) { videoView.pause(); } else { videoView.start(); } return true; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // 视频还没加载完成时不处理滑动 if (videoView.getDuration() <= 0) { return false; } // 计算目标进度:这里减distanceY是实现手指上滑快进、下滑后退,改成加就是反过来的逻辑 long targetPos = videoView.getCurrentPosition() - (long) (distanceY * SCROLL_STEP); // 边界校验,避免进度超出合法范围 if (targetPos < 0) { targetPos = 0; } if (targetPos > videoView.getDuration()) { targetPos = videoView.getDuration(); } videoView.seekTo((int) targetPos); // 返回true表示消费了当前滑动事件 return true; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } }
调整提示
如果觉得滑动太灵敏,就把SCROLL_STEP的数值改小;如果觉得滑动太迟钝,就把数值改大即可。
内容的提问来源于stack exchange,提问作者AdhesiveWombat
相关产品推荐
相关产品推荐

