android开发之GestureDetector手势识别(调节音量、亮度、快进和后退)

时间:2022-09-01 16:36:15

android开发之GestureDetector手势识别(调节音量、亮度、快进和后退)

写UI布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical" > <include
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="200dp"
layout="@layout/video_layout" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" > <com.zanelove.gesturedetectordemo.views.MyVideoView
android:id="@+id/tv_pro_play"
android:layout_width="match_parent"
android:layout_height="match_parent" /> <LinearLayout
android:id="@+id/ll_player_controller"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#c0000000"
android:gravity="center"
android:orientation="horizontal"
android:visibility="gone"> <ImageView
android:id="@+id/iv_play_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
android:src="@drawable/btn_pause" /> <TextView
android:id="@+id/tv_playing_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="00:00"
android:textColor="@android:color/darker_gray"
android:textSize="15sp" /> <SeekBar
android:id="@+id/sb_video_progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_weight="2" /> <TextView
android:id="@+id/tv_total_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="00:00"
android:textColor="@android:color/darker_gray"
android:textSize="15sp" /> <ImageView
android:id="@+id/iv_full_screen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:padding="15dp"
android:src="@drawable/btn_full_screen" />
</LinearLayout> <RelativeLayout
android:id="@+id/gesture_volume_layout"
android:layout_width="120dip"
android:layout_height="100dip"
android:layout_centerInParent="true"
android:background="@drawable/souhu_player_gesture_bg"
android:gravity="center"
android:visibility="gone" > <ImageView
android:id="@+id/gesture_iv_player_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/souhu_player_volume" /> <TextView
android:id="@+id/geture_tv_volume_percentage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/gesture_iv_player_volume"
android:layout_centerHorizontal="true"
android:gravity="right"
android:text="80%"
android:textColor="#ffececec" />
</RelativeLayout> <RelativeLayout
android:id="@+id/gesture_bright_layout"
android:layout_width="120dip"
android:layout_height="100dip"
android:layout_centerInParent="true"
android:background="@drawable/souhu_player_gesture_bg"
android:gravity="center"
android:visibility="gone" > <ImageView
android:id="@+id/gesture_iv_player_bright"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/souhu_player_bright" /> <TextView
android:id="@+id/geture_tv_bright_percentage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/gesture_iv_player_bright"
android:layout_centerHorizontal="true"
android:gravity="right"
android:text="80%"
android:textColor="#ffececec" />
</RelativeLayout> <RelativeLayout
android:id="@+id/gesture_progress_layout"
android:layout_width="120dip"
android:layout_height="100dip"
android:layout_centerInParent="true"
android:background="@drawable/souhu_player_gesture_bg"
android:gravity="center"
android:visibility="gone"> <ImageView
android:id="@+id/gesture_iv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/souhu_player_backward" /> <TextView
android:id="@+id/geture_tv_progress_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/gesture_iv_progress"
android:layout_centerHorizontal="true"
android:gravity="right"
android:text="00:35/24:89"
android:textColor="#ffececec" />
</RelativeLayout> </RelativeLayout>

以上将UI布局给大伙粘贴上来了。大家依照各自的需求改吧改吧…就可以

那么。就下来我将首先给大家分析分析怎样通过手势识别来调节音量、亮度、快键和后退需求!

一提到手势识别。大伙第一反应绝对是Google提供给我们的GestureDetector类,没错今天我们就使用使用这个类来给大家完毕以上的需求!

第一:将主逻辑代码类继承FragmentActivity类并实现OnGestureListener监听和OnTouchListener监听,同一时候在onCreate方法中创建GestureDetector对象,这时须要传递两个对象,这也是为啥我要继承和实现了!

GestureDetector gestureDetector = new GestureDetector(this, this);

第二:获取UI布局中定义的控件

这些你全然能够使用xUtils第三方工具的注解来完毕下面操作:

@ViewInject(R.id.gesture_bright_layout)
RelativeLayout gesture_bright_layout; ViewUtils.inject(this);

也能够通过findViewById方法:

// 视频播放控件
tv_pro_play = (MyVideoView) findViewById(R.id.tv_pro_play); /*
iv_full_screen = (ImageView) findViewById(R.id.iv_full_screen);
iv_play_pause = (ImageView) findViewById(R.id.iv_play_pause); ll_player_controller = (LinearLayout) findViewById(R.id.ll_player_controller); iv_play_pause = (ImageView) findViewById(R.id.iv_play_pause);
sb_video_progress = (SeekBar) findViewById(R.id.sb_video_progress);
iv_full_screen = (ImageView) findViewById(R.id.iv_full_screen);
tv_playing_time = (TextView) findViewById(R.id.tv_playing_time);
tv_total_time = (TextView) findViewById(R.id.tv_total_time);*/ // ****************音量/进度/亮度********************* root_layout = (RelativeLayout) findViewById(R.id.root_layout);
gesture_volume_layout = (RelativeLayout) findViewById(R.id.gesture_volume_layout);
gesture_bright_layout = (RelativeLayout) findViewById(R.id.gesture_bright_layout);
gesture_progress_layout = (RelativeLayout) findViewById(R.id.gesture_progress_layout);
geture_tv_progress_time = (TextView) findViewById(R.id.geture_tv_progress_time);
geture_tv_volume_percentage = (TextView) findViewById(R.id.geture_tv_volume_percentage);
geture_tv_bright_percentage = (TextView) findViewById(R.id.geture_tv_bright_percentage);
gesture_iv_progress = (ImageView) findViewById(R.id.gesture_iv_progress);
gesture_iv_player_volume = (ImageView) findViewById(R.id.gesture_iv_player_volume);
gesture_iv_player_bright = (ImageView) findViewById(R.id.gesture_iv_player_bright);
gestureDetector = new GestureDetector(this, this); //须要实现OnGestureListener监听
root_layout.setLongClickable(true);
gestureDetector.setIsLongpressEnabled(true);
root_layout.setOnTouchListener(this);//须要实现OnTouchListener监听
audiomanager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
maxVolume = audiomanager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); // 获取系统最大音量
currentVolume = audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC); // 获取当前值

第三:获取视频播放窗体的尺寸,推断触发的视频播放窗体位置来识别不同的操作和需求:

/** 获取视频播放窗体的尺寸 */
ViewTreeObserver viewObserver = root_layout.getViewTreeObserver();
viewObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
root_layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
playerWidth = root_layout.getWidth();
playerHeight = root_layout.getHeight();
}
});

第四:当你实现OnGestureListener监听和OnTouchListener监听时是须要您实现其方法的。各自是:

当你实现了OnTouchListener监听须要覆写其方法:
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
} 当你实现了OnGestureListener监听须要覆写一下方法:
// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
@Override
public boolean onDown(MotionEvent e) {
return false;
} // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
} // 用户(轻触触摸屏后)松开,由1个MotionEvent ACTION_UP触发
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
} // 用户按下触摸屏、高速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
} // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
@Override
public void onLongPress(MotionEvent e) {} // 用户轻触触摸屏,尚未松开或拖动,由1个MotionEvent ACTION_DOWN触发, 注意和onDown()的差别,强调的是没有松开或者拖动的状态
@Override
public void onShowPress(MotionEvent e) {}

能够看到OnTouchListener仅仅能监听到三种触摸事件,即按下。移动,松开,假设想要监听到双击、滑动、长按等复杂的手势操作,这个时候就必须得用到OnGestureListener了。

因此在onTouch()方法中,我们要进行例如以下的处理:

@Override
public boolean onTouch(View v, MotionEvent event) {
// 手势里除了singleTapUp,没有其它检測up的方法
if (event.getAction() == MotionEvent.ACTION_UP) {
GESTURE_FLAG = 0;// 手指离开屏幕后,重置调节音量或进度的标志
gesture_volume_layout.setVisibility(View.GONE);
gesture_bright_layout.setVisibility(View.GONE);
gesture_progress_layout.setVisibility(View.GONE);
}
return gestureDetector.onTouchEvent(event);//假设想要监听到双击、滑动、长按等复杂的手势操作,这个时候就必须得用到OnGestureListener了
}

同一时候点击屏幕时触发的onDown()方法中:

@Override
public boolean onDown(MotionEvent e) {
firstScroll = true;// 设定是触摸屏幕后第一次scroll的标志
return false;
}

通过在onTouch()方法中调用gestureDetector.onTouchEvent(event)方法时,它会去调用onScroll()方法,这样在该方法中通过手势识别来完毕调节音量、亮度、快键和后退操作:

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
float mOldX = e1.getX(), mOldY = e1.getY();
int y = (int) e2.getRawY();
if (firstScroll) {// 以触摸屏幕后第一次滑动为标准,避免在屏幕上操作切换混乱
// 横向的距离变化大则调整进度,纵向的变化大则调整音量
if (Math.abs(distanceX) >= Math.abs(distanceY)) {
gesture_progress_layout.setVisibility(View.VISIBLE);
gesture_volume_layout.setVisibility(View.GONE);
gesture_bright_layout.setVisibility(View.GONE);
GESTURE_FLAG = GESTURE_MODIFY_PROGRESS;
} else {
if (mOldX > playerWidth * 3.0 / 5) {// 音量
gesture_volume_layout.setVisibility(View.VISIBLE);
gesture_bright_layout.setVisibility(View.GONE);
gesture_progress_layout.setVisibility(View.GONE);
GESTURE_FLAG = GESTURE_MODIFY_VOLUME;
} else if (mOldX < playerWidth * 2.0 / 5) {// 亮度
gesture_bright_layout.setVisibility(View.VISIBLE);
gesture_volume_layout.setVisibility(View.GONE);
gesture_progress_layout.setVisibility(View.GONE);
GESTURE_FLAG = GESTURE_MODIFY_BRIGHT;
}
}
} // 假设每次触摸屏幕后第一次scroll是调节进度。那之后的scroll事件都处理音量进度,直到离开屏幕运行下一次操作
if (GESTURE_FLAG == GESTURE_MODIFY_PROGRESS) {
// distanceX=lastScrollPositionX-currentScrollPositionX,因此为正时是快进
if (Math.abs(distanceX) > Math.abs(distanceY)) {// 横向移动大于纵向移动
if (distanceX >= DensityUtil.dip2px(this, STEP_PROGRESS)) {// 快退,用步长控制改变速度。可微调
gesture_iv_progress.setImageResource(R.drawable.souhu_player_backward);
if (playingTime > 3) {// 避免为负
playingTime -= 3;// scroll方法运行一次快退3秒
} else {
playingTime = 0;
}
} else if (distanceX <= -DensityUtil.dip2px(this, STEP_PROGRESS)) {// 快进
gesture_iv_progress.setImageResource(R.drawable.souhu_player_forward);
if (playingTime < videoTotalTime - 16) {// 避免超过总时长
playingTime += 3;// scroll运行一次快进3秒
} else {
playingTime = videoTotalTime - 10;
}
}
if (playingTime < 0) {
playingTime = 0;
}
tv_pro_play.seekTo(playingTime);
geture_tv_progress_time.setText(DateTools.getTimeStr(playingTime) + "/" + DateTools.getTimeStr(videoTotalTime));
}
} // 假设每次触摸屏幕后第一次scroll是调节音量,那之后的scroll事件都处理音量调节。直到离开屏幕运行下一次操作
else if (GESTURE_FLAG == GESTURE_MODIFY_VOLUME) {
currentVolume = audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC); // 获取当前值
if (Math.abs(distanceY) > Math.abs(distanceX)) {// 纵向移动大于横向移动
if (distanceY >= DensityUtil.dip2px(this, STEP_VOLUME)) {// 音量调大,注意横屏时的坐标体系,虽然左上角是原点,但横向向上滑动时distanceY为正
if (currentVolume < maxVolume) {// 为避免调节过快,distanceY应大于一个设定值
currentVolume++;
}
gesture_iv_player_volume.setImageResource(R.drawable.souhu_player_volume);
} else if (distanceY <= -DensityUtil.dip2px(this, STEP_VOLUME)) {// 音量调小
if (currentVolume > 0) {
currentVolume--;
if (currentVolume == 0) {// 静音,设定静音独有的图片
gesture_iv_player_volume.setImageResource(R.drawable.souhu_player_silence);
}
}
}
int percentage = (currentVolume * 100) / maxVolume;
geture_tv_volume_percentage.setText(percentage + "%");
audiomanager.setStreamVolume(AudioManager.STREAM_MUSIC,currentVolume, 0);
}
} // 假设每次触摸屏幕后第一次scroll是调节亮度,那之后的scroll事件都处理亮度调节。直到离开屏幕运行下一次操作
else if (GESTURE_FLAG == GESTURE_MODIFY_BRIGHT) {
gesture_iv_player_bright.setImageResource(R.drawable.souhu_player_bright);
if (mBrightness < 0) {
mBrightness = getWindow().getAttributes().screenBrightness;
if (mBrightness <= 0.00f)
mBrightness = 0.50f;
if (mBrightness < 0.01f)
mBrightness = 0.01f;
}
WindowManager.LayoutParams lpa = getWindow().getAttributes();
lpa.screenBrightness = mBrightness + (mOldY - y) / playerHeight;
if (lpa.screenBrightness > 1.0f)
lpa.screenBrightness = 1.0f;
else if (lpa.screenBrightness < 0.01f)
lpa.screenBrightness = 0.01f;
getWindow().setAttributes(lpa);
geture_tv_bright_percentage.setText((int) (lpa.screenBrightness * 100) + "%");
} firstScroll = false;// 第一次scroll运行完毕,改动标志
return false;
}

这种话,我个人觉得完美了…不完美之处还望各位大牛多多提醒,本人随时随地进行接纳…哈哈,谢谢咯

演示样例代码

android开发之GestureDetector手势识别(调节音量、亮度、快进和后退)的更多相关文章

  1. Android开发之MdiaPlayer详解

    Android开发之MdiaPlayer详解 MediaPlayer类可用于控制音频/视频文件或流的播放,我曾在<Android开发之基于Service的音乐播放器>一文中介绍过它的使用. ...

  2. Android开发之Java集合类性能分析

    对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天Android吧(ard8. ...

  3. Android开发之InstanceState详解

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  4. Android开发之Git配置

    Android开发之Git配置 1.首先git配置: 输入命令: git config --global user.name "xxx.xx" git config --globa ...

  5. 【Android UI】Android开发之View的几种布局方式及实践

    引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...

  6. Android开发之旅&colon; Intents和Intent Filters(理论部分)

    引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...

  7. Android开发之ViewPager&plus;ActionBar&plus;Fragment实现响应式可滑动Tab

     今天我们要实现的这个效果呢,在Android的应用中十分地常见,我们可以看到下面两张图,无论是系统内置的联系人应用,还是AnyView的阅读器应用,我们总能找到这样的影子,当我们滑动屏幕时,Tab可 ...

  8. Android开发之Java必备基础

    Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...

  9. Android开发之PopupWindow

      /* *  Android开发之PopupWindow * *  Created on: 2011-8-8 *  Author: blueeagle *  Email: liujiaxiang@g ...

随机推荐

  1. &lbrack;nginx&rsqb; connect&lpar;&rpar; failed &lpar;111&colon; Connection refused&rpar; while connecting to upstream&comma; client&colon; 101&period;18&period;123&period;107&comma; server&colon; localhost&comma;

    nginx一直报错, 2016/12/02 10:23:19 [error] 1472#0: *31 connect() failed (111: Connection refused)while c ...

  2. AIX 文件 打包 与 压缩 tar gzip compress 的使用

    今天在Aix用tar -cvf 备份,打成tar包,占有硬盘空间过大,没有压缩比, 尝试使用tar -zcvf  linux系统下可以用-z 命令 (z 用gzip来压缩/解压缩文件,加上该选项后可以 ...

  3. 北大poj-1062

    昂贵的聘礼 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 43523   Accepted: 12760 Descripti ...

  4. javascript 网页运行代码效果

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  5. 问题解决——在STL的queue中使用自定义类

    本文原创,转载请保证文章的完整性,并显要的注明出处. 本文链接:http://blog.csdn.net/wlsgzl/article/details/38843513 平时很少用STL,就算用,也基 ...

  6. AudioManager音频管理器

    AudioManager音频管理器提供了如下几种常用方法来控制手机音频: 1.adjustStreamVolume(int StreamType,int direction,int flgs):调整手 ...

  7. bzoj 2754 &lbrack;SCOI2012&rsqb;喵星球上的点名(后缀数组)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2754 [题意] 每只喵有名姓,如果被老师点到名或姓的子串都要答道,但每只喵一次点名只答 ...

  8. JQuery焦点Table

    ;;} .table-bordered{;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .table{mar ...

  9. 【转】Android HAL实例解析

    原文网址:http://www.embedu.org/Column/Column339.htm 作者:刘老师,华清远见嵌入式学院讲师. 一.概述 本文希望通过分析*的Jollen的mokoid 工程 ...

  10. MySQL的用户密码过期功能详解

    MySQL的用户密码过期功能详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs 先说明两个术语. Payment Ca ...