Android 快速学习onTouch,并完成实验单点滑动,双点触控,多点触控。(一)单点触控,拖动目标滑动

版权声明:@jj--(Google E-mail t281138580) https://blog.csdn.net/qq_35323561/article/details/80231994

Android 快速学习onTouch,并完成实验单点滑动,双点触控,多点触控。

(一)单点触控,拖动目标滑动

话不多说先来看看onTouchEvent方法。

/**
 * 屏幕触控事件
 * @param event
 * @return
 */
@Override
public boolean onTouchEvent(MotionEvent event) {
    return super.onTouchEvent(event);
    
}

参数传入一个MotionEvent类

我们看看MotionEvent类几个比较重要的属性和方法。

常量:

  • MotionEvent.ACTION_DOWN:当屏幕检测到第一个触点按下之后就会触发到这个事件。
  • MotionEvent.ACTION_MOVE:当触点在屏幕上移动时触发,触点在屏幕上停留也是会触发的,主要是由于它的灵敏度很高,而我们的手指又不可能完全静止(即使我们感觉不到移动,但其实我们的手指也在不停地抖动)。
  • MotionEvent.ACTION_UP:当触点松开时被触发。
  • MotionEvent.ACTION_POINTER_DOWN:当屏幕上已经有触点处于按下的状态的时候,再有新的触点被按下时触发。
  • MotionEvent.ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)触发。
  • MotionEvent.ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界.

方法:

  • getAction():返回动作类型,如上常量。
  • getX()/getY():获得事件发生时,触摸的中间区域的X/Y坐标,由这两个函数获得的X/Y值是相对坐标,相对于消费这个事件的视图的左上角的坐标。 
  • getDownTime() :按下开始时间 
  • getEventTime() : 事件结束时间 
  • getPointerCount():获取触控点的数量,比如2则可能是两个手指同时按压屏幕 
  • getX(nID):获取第nID个触控点的x位置 
  • getY(nID):获取第nID个触控点的y位置 

实验1:单击控件,控件跟随手指移动。

先上效果图:

布局代码:

shape_tv_cir.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <corners android:radius="360dp"/>
    <solid android:color="#ff0000"/>
</shape>

其他几个shape一样只改个色码值。

activity_main.xml

<?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">

    <TextView
        android:id="@+id/tv_cir1"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="100dp"
        android:background="@drawable/shape_tv_cir"/>

    <TextView
        android:id="@+id/tv_cir2"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="100dp"
        android:background="@drawable/shape_tv_cir2"/>
    
    <TextView
        android:id="@+id/tv_cir3"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="100dp"
        android:background="@drawable/shape_tv_cir3"/>

</RelativeLayout>

界面代码:

看注释即可↓

public class SingleTouchActivity extends AppCompatActivity {

    /**
     * UI
     */
    private TextView tvCir1, tvCir2, tvCir3;

    /**
     * Data & other
     */
    private static final String TAG = "onTouch";
    //点击位置的范围,越大范围越容易触控到。
    private static final int TOUCHRANGE = 30;

    //用于记录各个点的位置
    private float Cir1X = 0;
    private float Cir1Y = 0;
    private float Cir2X = 0;
    private float Cir2Y = 0;
    private float Cir3X = 0;
    private float Cir3Y = 0;

    //各个点的状态-是否被触控到 true按下 false反之
    private boolean Cir1State = false;
    private boolean Cir2State = false;
    private boolean Cir3State = false;

    //状态栏高度
    private int statusBarHeight = 0;
    //标题栏高度
    private int contentViewTop = 0;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_singletouch);
        initView();
    }

    private void initView() {
        tvCir1 = (TextView) findViewById(R.id.single_tv_cir1);
        tvCir2 = (TextView) findViewById(R.id.single_tv_cir2);
        tvCir3 = (TextView) findViewById(R.id.single_tv_cir3);

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            //状态栏高度
            Rect frame = new Rect();
            getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
            statusBarHeight = frame.top;
            //标题栏高度
            Window window = getWindow();
            contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();

            //这里注意不能放在onCreate方法里面....那会儿控件还没加载完成呢
            //通过获取Top Left 来获取View的位置
            Cir1X = tvCir1.getLeft();
            //onTouch事件里的x,y是相对于整个屏幕而言的  activity里的控件的位置是其父布局为参照物
            //所以需要加一个状态栏+标题栏的高度
            Cir1Y = tvCir1.getTop() + contentViewTop + statusBarHeight;
            Cir2X = tvCir2.getLeft();
            Cir2Y = tvCir2.getTop() + contentViewTop + statusBarHeight;
            Cir3X = tvCir3.getLeft();
            Cir3Y = tvCir3.getTop() + contentViewTop + statusBarHeight;
        }
    }

    /**
     * 屏幕触控事件
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            //判断手指按下的位置 是否在目标周围  是的话在滑动时控件跟随滑动 反之...
            case MotionEvent.ACTION_DOWN:
                Log.i(TAG, "手指按下了 X:" + event.getX() + " Y:" + event.getY());

                if (onTouchRange(Cir1X, Cir1Y, event)) {
                    Cir1State = true;
                } else if (onTouchRange(Cir2X, Cir2Y, event)) {
                    Cir2State = true;
                } else if (onTouchRange(Cir3X, Cir3Y, event)) {
                    Cir3State = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i(TAG, "手指在滑动 X:" + event.getX() + " Y:" + event.getY());
                if (Cir1State) {
                    tvCir1.setX(event.getX());
                    //onTouch事件里的x,y是相对于整个屏幕而言的  activity里的控件的位置是其父布局为参照物
                    //所以移动时的y轴要扣除一个状态栏+标题栏的高度
                    tvCir1.setY(event.getY() - statusBarHeight - contentViewTop);
                } else if (Cir2State) {
                    tvCir2.setX(event.getX());
                    tvCir2.setY(event.getY() - statusBarHeight - contentViewTop);
                } else if (Cir3State) {
                    tvCir3.setX(event.getX());
                    tvCir3.setY(event.getY() - statusBarHeight - contentViewTop);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (Cir1State) {
                    Cir1X = event.getX();
                    Cir1Y = event.getY();
                } else if (Cir2State) {
                    Cir2X = event.getX();
                    Cir2Y = event.getY();
                } else if (Cir3State) {
                    Cir3X = event.getX();
                    Cir3Y = event.getY();
                }
                Cir1State = false;
                Cir2State = false;
                Cir3State = false;
                break;
            default:

                break;
        }
        return true;
    }

    /**
     * @param x     目标x     * @param y     目标y     * @param event
     * @return true 在范围内 反之...
     */
    private boolean onTouchRange(float x, float y, MotionEvent event) {
        //判断x轴范围
        if ((event.getX() - TOUCHRANGE) < x && (event.getX() + TOUCHRANGE) > x) {
            //判断y轴范围
            if ((event.getY() - TOUCHRANGE) < y && (event.getY() + TOUCHRANGE) > y) {
                return true;
            }
        }
        return false;
    }
}

思路点拨:先判断是否按下,并且位置在目标上或者目标范围使其按住滑动有效(因为有的东西可能非常小,用户很难点击到,我们给这个加大范围,便于用户操作)。按住时目标跟随手指滑动移动(获取xy位置,赋值给目标就好)--目标可能是控件。松开清除状态,并更新位置。


好了今天先到这里---2018/05/07 23:34

猜你喜欢

转载自blog.csdn.net/qq_35323561/article/details/80231994