Android 快速学习onTouch,并完成实验单点滑动,双点触控,多点触控。(一)单点触控,拖动目标滑动
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