效果图
前言
2020年,智能手机大行其道,相信不会还有人用着老式的按键手机了吧,而智能手机最大的交互就是手机屏幕,其次的就是音量操作、生物识别(指纹+人脸+瞳孔)、说白了用的最多的是手机的屏幕,屏幕与用户之前进行交互,比如打开一个app你是不是要点击屏幕上某一个?有人说我可以用语音去打开,但是你没有想过语音其实只是帮你执行了点击,在手机上不管是玩游戏还是看电影或者是搞学习,都是要使用手机屏幕的,所以你知道屏幕交互有多么重要吗?
正文
屏幕的交互当然首先是触摸,说道触摸就是有一个手势监听,这个是Google起的名字,你不用手难道用脚吗?
下面可以新建一个项目,在MainActivity中实现两个监听
GestureDetector.OnGestureListener//手势监听 GestureDetector.OnDoubleTapListener//双击监听
实现这两个监听之后,会创建好几个方法,这里我会一个一个说明
onDown
/** * 当用户在屏幕上按下时会触发该方法,但在移动或抬起手指时不会触发 * @param e * @return */ @Override public boolean onDown(MotionEvent e) { return false; }
onShowPress
/** * 当用户在屏幕上按下,并且既没有移动有没有抬起手指时,会触发该方法。 * 一般通过该方法告知用户他们的动作已经被识别到了,你可以 高亮某个元素来提醒他们 * @param e */ @Override public void onShowPress(MotionEvent e) { }
onSingleTapUp
/** * 当用户在屏幕上轻击时(通常是指点击屏幕的时间很短)会触发该方法 * @param e * @return */ @Override public boolean onSingleTapUp(MotionEvent e) { return false; }
onScroll
/** * 在屏幕上发起滚动的手势时会触发该方法 * @param e1 第一个按下开始滚动的动作事件 * @param e2 触发当前这个方法的移动动作的事件 * @param distanceX 触发onScroll方法期间的X上的滚动距离 * @param distanceY 触发onScroll方法期间的Y上的滚动距离 * @return */ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; }
onLongPress
/** * 记得设置detector.setIsLongpressEnabled(true);,否则长按不会触发 * 当用户在屏幕上持续地长按时会触发该方法 * * @param e */ @Override public void onLongPress(MotionEvent e) { }
onFling
/** * 当用户在屏幕上持续地按下并且有“抛”的动作时,会触发该方法。对于该事件的理解, * 你可以体会一下按住一个图标然后把它扔到某个地方的感觉。 * * @param e1 第一个按下的动作事件 * @param e2 触发当前这个方法的“猛扔”动作的事件 * @param velocityX 触发onFling方法期间X轴上的移动速度 * @param velocityY 触发onFling方法期间Y轴上的移动速度 * @return */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; }
onSingleTapConfirmed
/** * 当用户在屏幕上单击是会触发此方法,与上面的onSingleTapUp方法不同的地方在于, * 该方法只会在监听器确定了用户在第一次单击后不会触发双击事件时才会被触发。 * * @param e * @return */ @Override public boolean onSingleTapConfirmed(MotionEvent e) { return true; }
onDoubleTap
/** * 当用户在屏幕上双击时会触发此方法。这里的按下动作事件指的时双击中的第一次触击。 * * @param e * @return */ @Override public boolean onDoubleTap(MotionEvent e) { return false; }
onDoubleTapEvent
/** * 在双击事件发生时会触发此方法,包括了按下、移动和抬起事件。 * * @param e * @return */ @Override public boolean onDoubleTapEvent(MotionEvent e) { return false; }
在Android系统中,每一次手势交互都会依照以下顺序执行
1,接触接触屏一刹那,触发一个MotionEvent事件。
2.该事件被OnTouchListener监听,在其onTouch()方法里获得该MotionEvent对象。
3.通过GestureDetector(手势识别器)转发次MotionEvent对象至OnGestureListener。
4.OnGestureListener获得该对象,听根据该对象封装的的信息,做出合适的反馈。
在Android中,是由GestureDetector类来负责手势的检测,每一个GestureDetector类的实例都代表一个手势监听器。在创建手势监听器时需要一个类OnGestureListener例。
下面就来实践一下,为了使整个效果更直观,我修改了一下布局
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/colorPrimary" app:navigationIcon="@mipmap/icon_clear" /> <LinearLayout android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_result" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="初学者-Study" android:textColor="#000" android:textSize="24sp" /> </LinearLayout> </LinearLayout>
里面用到了一个图标icon_clear.png
回到MainActivity
GestureDetector detector;//声明一个手势检测器对象 private TextView tvResult, tvTest; Toolbar toolbar; String result = "";
然后在onCreate()中
tvResult = findViewById(R.id.tv_result); toolbar = findViewById(R.id.toolbar); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { result = "初学者-Study"; tvResult.setText(result); result = ""; } }); detector = new GestureDetector(this, this);//实例化这个手势检测器对象 detector.setIsLongpressEnabled(true);//打开长触摸
然后就是具体的使用了
//绑定手势监听 这是前置条件 @Override public boolean onTouchEvent(MotionEvent e) { return detector.onTouchEvent(e); }
然后就可以在各个方法中进行数据的处理和显示了
/** * 当用户在屏幕上按下时会触发该方法,但在移动或抬起手指时不会触发 * * @param e * @return */ @Override public boolean onDown(MotionEvent e) { result += "onDown\n"; tvResult.setText(result); return false; } /** * 当用户在屏幕上按下,并且既没有移动有没有抬起手指时,会触发该方法。 * 一般通过该方法告知用户他们的动作已经被识别到了,你可以 高亮某个元素来提醒他们 * * @param e */ @Override public void onShowPress(MotionEvent e) { result += "onShowPress\n"; tvResult.setText(result); } /** * 当用户在屏幕上轻击时(通常是指点击屏幕的时间很短)会触发该方法 * * @param e * @return */ @Override public boolean onSingleTapUp(MotionEvent e) { result += "onSingleTapUp\n"; tvResult.setText(result); return false; } /** * 在屏幕上发起滚动的手势时会触发该方法 * * @param e1 第一个按下开始滚动的动作事件 * @param e2 触发当前这个方法的移动动作的事件 * @param distanceX 触发onScroll方法期间的X上的滚动距离 * @param distanceY 触发onScroll方法期间的Y上的滚动距离 * @return */ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (distanceY >= 0) {//上滑 result += "onScroll - Up\n"; tvResult.setText(result); } else {//下滑 result += "onScroll - Down\n"; tvResult.setText(result); } return false; } /** * 记得设置detector.setIsLongpressEnabled(true);,否则长按不会触发 * 当用户在屏幕上持续地长按时会触发该方法 * * @param e */ @Override public void onLongPress(MotionEvent e) { result += "onLongPress\n"; tvResult.setText(result); } /** * 当用户在屏幕上持续地按下并且有“抛”的动作时,会触发该方法。对于该事件的理解, * 你可以体会一下按住一个图标然后把它扔到某个地方的感觉。 * * @param e1 第一个按下的动作事件 * @param e2 触发当前这个方法的“猛扔”动作的事件 * @param velocityX 触发onFling方法期间X轴上的移动速度 * @param velocityY 触发onFling方法期间Y轴上的移动速度 * @return */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { result += "onFling\n"; tvResult.setText(result); return false; } /** * 当用户在屏幕上单击是会触发此方法,与上面的onSingleTapUp方法不同的地方在于, * 该方法只会在监听器确定了用户在第一次单击后不会触发双击事件时才会被触发。 * * @param e * @return */ @Override public boolean onSingleTapConfirmed(MotionEvent e) { result += "onSingleTapConfirmed\n"; tvResult.setText(result); return true; } /** * 当用户在屏幕上双击时会触发此方法。这里的按下动作事件指的时双击中的第一次触击。 * * @param e * @return */ @Override public boolean onDoubleTap(MotionEvent e) { result += "onDoubleTap\n"; tvResult.setText(result); return false; } /** * 在双击事件发生时会触发此方法,包括了按下、移动和抬起事件。 * * @param e * @return */ @Override public boolean onDoubleTapEvent(MotionEvent e) { result += "onDoubleTapEvent\n"; tvResult.setText(result); return false; }
运行看一下效果
点击屏幕
长触摸
双击屏幕
向上滑动
向下滑动
这就是基本的事件逻辑了,可以根据自己的需求进一步做处理,比如音量屏幕左边上滑时调节亮度,右边上滑时调节音量,这都是通过在onScroll方法中做处理实现的。OK,就是这样了