View基礎(chǔ)概念
位置參數(shù)
- top务漩、left瓢阴、right夏志、bottom
大小均是基于父容器的左或上的距離咐蚯,由此可計算View自身的寬高 - translationX童漩、translationY
Android3.0后新增加的,相對父容器的偏移量春锋,屬性動畫改變的就是這類的參數(shù)
通過get/set方法調(diào)用
View在平移過程中改變的是偏移量
MotionEvent相關(guān)方法
getX矫膨、getY
相對于當(dāng)前View左上角的x、y坐標(biāo)getRawX看疙、getRawY
相對于手機(jī)屏幕左上角的x豆拨、y坐標(biāo)ViewConfiguration
// 獲取系統(tǒng)能識別的被認(rèn)為是滑動的最小距離
ViewConfiguration.get(getContext()).getScaledTouchSlop();
// 允許Fling手勢動作的最小值
ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity();
// 允許Fling手勢動作的最大值
ViewConfiguration.get(getContext()).getScaledMaximumFlingVelocity();-
GestureDetector
手勢識別
GestureDetector mGestureDetector = new GestureDetector(getApplicationContext(), this);
// 解決長按屏幕無法拖動
mGestureDetector.setIsLongpressEnabled(false);
// 觸摸屏幕時
@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) { } // 手指快速滑動時,此時也會不斷調(diào)用onScroll @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; }
Activity事件托管給GestureDetector
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
View事件托管給GestureDetector
mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
- VelocityTracker
速度追蹤
if(mVelocityTracker == null){
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
一段時間內(nèi)手指滑過的像素數(shù)能庆,下面是1000毫秒滑動的速度
// 設(shè)置單位
mVelocityTracker.computeCurrentVelocity(1000);
// 獲取1秒內(nèi)x方向滑動像素
int xVelocity = (int) mVelocityTracker.getXVelocity();
重置和回收的方法
mVelocityTracker.clear();
mVelocityTracker.recycle();
View的滑動
按正常理解施禾,在屏幕坐標(biāo)系中,向右滑動為正搁胆,向左滑動為左
- scrollTo/scrollBy
Scroller滑動方式只能滑動內(nèi)容
實際scrollTo/scrollBy滑動時相反
View左邊緣在內(nèi)容的右邊時為正
View上邊緣在內(nèi)容的下邊時為正
Scroller mScroller = new Scroller(mContext);
// 開始位置—>終點位置弥搞、時間
mScroller.startScroll(getScrollX(), 0, dx, 0, 500);
private void smoothScrollTo(int destX, int destY){
int scrollX = getScrollX();
int deltaX = destX - scrollX;
// 滑動的位置-當(dāng)前位置就是1000ms內(nèi)滑動的距離
mScroller.startScroll(scrollX, 0, deltaX, 0, 1000);
invalidate();
}
@Override
public void computeScroll(){
if(mScroller.computeScrollOffset()){
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
invalidate方法導(dǎo)致View重繪,draw方法會調(diào)用computeScroll方法
computeScrollOffset方法獲取scrollX和scrollY渠旁,就是當(dāng)前應(yīng)該滑動到的新位置
通過scrollTo方法來滑動
整個原理就是插值器通過通過時間流逝百分比計算出當(dāng)前屬性值改變百分比攀例,再通過估值器計算出改變后具體的屬性值
上面的過程就會實現(xiàn)彈性滑動,就是將一次大的滑動分成若干次小的滑動
- 動畫
ObjectAnimator.ofFloat(view, "translationX", 0, 100).setDuration(100).start(); - LayoutParams布局參數(shù)
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)button.getLayoutParams();
params.width += 100;
params.leftMargin += 100;
// 兩種設(shè)置方式
// button.setLayoutParams(params);
// button.requestLayout();
View彈性滑動
- Scroller
使用Scroller顾腊,View普通滑動已經(jīng)總結(jié)了粤铭。主要是配合computeScroll方法的使用 - 動畫
動畫本身就具備這樣的功能,可以通過ObjectAnimator或ValueAnimator實現(xiàn)
ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(200);
animator.addUpdateListener(new AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animator){
// 根據(jù)時間流逝得到值的百分比
int fraction = (int)animator.getAnimatedFraction();
mButton.scrollTo(startX + deltaX * fraction, 0);
}
});
動畫在這里只提供當(dāng)前值百分比計算杂靶,與Scroller類似
-
延時實現(xiàn)分段滑動
比如距離100像素梆惯,時間1000毫秒酱鸭,分30次小的滑動,每次滑動延時30毫秒
private View view;
private int mCount = 0;
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
mCount++;
if(mCount <= 30){
// 分30次垛吗,計算每次移動的位置
float fraction = mCount/30.0f;
int scrollX = (int) (fraction * 100);
view.scrollTo(-scrollX, 0);
handler.sendEmptyMessageDelayed(0, 30);
}} }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); view = findViewById(R.id.text_view); handler.sendEmptyMessageDelayed(0, 5000); }
這里scrollTo滑動的只是View的內(nèi)容凹髓,不是自身