Android手势识别GestureOverlayView手势自动消除和多笔画识别问题

本文介绍了在Android项目中使用GestureOverlayView进行手势识别时遇到的自动消除和多笔画识别问题。通过分析GestureStore和GestureOverlayView的源码,揭示了Android并未提供直接解决这些问题的API,并提供了相关源码链接进行深入学习。作者修改了源代码以适配项目需求,但强调更好的识别效果需要更深入的学习和探讨。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android手势识别GestureOverlayView手势消除和多笔画识别问题

最近做的一个项目,要求将手势(Gesture)由用户自定义储存,然后再根据用户划出的手势分别启动相应的功能。在网上查找了一些资料,发现可以使用Android 1.6开始支持的手势识别功能,至于完成笔画绘制的部分可以直接使用GestureOverlayView来完成。在Android的模拟器了预装了一个叫GesturesBuilder的程序(最近的4.4还有,源码:http://download.youkuaiyun.com/detail/xiaowan0404/7852261)。通过对这个软件的源码学习以及网上的资料,完成的还算顺利,不过却遇到了两个问题,也就是标题中所说的自动消除和多笔画识别不准确。不过要解决这两个问题却有点麻烦,我直接说结论吧,Android的源码就是这样的,它并没有提供相应的API来给我们使用,所以我觉得这里Android只是给我们提供了一个“半成品”,尽管以我的水平来说,要写出这么一个半成品还是远远不足。

http://blog.youkuaiyun.com/stevenhu_223/article/category/1515741

这里已经把Android手势识别源码说明的很详细了,一些API我就不列出来,Android的官方文档和网上就有很多资料了。我就说一些值得注意之处。

http://download.youkuaiyun.com/detail/xiaowan0404/8039051

这是手势识别相关源代码。

GestureStore

GestureStore里面的两个方法:setOrientationStyle(int style)和void setSequenceType(int type)。我们可以看一下源码:

    public static final int SEQUENCE_INVARIANT = 1;
    // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed
    public static final int SEQUENCE_SENSITIVE = 2;

    // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures
    public static final int ORIENTATION_INVARIANT = 1;
    // at most 2 directions can be recognized
    public static final int ORIENTATION_SENSITIVE = 2;
    // at most 4 directions can be recognized
    static final int ORIENTATION_SENSITIVE_4 = 4;
    // at most 8 directions can be recognized
    static final int ORIENTATION_SENSITIVE_8 = 8;

这里注意,只有ORIENTATION_INVARIANT和ORIENTATION_SENSITIVE是public的,但是我们在外面调用时也是可以直接set 4和8的。

public void setOrientationStyle(int style) {
        mOrientationStyle = style;
    }
public void setSequenceType(int type) {
        mSequenceType = type;
    }

这两个方法对于提高识别精度个人认为还是很重要的,不然有时候我们画一条斜率是45度的直线,它直接给把横线的情况识别出来了。

GestureOverlayView

setGestureVisible(boolean visible):手势是否可见。
setFadeEnabled(boolean fadeEnabled):这个方法不是设置手势是否自动清除的,只是手势消散动画的开关。
setFadeOffset(long fadeOffset):手势多少毫秒后消除,或调用onGesturePerformed(手势识别Listener方法)的时间间隔(如果调用)。

所以自动消除的问题来了,如果想让手势识别进行后不会自动消散的话,Android并没有给出API。

private void clear(boolean animated, boolean fireActionPerformed, boolean immediate) {
        setPaintAlpha(255);
        removeCallbacks(mFadingOut);
        mResetGesture = false;
        mFadingOut.fireActionPerformed = fireActionPerformed;
        mFadingOut.resetMultipleStrokes = false;

        if (animated && mCurrentGesture != null) {
            mFadingAlpha = 1.0f;
            mIsFadingOut = true;
            mFadingHasStarted = false;
            mFadingStart = AnimationUtils.currentAnimationTimeMillis() + mFadeOffset;

            postDelayed(mFadingOut, mFadeOffset);
        } else {
            mFadingAlpha = 1.0f;
            mIsFadingOut = false;
            mFadingHasStarted = false;

            if (immediate) {
                mCurrentGesture = null;
                mPath.rewind();
                invalidate();
            } else if (fireActionPerformed) {
                postDelayed(mFadingOut, mFadeOffset);
            } else if (mGestureStrokeType == GESTURE_STROKE_TYPE_MULTIPLE) {
                mFadingOut.resetMultipleStrokes = true;
                postDelayed(mFadingOut, mFadeOffset);
            } else {
                mCurrentGesture = null;
                mPath.rewind();
                invalidate();
            }
        }
    }

再看一下mFadingOut相关的代码,可以看到,无论怎么样,它总会调用rewind()和invalidate()方法,所以最后手势是会消散的。

多笔识别问题

我遇到一个坑爹问题就是多笔识别时,如果第一笔相同,那么这两个手势一定会判断判断为相似,如“一”,“二”,“三”等。
可以看代码:

private static float[] temporalSampler(int orientationType, Gesture gesture) {
        //这里是get(0)
        float[] pts = GestureUtils.temporalSampling(gesture.getStrokes().get(0),
                SEQUENCE_SAMPLE_SIZE); 
        float[] center = GestureUtils.computeCentroid(pts);
        float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);

        float adjustment = -orientation;
        if (orientationType != GestureStore.ORIENTATION_INVARIANT) {
            int count = ORIENTATIONS.length;
            for (int i = 0; i < count; i++) {
                float delta = ORIENTATIONS[i] - orientation;
                if (Math.abs(delta) < Math.abs(adjustment)) {
                    adjustment = delta;
                }
            }
        }

        GestureUtils.translate(pts, -center[0], -center[1]);
        GestureUtils.rotate(pts, adjustment);

        return pts;
    }

其他代码分析可以在我上文分享的链接里查看。可以看到这里只是取了第一笔,那么相同也就理所当然了。

总结

我的项目是基于Android系统开发的,所以我适当修改了源代码,这只是一种权宜之技罢了。我本人也是一个初学者,对这一块也是刚起步,所以怎么达到更好的识别,还得靠各位牛人出手以及更加深入学习了。以上只是我的一点学习心得,如有错误请各位多多指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值