Android开发艺术探索笔记 ——View(一)
View的基础知识
什么是View
View是Android中所有控件的基类。是一种界面层控件的抽象。
View的位置参数
参数名 | 获取方式 | 含义 |
---|---|---|
top | getTop() | View左上角纵坐标 |
left | getLeft() | View左上角横坐标 |
bottom | getBottom() | View右下角纵坐标 |
right | getRight() | View右下角横坐标 |
View:x/y | getX()/getY() | View左上角坐标 |
translationX | getTranslationX() | View左上角相对于父容器的偏移量 |
translationY | getTranslationY() | View左上角相对于父容器的偏移量 |
MotionEvent:x/y | event.getX()/event.getY() | 点击事件相对于View左上角的坐标 |
MotionEvent:rawX/rawY | event.getRawX()/event.getRawY() | 点击事件相对于手机屏幕左上角的坐标 |
MotionEvent
- ACTION_DOWN
- ACTION_MOVE
- ACTION_UP
MotionEvent获取点击事件x,y坐标:
getX/getY 相对于View左上角
getRawX/getRawY 相对于手机屏幕左上角
//在View或Activity中拦截touch events,重写onTouchEvent方法 @Override public boolean onTouchEvent(MotionEvent event) { int action = MotionEventCompat.getActionMasked(event); switch (action) { case (MotionEvent.ACTION_DOWN): Log.d(TAG,"action down"); return true; case (MotionEvent.ACTION_MOVE): Log.d(TAG,"action move"); return true; case (MotionEvent.ACTION_UP): Log.d(TAG,"action up"); return true; case (MotionEvent.ACTION_CANCEL): Log.d(TAG,"action cancel"); return true; case (MotionEvent.ACTION_OUTSIDE): Log.d(TAG,"action outside"); return true; default: return super.onTouchEvent(event); } } //对于View,可以使用setOnTouchListener()方法来监听touch events而不需要继承现有的View View myView = findViewById(R.id.my_view);myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // ... Respond to touch events return true; }});
TouchSlop
滑动的最小距离,常量,和设备有关。
//获取方式:ViewConfiguration.get(getContext()).getScaledTouchSlop();
VelocityTracker
学习资料:
1.
追踪手指滑动的速度
使用过程:
//在View的onTouchEvent方法中 VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMoveMent(event); //时间间隔设为1000ms tracker.computeCurrentVelocity(1000); int Vx = (int)velocityTracker.getXVelocity(); int Vy = (int)VelocityTracker.getYVelocity(); //不再使用的时候,需要清除并回收 velocityTracker.clear(); velocityTracker.recycle();
GestureDetector
手势监测:单击,滑动,长按,双击等等。
使用方法:
- 1.实例化
GestureDetectorCompat
类 - 2.如需监测所有的手势,则实现
GestureDetector.OnGestureListener
接口和GestureDetector.OnDoubleTapListener
接口。 - 3.若只需监测部分手势,则继承
GestureDetector.SimpleOnGestureListener
类。
//监测所有的手势public class MainActivity extends Activity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{ private static final String DEBUG_TAG = "Gestures"; private GestureDetectorCompat mDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //实例化GestureDetectorCompat mDetector = new GestureDetectorCompat(this,this); //将双击事件交给GestureDetectorCompat监听 mDetector.setOnDoubleTapListener(this); } @Override public boolean onTouchEvent(MotionEvent event){ this.mDetector.onTouchEvent(event); return super.onTouchEvent(event); } @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString()); return true; } @Override public void onLongPress(MotionEvent event) { Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.toString()); return true; } @Override public void onShowPress(MotionEvent event) { Log.d(DEBUG_TAG, "onShowPress: " + event.toString()); } @Override public boolean onSingleTapUp(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString()); return true; } @Override public boolean onDoubleTap(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); return true; } @Override public boolean onDoubleTapEvent(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString()); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); return true; }}//监测部分手势public class MainActivity extends Activity { private GestureDetectorCompat mDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDetector = new GestureDetectorCompat(this, new MyGestureListener()); } @Override public boolean onTouchEvent(MotionEvent event){ this.mDetector.onTouchEvent(event); return super.onTouchEvent(event); } class MyGestureListener extends GestureDetector.SimpleOnGestureListener { private static final String DEBUG_TAG = "Gestures"; @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString()); return true; } }}
Scroller
弹性滑动对象,用于实现View的弹性滑动。
学习资料:
1. 2.
Scroller的基本用法:
- 1.创建Scroller实例
- 2.调用
startScroll()
方法来初始化 - 3.重写View的
computeScroll()
方法,并在其内部完成平滑移动的逻辑。
View的滑动
三种方式实现View的滑动:
- 1.View的
ScrollTo
和ScrollBy
方法。 - 2.动画
- 3.改变View的LayoutParams使View重新布局从而实现滑动
使用ScrollTo和ScrollBy
- ScrollTo相对于初始位置滚动某段距离。
- ScrollBy相对于当前位置滚动某段距离。
- 其中,水平方向,正值为向左滚动,负值为向右滚动。竖直方向,正值为向上滚动,负值为向下滚动。
- 两个
Scroll
方法的滚动都是跳跃式的,没有平滑移动的效果。
使用动画
使用动画操作View的translationX
和translationY
两个属性来移动View。可使用属性动画/View动画。
View动画是对View的影像进行操作的。也就是说View动画并不能真正的改变View的位置。
属性动画是真正改变View的位置,但它是从Android3.0开始推出的。//View动画实现移动Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate); layout.setAnimation(animation); animation.start();//使用属性动画实现移动ObjectAnimator.ofFloat(layout,"translationX",0,100).setDuration(1000).start();
改变布局参数
改变布局参数LayoutParams
。
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) layout.getLayoutParams(); params.width+=1000; params.leftMargin+=1000; layout.requestLayout();
三种滑动方式的对比
方式 | 优点 | 缺点 |
---|---|---|
scrollTo/scrollBy | 原生方法,操作简单,适用于对内容的滑动 | 不能滑动View本身 |
动画 | 操作简单,适用于没有交互的View和复杂的动画效果 | |
改变布局参数 | 适用于有交互的View | 操作较复杂 |
弹性滑动
将一次时间长的滑动分成若干次短的滑动。
使用Scroller
//1.创建ScrollerScroller scroller = new Scroller(context);...//2.调用Scroller的startScroll方法int scrollX = getScrollX();int deltaX = destX - scrollX;scroller.startScroll(scrollX,0,deltaX,0,1000);invalidate();//3.复写computeScroll()方法@Overridepublic void computeScroll(){ if(scroller.computeScrollOffset()){ scrollTo(scroller.getCurrX(),scroller.getCurrY()); invalidate(); }}