Android回彈阻尼效果的簡單實現,非基於ListView,ScrollView

版權說明 :《Android回彈阻尼效果的簡單實現,非基於ListView,ScrollView於當前CSDN博客乘月網屬同一原創,轉載請說明出處,謝謝。


ReboundEffects

好久沒有寫Android博客了,這段時間有點浮躁,靜不下心來寫。趁今天週五心情好點,寫個簡單點的技術實現。

先簡單說說回彈阻尼效果的思路,先自定義一個ViewGroup ----- ReboundEffectsView,通過手勢的上下滑動距離差不斷改變其子View(一般都是子ViewGroup)的相對於該ReboundEffectsView的位置(座標),當手勢爲釋放(action_up)或取消(action_cancel)時,重置子View最初始相對ReboundEffectsView的位置,最初始的位置值應在處理滑動事件前保存下來以用來重置。

效果圖

Demo項目下載地址:https://github.com/ausboyue/ReboundEffects

進入代碼板塊

1.在自定義ReboundEffectsView中重寫onFinishInflate方法,XML佈局完成加載後獲取其第一個子View(使用該ReboundEffectsView時應保證其只有且只有一個子View,唯一的獨生子,我就叫它太子View):

/**
 * XML佈局完成加載
 */
@Override
protected void onFinishInflate() {
	super.onFinishInflate();
	if (getChildCount() > 0) {
		mPrinceView = getChildAt(0);// 獲得子View,太子View
	}
}

2.onTouchEvent方法,分別對ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL事件進行處理:

/**
 * Touch事件
 */
@Override
public boolean onTouchEvent(MotionEvent e) {
	if (null != mPrinceView) {
		switch (e.getAction()) {
		case MotionEvent.ACTION_DOWN:
			onActionDown(e);
			break;
		case MotionEvent.ACTION_MOVE:
			return onActionMove(e);
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:
			onActionUp(e);// 當ACTION_UP一樣處理
			break;
		}
	}
	return super.onTouchEvent(e);
}

3.onActionDown中保存子View的初始上下高度位置:

/**
 * 手指按下事件
 */
private void onActionDown(MotionEvent e) {
	mVariableY = e.getY();
	/**
	 * 保存mPrinceView的初始上下高度位置
	 */
	mInitTop = mPrinceView.getTop();
	mInitBottom = mPrinceView.getBottom();
}

4.核心代碼,onActionMove中,主要是判斷手勢移動事件是否爲上下滑動事件,是的話根據上下滑動的絕對距離重繪子View的位置(這裏的絕對距離除以2了,目的是放緩子View的移動速度),並在以後的Touch拿到直接的控制權,返回true:

/**
 * 手指滑動事件
 */
private boolean onActionMove(MotionEvent e) {
	float nowY = e.getY();
	float diff = (nowY - mVariableY) / 2;
	if (Math.abs(diff) > 0) {// 上下滑動
		// 移動太子View的上下位置
		mPrinceView.layout(mPrinceView.getLeft(), mPrinceView.getTop() + (int) diff, mPrinceView.getRight(),
				mPrinceView.getBottom() + (int) diff);
		mVariableY = nowY;
		isEndwiseSlide = true;
		return true;// 消費touch事件
	}
	return super.onTouchEvent(e);
}

5.手指釋放或手勢取消時,則調用onActionUp方法恢復子View的位置:

/**
 * 手指釋放事件
 */
private void onActionUp(MotionEvent e) {
	if (isEndwiseSlide) {// 是否爲縱向滑動事件
		// 是縱向滑動事件,需要給太子View重置位置
		resetPrinceView();
		isEndwiseSlide = false;
	}
}

/**
 * 回彈,重置太子View初始的位置
 */
private void resetPrinceView() {
	TranslateAnimation ta = new TranslateAnimation(0, 0, mPrinceView.getTop() - mInitTop, 0);
	ta.setDuration(600);
	mPrinceView.startAnimation(ta);
	mPrinceView.layout(mPrinceView.getLeft(), mInitTop, mPrinceView.getRight(), mInitBottom);
}

OK,整個自定義View中重寫原生的方法並不多,也不需要自行測量和繪製View,代碼邏輯也足夠精簡,如果有什麼bug或建議可以在下面評論,我會繼續更新博客。


發佈了46 篇原創文章 · 獲贊 181 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章