商城首页欢迎来到中国正版软件门户

您的位置:首页 >3.8 Gestures(手势)

3.8 Gestures(手势)

  发布于2026-08-12 阅读(0)

扫一扫,手机访问

本节引言:

周六不休息,刚剪完了个大平头回来,继续码字~

这一节来到第三章的收尾部分,聊的是 Gestures(手势)。用过魅族手机的朋友,对这套交互方式大多不会陌生:比如从 home 键两侧向屏幕内滑动,就能直接调出后台任务列表。其实,手势一旦用到应用里,用户体验往往会明显提升。举个最直观的例子,浏览器里常见的 Scroll 手势可以用来滚动页面,Fling 则常被用来切换页面,这类操作既顺手,也更高效。

当然,有利也有弊,比如不当的手势操作引起APP Carsh,经常这样可是会引起用户不满的! 所以是否要为你的应用增加手势,可要考虑清楚哦!另外手势要和前面学的单指/多指触碰相区分哦!

手势是:连续触碰的行为,比如左右上下滑动屏幕,又或者画一些不规则的几何图形! Android对上述两种手势行为都提供了支持:

  • Android提供手势检测,并为手势识别提供了相应的监听器!
  • Android运行开发者自行添加手势,并且提供了相应的API识别用户手势!

如果你的手机用的是 Android 4.x 的原生系统,那么大概率会在手机或平板里看到谷歌提供的一个 Gesture Builder 应用。这个工具挺直观,用户可以像随手涂鸦一样画出一个手写符号,再把它和某个字符串名称对应起来。当然,就算手头没有这样的设备也没关系,直接用模拟器也一样,开一个 4.0 系统试一试,效果一看便知。另外,还可以到mmtsdcardgestures拿到保存手势的文件。前面的铺垫先到这里,接下来进入正题。

对了,贴下官方API文档先:GestureDetector

1.Android中手势交互的执行顺序

  • 1.手指触碰屏幕时,触发MotionEvent事件!
  • 2.该事件被OnTouchListener监听,可在它的onTouch()方法中获得该MotionEvent对象!
  • 3.通过GestureDetector转发MotionEvent对象给OnGestureListener
  • 4.我们可以通过OnGestureListener获得该对象,然后获取相关信息,以及做相关处理!

我们来看下上述的三个类都是干嘛的: MotionEvent: 这个类用于封装手势、触摸笔、轨迹球等等的动作事件。 其内部封装了两个重要的属性X和Y,这两个属性分别用于记录横轴和纵轴的坐标。 GestureDetector: 识别各种手势。 OnGestureListener: 这是一个手势交互的监听接口,其中提供了多个抽象方法, 并根据GestureDetector的手势识别结果调用相对应的方法。

——上述资料摘自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1020/448.html

2.GestureListener详解:

从1中我们知道了监听手势的关键是:GestureListener 他给我们提供了下述的回调方法:

  • 按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。
  • 抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。
  • 长按(onLongPress): 手指按在持续一段时间,并且没有松开。
  • 滚动(onScroll): 手指在触摸屏上滑动。
  • 按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。
  • 抬起(onSingleTapUp):手指离开触摸屏的那一刹那。

知道了GestureListener的相关方法后,实现手势检测也很简单,步骤如下:

  • Step 1: 创建GestureDetector对象,创建时需实现GestureListener传入
  • Step 2: 将Activity或者特定组件上的TouchEvent的事件交给GestureDetector处理即可! 我们写个简单的代码来验证这个流程,即重写对应的方法:

代码如下:

public class MainActivity extends AppCompatActivity {
private MyGestureListener mgListener;
    private GestureDetector mDetector;
    private final static String TAG = "MyGesture";
@Override
    protected void onCreate(Bundle sa vedInstanceState) {
        super.onCreate(sa vedInstanceState);
        setContentView(R.layout.activity_main);
        //实例化GestureListener与GestureDetector对象
        mgListener = new MyGestureListener();
        mDetector = new GestureDetector(this, mgListener);
}
@Override
    public boolean onTouchEvent(MotionEvent event) {
        return mDetector.onTouchEvent(event);
    }
//自定义一个GestureListener,这个是View类下的,别写错哦!!!
    private class MyGestureListener implements GestureDetector.OnGestureListener {
@Override
        public boolean onDown(MotionEvent motionEvent) {
            Log.d(TAG, "onDown:按下");
            return false;
        }
@Override
        public void onShowPress(MotionEvent motionEvent) {
            Log.d(TAG, "onShowPress:手指按下一段时间,不过还没到长按");
        }
@Override
        public boolean onSingleTapUp(MotionEvent motionEvent) {
            Log.d(TAG, "onSingleTapUp:手指离开屏幕的一瞬间");
            return false;
        }
@Override
        public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
            Log.d(TAG, "onScroll:在触摸屏上滑动");
            return false;
        }
@Override
        public void onLongPress(MotionEvent motionEvent) {
            Log.d(TAG, "onLongPress:长按并且没有松开");
        }
@Override
        public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
            Log.d(TAG, "onFling:迅速滑动,并松开");
            return false;
        }
    }
}

对应操作截图:

  • 1.按下后立即松开:
  • 2.长按后松开:
  • 3.轻轻一滑,同时松开:
  • 4.按住后不放持续做滑动操作:

PS:从上述结果来看,我们发现了一个问题: 我们实现OnGestureListener需要实现所有的手势,可能我针对的仅仅是滑动,但是你还是要去重载, 这显得很逗逼,是吧,官方肯定会给出解决方法滴,官方另外给我们提供了一个SimpleOnGestureListener类 只需把上述的OnGestureListener替换成SimpleOnGestureListener即可!

3.简单的例子:下滑关闭Activity,上滑启动新的Activity

这里就用上述的SimpleOnGestureListener来实现吧:

运行效果图:

实现代码:

public class MainActivity extends AppCompatActivity {
private GestureDetector mDetector;
    private final static int MIN_MOVE = 200;   //最小距离
    private MyGestureListener mgListener;
@Override
    protected void onCreate(Bundle sa vedInstanceState) {
        super.onCreate(sa vedInstanceState);
        setContentView(R.layout.activity_main);
        //实例化SimpleOnGestureListener与GestureDetector对象
        mgListener = new MyGestureListener();
        mDetector = new GestureDetector(this, mgListener);
    }
@Override
    public boolean onTouchEvent(MotionEvent event) {
        return mDetector.onTouchEvent(event);
    }
//自定义一个GestureListener,这个是View类下的,别写错哦!!!
    private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float v, float v1) {
            if(e1.getY() - e2.getY() > MIN_MOVE){
                startActivity(new Intent(MainActivity.this, MainActivity.class));
                Toast.makeText(MainActivity.this, "通过手势启动Activity", Toast.LENGTH_SHORT).show();
            }else if(e1.getY() - e2.getY()  < MIN_MOVE){
                finish();
                Toast.makeText(MainActivity.this,"通过手势关闭Activity",Toast.LENGTH_SHORT).show();
            }
            return true;
        }
    }
}

结果分析: 从上面的对比就可以知道,相比起SimpleOnGestureListener使用SimpleOnGestureListener 显得更加的简单,想重写什么方法就重写什么方法,另外例子比较简单,大家可以自己试试 其他玩法,比如通过手势缩放图片~

4.手势添加与识别:

除了上面讲解的手势检测外,Android还运行我们将手势进行添加,然后提供了相关的识别API; Android中使用GestureLibrary来代表手势库,提供了GestureLibraries工具类来创建手势库!

四个加载手势库的静态方法:

获得GestureLibraries对象后,就可以使用该对象提供的下述方法来做相应操作了:

相关方法:

  • public void addGesture (String entryName, Gesture gesture):添加一个名为entryName的手势
  • public Set getGestureEntries ():获得手势库中所有手势的名称
  • public ArrayList getGestures (String entryName):获得entryName名称对应的全部手势
  • public ArrayList recognize (Gesture gesture): 从当前手势库中识别与gesture匹配的全部手势
  • public void removeEntry (String entryName):删除手势库中entryName名称对应的手势
  • public void removeGesture (String entryName, Gesture gesture):删除手势库中entryName和gesture都匹配的手势
  • public abstract boolean sa ve ():想手势库中添加手势或从中删除手势后调用该方法保存手势库

GestureOverlayView手势编辑组件:

Android为GestureOverlayView提供了三种监听器接口,如下,一般常用的是:OnGesturePerformedListener;用于手势完成时提供响应!

5.手势添加示例:

PS:例子引用的是——李刚《Android疯狂讲义》的代码

运行效果图:

好吧,下面贴下实现代码:

两个布局文件:activity_main.xml和dialog_sa ve.xml

activity_main.xml




    

dialog_sa ve.xml




        
        
    

MainActivity.ja va:

public class MainActivity extends AppCompatActivity {
private EditText editText;
    private GestureOverlayView gesture;
@Override
    protected void onCreate(Bundle sa vedInstanceState) {
        super.onCreate(sa vedInstanceState);
        setContentView(R.layout.activity_main);
        //获取手势编辑组件后,设置相关参数
        gesture = (GestureOverlayView) findViewById(R.id.gesture);
        gesture.setGestureColor(Color.GREEN);
        gesture.setGestureStrokeWidth(5);
        gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
            @Override
            public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) {
                View sa veDialog = getLayoutInflater().inflate(R.layout.dialog_sa ve,null,false);
                ImageView img_show = (ImageView) sa veDialog.findViewById(R.id.img_show);
                final EditText edit_name = (EditText) sa veDialog.findViewById(R.id.edit_name);
                Bitmap bitmap = gesture.toBitmap(128,128,10,0xffff0000);
                img_show.setImageBitmap(bitmap);
                new AlertDialog.Builder(MainActivity.this).setView(sa veDialog)
                        .setPositiveButton("保存",new DialogInterface.OnClickListener()
                        {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                //获取文件对应的手势库
                                GestureLibrary gestureLib = GestureLibraries.fromFile("/mnt/sdcard/mygestures");
                                gestureLib.addGesture(edit_name.getText().toString(),gesture);
                                gestureLib.sa ve();
                            }
                        }).setNegativeButton("取消", null).show();
            }
        });
    }
}

最后还需要在AndroidManifest.xml中添加写入SD卡的权限:

6.手势识别示例

实现代码:

public class MainActivity extends AppCompatActivity {
private GestureOverlayView gesture;
    private GestureLibrary gestureLibrary;
    private Context mContext;
@Override
    protected void onCreate(Bundle sa vedInstanceState) {
        super.onCreate(sa vedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        gestureLibrary = GestureLibraries.fromFile("mmt/sdcard/mygestures");
        if (gestureLibrary.load()) {
            Toast.makeText(mContext, "手势库加载成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mContext, "手势库加载失败", Toast.LENGTH_SHORT).show();
        }
//获取手势编辑组件后,设置相关参数
        gesture = (GestureOverlayView) findViewById(R.id.gesture);
        gesture.setGestureColor(Color.GREEN);
        gesture.setGestureStrokeWidth(5);
        gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
            @Override
            public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) {
                //识别用户刚绘制的手势
                ArrayList predictions = gestureLibrary.recognize(gesture);
                ArrayList result = new ArrayList();
                //遍历所有找到的Prediction对象
                for (Prediction pred : predictions) {
                    if (pred.score > 2.0) {
                        result.add("与手势【" + pred.name + "】相似度为" + pred.score);
                    }
                }
                if (result.size() > 0) {
                    ArrayAdapter adapter = new ArrayAdapter(mContext,
                            android.R.layout.simple_dropdown_item_1line, result.toArray());
                    new AlertDialog.Builder(mContext).setAdapter(adapter,null).setPositiveButton("确定",null).show();
                }else{
                    Toast.makeText(mContext,"无法找到匹配的手势!",Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

另外别忘了在AndroidManifest.xml文件中加入读SD卡的权限:

本节小结:

好的,本节介绍了Android中的Gesture手势,讲解了手势判断,手势添加,手势识别三个内容 ,大部分例子来自于李刚老师的Android疯狂讲义,有兴趣的可以看看该书~谢谢

本文转载于:https://www.runoob.com/w3cnote/android-tutorial-gestures.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。
  • 2.6.0 其他几种常用对话框基本使用 正版软件
    2.6.0 其他几种常用对话框基本使用
    本节引言: 上一节已经把Dialog的父类 AlertDialog 过了一遍,这一节顺着往下看,重点聊几个开发里很常用的 Dialog 基本用法,分别是:ProgressDialog(进度条对话框)、DatePickerDialog(日期选择对话框)和 TimePickerDialog(时间选择对话
    刚刚 0
  • 2.6.1 PopupWindow(悬浮框)的基本使用 正版软件
    2.6.1 PopupWindow(悬浮框)的基本使用
    本节引言: 这一节要说的,是用于信息展示的最后一个 UI 控件——PopupWindow(悬浮框)。如果一时没概念,不妨直接想想手机里的 QQ:长按列表中的某一项,通常会弹出一个黑色的小对话框,这类效果基本就是 PopupWindow。它和 AlertDialog 对话框最大的区别在于,位置并不是固
    刚刚 0
  • 2.6.2 菜单(Menu) 正版软件
    2.6.2 菜单(Menu)
    本节引言: 本章给大家带来的是Android中的Menu(菜单),而在Android中的菜单有如下几种: OptionMenu:选项菜单,android中最常见的菜单,通过Menu键来调用 SubMenu:子菜单,android中点击子菜单将弹出一个显示子菜单项的悬浮框, 子菜单不支持嵌套,即不能包
    刚刚 0
  • 2.6.3 ViewPager的简单使用 正版软件
    2.6.3 ViewPager的简单使用
    本节引言: 这一节要说的,是 Android 3.0 之后引入的一个 UI 控件——ViewPager(视图滑动切换工具)。这个名字其实已经把作用点得很明白了:它的核心能力,就是通过手势滑动来完成 View 之间的切换。实际开发里,这个控件很常见,APP 引导页、图片轮播这类场景,基本都少不了它。也
    1分钟前 0
  • 2.6.4 DrawerLayout(官方侧滑菜单)的简单使用 正版软件
    2.6.4 DrawerLayout(官方侧滑菜单)的简单使用
    本节引言: 这一节来说基础 UI 控件里的最后一位:DrawerLayout。它是官方提供的侧滑菜单控件,和上一节提到的 ViewPager 一样,都是在 3.0 之后引入的;如果项目需要兼容更低版本,就得配合 v4 兼容包来用。提到侧滑菜单,很多人应该都接触过 github 上的 SlidingM
    1分钟前 0