getTop:获取到的,是view自身的顶边到其父布局顶边的距离
getLeft:获取到的,是view自身的左边到其父布局左边的距离
getRight:获取到的,是view自身的右边到其父布局左边的距离
getBottom:获取到的,是view自身的底边到其父布局顶边的距离
getX():获取点击事件相对控件左边的x轴坐标,即点击事件距离控件左边的距离
getY():获取点击事件相对控件顶边的y轴坐标,即点击事件距离控件顶边的距离
getRawX():获取点击事件相对整个屏幕左边的x轴坐标,即点击事件距离整个屏幕左边的距离
getRawY():获取点击事件相对整个屏幕顶边的y轴坐标,即点击事件距离整个屏幕顶边的距离
ps:在触摸事件中这些值是随着触摸滑动事件一直变化
系统所能识别滑动的最小距离,手指在屏幕上滑动小于这个距离时,系统认为没有滑动。这是一个常量和设备有关,不同的设备这个值有所不同。(栗子如下:夜神模拟器打印出的常量)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate: "+ViewConfiguration.get(this).getScaledTouchSlop());
}
// log:04-08 09:35:48.274 2726-2726/? I/aaa: onCreate: 12
速度追踪,用于追踪手指在滑动过程中的速度。如下栗子:在view的ontouchEvent中追踪滑动速度。
//1、添加事件
velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
//2、设置时间段
velocityTracker.computeCurrentVelocity(1000);
//3、获得x,y上,某时间段移动的像素
int x = (int) velocityTracker.getXVelocity();
int y = (int) velocityTracker.getYVelocity();
//4、不用时回收
velocityTracker.clear();
velocityTracker.recycle();
ps:速度有正负
速度=(终点位置-起点位置)/时间段
手势检测用于辅助检测用户的单击、长摁、滑动、双击等行为。
基本使用:
// 1创建对象
参数为: GestureDetector.OnGestureListener类型,OnGestureListener是一个接口我们可以实现他
GestureDetector gestureDetector = new GestureDetector(参数)
栗子:
final GestureDetector gestureDetector = new GestureDetector(new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
});
//2 接管目标view的onTouchEvent方法(如下举例子)
findViewById(R.id.text).setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// 接管
return gestureDetector.onTouchEvent(event);
}
});
接口方法详解:
onDown
手指轻触屏幕一瞬间,由一个ACTION_DOWN触发
onShowPress
手指轻触屏幕,尚未松开或拖动由一个ACTION_DOWN触发。注意和onDown区别,这里强调的是没有松开,或拖动的状态。
onSingleTapUp
单击行为
onScroll
滑动行为 一个ACTION_DOWN多个ACTION_MOVE
onLongPress
长按行为
onFling
用户按下触摸屏快速滑动松开,一个ACTION_DOWN多个ACTION_MOVE,一个ACTION_UP。属于快速滑动行为。
ps:
实际开发中可以不使用GestureDetector,完全可以在自己的view中的onToucEvent中实现所有的监听。
参考建议:如果只是滑动相关监听就使用onToucEvent,如果是监听双击行为再用GestureDetector(如下)
//设置双击监听器
mGestureDetector.setOnDoubleTapListener(new doubleTapListener());
private class doubleTapListener implements GestureDetector.OnDoubleTapListener
参考:https://blog.csdn.net/harvic880925/article/details/39520901
弹性滑动对象,用于实现view的弹性滑动。我们知道使用使用view的ScrollTo、ScrollBy方法来进行滑动时,滑动的动作是瞬间完成,用户体验不好。而使用Scroller可以让滑动的动作在时间段完成,增加用户体验。
ps:Scroller的使用代码固定,详细参考下面的view的滑动方式中详解。
栗子:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:id="@+id/layout">
<Button
android:id="@+id/btn_scrollto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ScrollTo"/>
<Button
android:id="@+id/btn_scrollby"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ScrollBy"/>
</LinearLayout>
package com.example.administrator.androidview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "aaa";
private LinearLayout mLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayout = (LinearLayout) findViewById(R.id.layout);
findViewById(R.id.btn_scrollto).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("test", "点击前getScrollX值:" + mLayout.getScrollX());
Log.e("test", "点击前getScrollY值:" + mLayout.getScrollY());
mLayout.scrollTo(-50, -50);
Log.e("test", "点击后getScrollX值:" + mLayout.getScrollX());
Log.e("test", "点击后getScrollY值:" + mLayout.getScrollY());
}
});
findViewById(R.id.btn_scrollby).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLayout.scrollBy(-50, -50);
}
});
}
}
二者的源码:
ScrollTo:
public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
postInvalidateOnAnimation();
}
}
}
ScrollBy:
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}
从源码得知scrollBy其实就是调用了ScrollTo
区别:
1、ScrollTo实现了基于所传参数的绝对滑动
2、ScrollBy实现了基于当前位置的相对滑动
大白话就是ScrollTo滑动到指定位置,ScrollBy滑动到相对当前位置的指定距离。
源码中mScrollX、mScrollY 的理解:
ScrollTo/ScrollBy的理解:
ScrollTo/ScrollBy只能改变view内容的位置,不能改变view本身的位置(参考栗子运行图分析)
如上就是我们前面代码中运行的草图,首先是一个LinearLayout,里面有两个按钮我们一看xml布局就知道。
1、我们结合图很快就理解了mScrollX,mScrollY。
2、可以看到我们让LinearLayout直行了ScrollTo/ScrollBy这时两个button滑动,而LinearLayout本身没滑动。而正好验证了我们上文对“ScrollTo/ScrollBy的理解”
再次深入解释 mScrollX、mScrollY:
动画我们都熟悉啊
view动画移动view栗子:
TranslateAnimation anim = new TranslateAnimation(0, 100, 0, 0);
anim.setDuration(300);
anim.start();
btn.setAnimation(anim);
属性动画移动view的栗子:
ObjectAnimator anim = ObjectAnimator.ofFloat(btn, "translationX", 0, 100);
anim.setDuration(300);
anim.start();
view动画:
1、view动画是对view的影响做操作,他并不能真正改变view的布局参数。
2、如果希望view动画后的状态得以保留,必须设置fillAfter为true,反之动画结束时,view回复原来的状态。
3、使用属性动画可以解决上面view动画的缺点
ps:自己写个demo搞个点击事件,设置好view动画后,看看点击原来位置生效,还是动画后的位置生效。
自定义个view:
package com.example.administrator.androidview;
import android.content.Context;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
/**
* Create by SunnyDay on 2019/04/08
*
* 随手指滑动的AppCompatImageView
*/
public class MoveView extends AppCompatImageView {
public MoveView(Context context, AttributeSet attrs) {
super(context, attrs);
}
int lastX = 0;
int lastY = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
//1、用户手指的坐标 用户滑动时坐标不停变化(事件封装在MotionEvent)
int x = (int) event.getX();
int y = (int) event.getY();
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
lastX = x; //2、 触发down事件时记录下触摸位置
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
// 计算滑动距离
int offsetX = x - lastX;// 滑动一段距离后:新的x坐标 - 上次记录的位置
int offsetY = y - lastY;
// 不断修改位置 这种方法也行
// layout(getLeft() + offsetX, getTop() + offsetY,
// getRight() + offsetX , getBottom() + offsetY);
// 使用布局参数
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
lp.leftMargin = getLeft() + offsetX;
lp.topMargin = getTop() + offsetY;
setLayoutParams(lp);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
我们手指滑动时,view跟着滑动。
这里总结了view的基础知识和几种滑动方式,下节总结view的弹性滑动。
View的事件体系(二)view的弹性滑动
本文来自<安卓开发艺术探索>笔记总结