关于Android上识别手势画圆的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/StrangeNightmare/article/details/52885058

      转载请注明来自于:http://blog.csdn.net/strangenightmare/article/details/52885058

      之前无聊同事和我讨论关于手机上如何实现手势画圆这个功能。我就也突然来了兴趣。今天上班正好闲着,就实现一下嘛。改天就研究下三角形怎么实现。嘿嘿。

      我的思路主要是这样:首先记录下开始点的坐标A,然后计算这个点距离所有手指移动过的点的距离(当然是利用距离公式啦)。距离A点最远的当然是直径了。然后记录距离A点最远的点C,利用中点公式计算出中心点B。这样确定了原点和半径radius,只需要取手势划过的点和中心B点的距离和半径radius对比就好了。完全重合当然不可能啦。毕竟是手画的。我就取了差值在15以下认为是圆,这个可以根据需求后期调整,是否要精确一个圆。然后目标取样个数点我取了手指划过点的15-30个作为取样(手指停留越短,取样点越多)。

      缺点:无法识别圆弧,半圆,和圆的关系。这个应该优化一下,通过周长公式就可以搞定。我是懒得弄啦。

      Demo样式:


      下面是核心代码部分,具体需要Demo的可以去我的git仓库下载来看效果。git仓库地址:git@git.oschina.net:coolnan/Finger_Cycle.git

package com.test.xiaonanfingercycle;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by playcrab on 16/10/20.
 */
public class MainActivity extends AppCompatActivity {
    private static final float RADIUS_OFFSET = 15.0f; //半径取样偏移值
    private static Point first_point;
    private static Point far_point;
    private static Point center_point;
    private float distance;
    private List<Point> points;
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) this.findViewById(R.id.tv);
        points = new ArrayList<Point>();
    }

    /**
     *
     * @param event
     * @return true
     * 触摸事件拦截
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                tv.setText("");
                far_point = null;
                distance = 0.0f;
                first_point = new Point(event.getX(),event.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                Point pt = new Point(event.getX(),event.getY());
                float temp = getDistance(first_point,pt);
                if(distance <= temp){
                    distance = temp;
                    far_point = new Point(pt.getPositionX(),pt.getPositionY());
                }
                points.add(pt);
                break;
            case MotionEvent.ACTION_UP:
                center_point = new Point((first_point.getPositionX()+far_point.getPositionX())/2,(first_point.getPositionY()+far_point.getPositionY())/2);
                boolean cycle = isCycle(center_point,points);
                tv.setText(tv.getText().toString()+"\n"+"是否划圆:"+ cycle);
                break;
        }
        return true;
    }

    /**
     *
     * @param A
     * @param B
     * @return distance
     * 计算两点之间距离
     */
    private float getDistance(Point A,Point B){
        float dis = (A.getPositionX()-B.getPositionX())*(A.getPositionX()-B.getPositionX())+(A.getPositionY()-B.getPositionY())*(A.getPositionY()-B.getPositionY());
        return (float) Math.sqrt(dis);
    }

    /**
     *
     * @param ct_point
     * @param p
     * @return 是否为圆
     * 计算圆心到散列点之间的距离
     */
    private boolean isCycle(Point ct_point,List<Point> p){
        boolean isCycle = false;
        int size = p.size();
        if(size >30){
            size = size/2;
        }
        int not_cycle =0,is_cycle = 0;
        for(int i=0;i<size;i++){
            Point tmp = p.get(i);
            float radiu = getDistance(ct_point,tmp);
            if(Math.abs(distance/2-radiu)<=RADIUS_OFFSET){
                is_cycle++;
            }else{
                not_cycle++;
            }
            tv.setText("半径:"+distance/2+" 半径差值:"+Math.abs(distance/2-radiu)+" 取样点个数:"+size+" 达到半径:"+is_cycle+" 不达半径:"+not_cycle);
        }

        if(not_cycle > is_cycle){
            isCycle = false;
        }else{
            isCycle = true;
        }
        p.clear();
        return  isCycle;
    }

}


阅读更多
换一批

没有更多推荐了,返回首页