View的滑动
一、View的位置参数(都是相对于父容器的位置)
1.View的位置由左上角点、右下角点来确定的。分别对应(左上的X—getLeft,左上的Y—getTop,右下的X—getRight,右下的Y—getBottom)。
2.View的偏移量(translation):表示左上角相对于父容器的偏移量(当前位置与移动后的位置之差叫做偏移量),默认为0。(进过测试只能通过setTranslation改变Translation,补间动画animation.xml无效)通过getTransaltion获取X,Y
3.View的getX(),getY()(都是左上角的点):X = left + translationX;就是左上角的X坐标加上X的偏移量,Y = top + translationY;(就是左上角Y的坐标,加上Y的偏移量)
4.View的getScaleX(),getScaleY():View的内容的左上角的坐标。(向左滑动为正,向右滑动为负)
解释:
二、介绍VelocityTracker、GestureDetector、Scroller
1.VelocityTrancker
作用:速度追踪,用于追踪手指在滑动过程中的速度(包括水平和竖直方向速度)
使用:①、将event事件添加至Velocity对象中 ②、设置时间:指一段时间划过的像素数 ③、获取X,Y方向滑过的像素数(从左向右为正,从上向下为正)
实例:
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private VelocityTracker mVelocityTracker = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取Velocity mVelocityTracker = VelocityTracker.obtain(); } @Override public boolean onTouchEvent(MotionEvent event) { //将事件对象由该对象掌管 mVelocityTracker.addMovement(event); switch (event.getAction()){ case MotionEvent.ACTION_MOVE: //设置时间间隔:速度指的是一段时间内手指划过的像素数 mVelocityTracker.computeCurrentVelocity(1000); //打印速度 Log.d(TAG,"1秒内滑动X像素数"+mVelocityTracker.getXVelocity()+" Y像素数"+mVelocityTracker.getYVelocity()); break; default: break; } return super.onTouchEvent(event); } }
注意:当调用getXVelocity()方法的时候,就会返回平均速度。(假设我设置1喵,就是说不是等一秒过后才会,返回getXVelocioty(),而是当你调用getXVelocity()利用数学计算出每秒的速度)。
2.GestureDetector
作用:辅助检测用户的单击、滑动、长按、双击等行为(跟onTouchEvent好想没有区别)
使用:①:实现onGestureDetecotr()接口 ②:创建GestureDetector对象 ③:将onTouchEvent的event事件给detector()对象
实例:(每个接口的方法的作用都写在上面)
//创建GestureDetector public class GestureTest extends Activity { GestureDetector detector = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //第一步:用匿名类实现接口,供创建GestureDetector时候使用。 GestureDetector.OnGestureListener gestureListener = 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) { //Touch了滑动一点距离后,拿起手时触发。velocityX表示“拖过”动作在横向的速度,velocityY表示“拖过”动作在纵向时的速度 return false; } }; //第二步:构造方法public GestureDetector(Context context,GestureDetector.OnGestureListener listener) detector = new GestureDetector(this,gestureListener); //解决长按屏幕后无法拖动的现象 detector.setIsLongpressEnabled(false); //监听双击行为 detector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() { //严格单击行为。和onSingleTapUp的区别。触发了onSingleTapConfirmed后不能再紧跟另一个单击行为 @Override public boolean onSingleTapConfirmed(MotionEvent e) { return false; } //双击,由两次连续的单击组成,不能和onSingleTapConfirmed共存 @Override public boolean onDoubleTap(MotionEvent e) { return false; } //发生双击行为,双击期间,DOWN、MOVE、UP都会触发此回调 @Override public boolean onDoubleTapEvent(MotionEvent e) { return false; } }); } //第三步:重写Activity的onTouchEvent()方法,并将点击事件给GestureDetector处理 @Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); } }
3.Scroller
作用:实现View的弹性滑动
使用:下一节详细讲解View的滑动
三、View的滑动
非弹性滑动
1.使用scrollTo/scrollBy
作用:使View的内容的滑动
使用:①、View自带scrollTo/scrollBy方法 ②、scrollTo/scrollBy区别:scrollTo是相对于父控件位置的滑动。scrollBy是相对于上一scroll位置的滑动
private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button)findViewById(R.id.main_textView); btn.scrollTo(30,30); btn.scrollBy(50,50); }
注:根据源码其实scrollBy(int x,int y)调用scrollTo(int x,int y);(源码分析详见Android开发艺术探索P130)
2.使用动画(AnimationDrawable 除开 属性动画)
详见Drawable类及XMLDrawable的使用 :(只是View视图上的改变,并不改变View的点击位置 但是属性动画可以)
弹性滑动:Scroller来实现有过度效果
第一种:Scroller
1.作用:实现滑动效果。(View内容的滑动)
2.使用流程:创建Scroller对象,之后设定scroller的初始值,并进行重绘,在重绘之前需要重写computeScroll()方法,因为重绘的时候系统会自动调用该方法,在computeScroll()方法中,我们利用computeScrollOffset()方法获取当前应该移动的距离,并用scrollTo()进行移动。
private Scroller mScroller; public TestLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); //创建Scroller mScroller = new Scroller(context); } //滑动到指定位置,参数为滑动的终点 private void smoothScrollTo(int destX,int destY){ //获取当前内容的左上角X坐标 int scrollX = getScrollX(); Log.d("TestView", scrollX + "-scroll," + destX + "-destX"); //获取滑动的距离 int deltaX = scrollX - destX; //该方法初始话scroller对象的参数 mScroller.startScroll(scrollX, 0, deltaX, 0, 1000); //重绘,能够调用computeScroll()方法 invalidate(); } @Override public boolean onTouchEvent(MotionEvent event) { //当按下时调用该方法 switch (event.getAction()){ case MotionEvent.ACTION_DOWN: smoothScrollTo((int)event.getRawX(),0); break; } return super.onTouchEvent(event); } //当重绘时候调用该方法 @Override public void computeScroll() { super.computeScroll(); //根据时间流逝(重绘需要时间)的百分比计算scrollX和scrollY if (mScroller.computeScrollOffset()){ //获取当前的scrollX和scrollY scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); //执行重绘 postInvalidate(); } }
第二种:利用Handler来定时移动 (不展开了)
第三种:使用空View改变View的布局 (真正能改变View在layout中的位置)
使用空View改变该View的布局参数
使用:建立空视图(Button1)在View(Button)的左边
在MainActivity中
MarginLayoutParams params = (MarginLayoutParams)mButton1.getLayoutParams();
params.width + = 100;
params.height += 100;
mButton1.setLayoutParams(params);
(这就能够使Button向右移)