PlayerGestureListener.java 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. package com.edufound.mobile.util;
  2. import android.content.Context;
  3. import android.util.DisplayMetrics;
  4. import android.view.GestureDetector;
  5. import android.view.MotionEvent;
  6. import android.view.ViewConfiguration;
  7. import android.view.WindowManager;
  8. import java.lang.ref.WeakReference;
  9. /**
  10. * 播放器常用手势监听:单击、双击、横向滑动、左右两边边竖向滑动(亮度和声音)
  11. */
  12. public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListener {
  13. private WeakReference<VideoGestureListener> listener;
  14. private int screenWidth, centerW;
  15. //播放器View的长宽DP
  16. private float dpVideoWidth, dpVideoHeight;
  17. private ScrollMode scrollMode = ScrollMode.NONE;
  18. private long timeStamp;
  19. private int mTouchSlop;
  20. private int scrollRatio = 1; //快进的比率,速度越快,值越大
  21. private int preDpVideoDuration = 0; //每一dp,快进的时长,ms
  22. private float density;
  23. private int totalDuration = 0; //单次快进快退累计值
  24. private float leftTBValue = 0; //单次左边累计值(一般是亮度)
  25. private float rightTBValue = 0; //单次右边累计值(一般是声音)
  26. public PlayerGestureListener(VideoGestureListener listener, Context context) {
  27. this.listener = new WeakReference<>(listener);
  28. WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  29. DisplayMetrics outMetrics = new DisplayMetrics();
  30. wm.getDefaultDisplay().getMetrics(outMetrics);
  31. screenWidth = outMetrics.widthPixels;
  32. centerW = screenWidth / 2;
  33. mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
  34. density = context.getResources().getDisplayMetrics().density;
  35. }
  36. //设置播放器SurfaceView的宽高
  37. public void setVideoWH(int w, int h) {
  38. dpVideoWidth = w / density;
  39. dpVideoHeight = h / density;
  40. //默认基础总共2分钟,代表的意义:从屏幕一边滑动到另一边,总共可以快进2分钟
  41. preDpVideoDuration = (int) (2 * 60 * 1000 / dpVideoWidth);
  42. }
  43. @Override
  44. public boolean onDown(MotionEvent e) {
  45. scrollMode = ScrollMode.NONE;
  46. timeStamp = System.currentTimeMillis();
  47. totalDuration = 0;
  48. // leftTBValue = 0;
  49. // rightTBValue = 0;
  50. if (listener.get() != null) {
  51. listener.get().onGestureDown();
  52. }
  53. return true;
  54. }
  55. @Override
  56. public boolean onSingleTapUp(MotionEvent e) {
  57. return super.onSingleTapUp(e);
  58. }
  59. @Override
  60. public void onShowPress(MotionEvent e) {
  61. super.onShowPress(e);
  62. }
  63. @Override
  64. public void onLongPress(MotionEvent e) {
  65. super.onLongPress(e);
  66. }
  67. @Override
  68. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  69. long time = System.currentTimeMillis();
  70. distanceX = -distanceX;
  71. distanceY = -distanceY;
  72. float dpX = distanceX / density;
  73. float dpY = distanceY / density;
  74. updateScrollRatio(dpX, time - timeStamp);
  75. timeStamp = time;
  76. float xDiff = e2.getX() - e1.getX();
  77. float yDiff = e2.getY() - e1.getY();
  78. if (scrollMode == ScrollMode.NONE) {
  79. //横向滑动
  80. if (Math.abs(xDiff) > mTouchSlop) {
  81. scrollMode = ScrollMode.HORIZONTAL_S;
  82. updateVideoTime((int) (preDpVideoDuration * xDiff));
  83. }
  84. //纵向滑动
  85. else if (Math.abs(yDiff) > mTouchSlop) {
  86. if (e1.getX() < centerW) {
  87. scrollMode = ScrollMode.LEFT_TB;
  88. } else {
  89. scrollMode = ScrollMode.RIGHT_TB;
  90. }
  91. }
  92. }
  93. //快进快退
  94. else if (scrollMode == ScrollMode.HORIZONTAL_S) {
  95. updateVideoTime((int) (preDpVideoDuration * scrollRatio * dpX));
  96. } else if (scrollMode == ScrollMode.LEFT_TB) {
  97. updateVideoLeftTB(dpY / dpVideoHeight);
  98. } else if (scrollMode == ScrollMode.RIGHT_TB) {
  99. updateVideoRightTB(dpY / dpVideoHeight);
  100. }
  101. return true;
  102. }
  103. @Override
  104. public boolean onDoubleTap(MotionEvent e) {
  105. if (listener.get() != null) {
  106. listener.get().onGestureDoubleClick();
  107. }
  108. //双击事件
  109. return super.onDoubleTap(e);
  110. }
  111. @Override
  112. public boolean onDoubleTapEvent(MotionEvent e) {
  113. return super.onDoubleTapEvent(e);
  114. }
  115. @Override
  116. public boolean onSingleTapConfirmed(MotionEvent e) {
  117. if (listener.get() != null) {
  118. listener.get().onGestureSingleClick();
  119. }
  120. //单击事件,在双击事件发生时不会产生这个事件,所以用这个回调作为播放器单击事件
  121. return super.onSingleTapConfirmed(e);
  122. }
  123. /***
  124. * 根据滑动速度更新速度比率值,这样可以在滑动速率较快时,快进的速度也会变快,可以根据需要调整
  125. * 根据实验,正常速度一般在10~40dp/s
  126. * @param dpX:横向滑动距离 dp
  127. * @param duration:时间间隔 ms
  128. */
  129. private void updateScrollRatio(float dpX, long duration) {
  130. int ratio = (int) ((Math.abs(dpX) / duration) * 1000);
  131. if (ratio < 20) {
  132. scrollRatio = 1;
  133. } else if (ratio < 40) {
  134. scrollRatio = 3;
  135. } else if (ratio < 70) {
  136. scrollRatio = 7;
  137. } else if (ratio < 100) {
  138. scrollRatio = 13;
  139. } else if (ratio < 300) {
  140. scrollRatio = 18;
  141. } else if (ratio < 500) {
  142. scrollRatio = 24;
  143. } else if (ratio < 800) {
  144. scrollRatio = 31;
  145. } else if (ratio < 1000) {
  146. scrollRatio = 40;
  147. } else {
  148. scrollRatio = 60;
  149. }
  150. }
  151. //累积快进进度,totalDuration:当前快进的总值,负值代表是要快退
  152. private void updateVideoTime(int duration) {
  153. totalDuration += duration;
  154. if (listener.get() != null) {
  155. listener.get().onGestureUpdateVideoTime(totalDuration);
  156. }
  157. }
  158. //累积亮度
  159. private void updateVideoLeftTB(float ratio) {
  160. leftTBValue += ratio;
  161. if (listener.get() != null) {
  162. listener.get().onGestureLeftTB(leftTBValue);
  163. }
  164. }
  165. //累积声音
  166. private void updateVideoRightTB(float ratio) {
  167. rightTBValue += ratio;
  168. if (listener.get() != null) {
  169. listener.get().onGestureRightTB(rightTBValue);
  170. }
  171. }
  172. public interface VideoGestureListener {
  173. /***
  174. * 手指在Layout左半部上下滑动时候调用,一般是亮度手势
  175. * 从View底部滑动到顶部,代表从0升到1
  176. * @param ratio:0-1 之间,1代表最亮,0代表最暗
  177. */
  178. void onGestureLeftTB(float ratio);
  179. /***
  180. * 手指在Layout右半部上下滑动时候调用,一般是音量手势
  181. * 从View底部滑动到顶部,代表从0升到1
  182. * @param ratio:0-1 之间,1代表音量最大,0代表音量最低
  183. */
  184. void onGestureRightTB(float ratio);
  185. /**
  186. * @param duration :快进快退,大于0快进,小于0快退
  187. */
  188. void onGestureUpdateVideoTime(int duration);
  189. //单击手势,确认是单击的时候调用
  190. void onGestureSingleClick();
  191. //双击手势,确认是双击的时候调用,可用于播放器暂停
  192. void onGestureDoubleClick();
  193. void onGestureDown();
  194. }
  195. private enum ScrollMode {
  196. NONE, //初始值
  197. LEFT_TB, //左边上下滑动(调节亮度)
  198. RIGHT_TB, //右边上下滑动(调节声音)
  199. HORIZONTAL_S, //横向滑动(快进快退)
  200. SINGLE_CLICK, //单击
  201. DOUBLE_CLICK //双击
  202. }
  203. }