Android開(kāi)發(fā)藝術(shù)探索筆記 ——View(一)
View的基礎(chǔ)知識(shí)
什么是View
View是Android中所有控件的基類。是一種界面層控件的抽象。
View的位置參數(shù)
參數(shù)名 | 獲取方式 | 含義 |
---|---|---|
top | getTop() | View左上角縱坐標(biāo) |
left | getLeft() | View左上角橫坐標(biāo) |
bottom | getBottom() | View右下角縱坐標(biāo) |
right | getRight() | View右下角橫坐標(biāo) |
View:x/y | getX()/getY() | View左上角坐標(biāo) |
translationX | getTranslationX() | View左上角相對(duì)于父容器的偏移量 |
translationY | getTranslationY() | View左上角相對(duì)于父容器的偏移量 |
MotionEvent:x/y | event.getX()/event.getY() | 點(diǎn)擊事件相對(duì)于View左上角的坐標(biāo) |
MotionEvent:rawX/rawY | event.getRawX()/event.getRawY() | 點(diǎn)擊事件相對(duì)于手機(jī)屏幕左上角的坐標(biāo) |
MotionEvent
- ACTION_DOWN
- ACTION_MOVE
- ACTION_UP
MotionEvent獲取點(diǎn)擊事件x,y坐標(biāo):
getX/getY 相對(duì)于View左上角
getRawX/getRawY 相對(duì)于手機(jī)屏幕左上角
//在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);
}
}
//對(duì)于View,可以使用setOnTouchListener()方法來(lái)監(jiān)聽(tīng)touch events而不需要繼承現(xiàn)有的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
滑動(dòng)的最小距離,常量留搔,和設(shè)備有關(guān)。
//獲取方式:
ViewConfiguration.get(getContext()).getScaledTouchSlop();
VelocityTracker
學(xué)習(xí)資料:
1.https://developer.android.com/training/gestures/movement.html
追蹤手指滑動(dòng)的速度
使用過(guò)程:
//在View的onTouchEvent方法中
VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMoveMent(event);
//時(shí)間間隔設(shè)為1000ms
tracker.computeCurrentVelocity(1000);
int Vx = (int)velocityTracker.getXVelocity();
int Vy = (int)VelocityTracker.getYVelocity();
//不再使用的時(shí)候铛铁,需要清除并回收
velocityTracker.clear();
velocityTracker.recycle();
GestureDetector
手勢(shì)監(jiān)測(cè):單擊隔显,滑動(dòng),長(zhǎng)按饵逐,雙擊等等括眠。
使用方法:
- 1.實(shí)例化
GestureDetectorCompat
類 - 2.如需監(jiān)測(cè)所有的手勢(shì),則實(shí)現(xiàn)
GestureDetector.OnGestureListener
接口和GestureDetector.OnDoubleTapListener
接口倍权。 - 3.若只需監(jiān)測(cè)部分手勢(shì)掷豺,則繼承
GestureDetector.SimpleOnGestureListener
類。
//監(jiān)測(cè)所有的手勢(shì)
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);
//實(shí)例化GestureDetectorCompat
mDetector = new GestureDetectorCompat(this,this);
//將雙擊事件交給GestureDetectorCompat監(jiān)聽(tīng)
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;
}
}
//監(jiān)測(cè)部分手勢(shì)
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
彈性滑動(dòng)對(duì)象薄声,用于實(shí)現(xiàn)View的彈性滑動(dòng)当船。
學(xué)習(xí)資料:
1.Android Scroller完全解析,關(guān)于Scroller你所需知道的一切
2.Animating a Scroll Gesture
Scroller的基本用法:
- 1.創(chuàng)建Scroller實(shí)例
- 2.調(diào)用
startScroll()
方法來(lái)初始化 - 3.重寫View的
computeScroll()
方法默辨,并在其內(nèi)部完成平滑移動(dòng)的邏輯德频。
View的滑動(dòng)
三種方式實(shí)現(xiàn)View的滑動(dòng):
- 1.View的
ScrollTo
和ScrollBy
方法。 - 2.動(dòng)畫
- 3.改變View的LayoutParams使View重新布局從而實(shí)現(xiàn)滑動(dòng)
使用ScrollTo和ScrollBy
- ScrollTo相對(duì)于初始位置滾動(dòng)某段距離缩幸。
- ScrollBy相對(duì)于當(dāng)前位置滾動(dòng)某段距離壹置。
- 其中,水平方向表谊,正值為向左滾動(dòng)钞护,負(fù)值為向右滾動(dòng)。豎直方向铃肯,正值為向上滾動(dòng)患亿,負(fù)值為向下滾動(dòng)。
- 兩個(gè)
Scroll
方法的滾動(dòng)都是跳躍式的,沒(méi)有平滑移動(dòng)的效果步藕。
使用動(dòng)畫
使用動(dòng)畫操作View的translationX
和translationY
兩個(gè)屬性來(lái)移動(dòng)View惦界。可使用屬性動(dòng)畫/View動(dòng)畫咙冗。
View動(dòng)畫是對(duì)View的影像進(jìn)行操作的沾歪。也就是說(shuō)View動(dòng)畫并不能真正的改變View的位置。
屬性動(dòng)畫是真正改變View的位置雾消,但它是從Android3.0開(kāi)始推出的灾搏。
//View動(dòng)畫實(shí)現(xiàn)移動(dòng)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="500"
android:toYDelta="1000"
android:duration="10000"
android:interpolator="@android:anim/linear_interpolator"
/>
</set>
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
layout.setAnimation(animation);
animation.start();
//使用屬性動(dòng)畫實(shí)現(xiàn)移動(dòng)
ObjectAnimator.ofFloat(layout,"translationX",0,100).setDuration(1000).start();
改變布局參數(shù)
改變布局參數(shù)LayoutParams
。
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) layout.getLayoutParams();
params.width+=1000;
params.leftMargin+=1000;
layout.requestLayout();
三種滑動(dòng)方式的對(duì)比
方式 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
scrollTo/scrollBy | 原生方法立润,操作簡(jiǎn)單狂窑,適用于對(duì)內(nèi)容的滑動(dòng) | 不能滑動(dòng)View本身 |
動(dòng)畫 | 操作簡(jiǎn)單,適用于沒(méi)有交互的View和復(fù)雜的動(dòng)畫效果 | |
改變布局參數(shù) | 適用于有交互的View | 操作較復(fù)雜 |
彈性滑動(dòng)
將一次時(shí)間長(zhǎng)的滑動(dòng)分成若干次短的滑動(dòng)桑腮。
使用Scroller
//1.創(chuàng)建Scroller
Scroller scroller = new Scroller(context);
...
//2.調(diào)用Scroller的startScroll方法
int scrollX = getScrollX();
int deltaX = destX - scrollX;
scroller.startScroll(scrollX,0,deltaX,0,1000);
invalidate();
//3.復(fù)寫computeScroll()方法
@Override
public void computeScroll(){
if(scroller.computeScrollOffset()){
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();
}
}