自定義ScrollView 下拉上拉回彈,阻尼效果

package com.customWidget;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;

/**
 * 自定義ScrollView
 */
public class MyScrollView extends ScrollView {
	private View inner;// 孩子

	private float y;// 座標

	private Rect normal = new Rect();// 矩形空白

	public MyScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	// android:fadingEdge=”none”
	@Override
	public void setFadingEdgeLength(int length) {
		// TODO Auto-generated method stub
		length = 0;
		super.setFadingEdgeLength(length);
		
	}
	/***
	 * 根據 XML 生成視圖工作完成.該函數在生成視圖的最後調用,在所有子視圖添加完之後. 即使子類覆蓋了 onFinishInflate
	 * 方法,也應該調用父類的方法,使該方法得以執行.
	 */
	@Override
	protected void onFinishInflate() {
		if (getChildCount() > 0) {
			inner = getChildAt(0);// 獲取其孩子
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (inner != null) {
			commOnTouchEvent(ev);
		}
		return super.onTouchEvent(ev);
	}

	/***
	 * 觸摸事件
	 * 
	 * @param ev
	 */
	public void commOnTouchEvent(MotionEvent ev) {
		int action = ev.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			y = ev.getY();// 獲取點擊y座標
			break;
		case MotionEvent.ACTION_UP:
			if (isNeedAnimation()) {
				animation();
			}
			break;
		case MotionEvent.ACTION_MOVE:
			final float preY = y;
			float nowY = ev.getY();
			int deltaY = (int) (preY - nowY);// 獲取滑動距離

			y = nowY;
			// 當滾動到最上或者最下時就不會再滾動,這時移動佈局
			if (isNeedMove()) {
				if (normal.isEmpty()) {
					// 填充矩形,目的:就是告訴this:我現在已經有了,你鬆開的時候記得要執行迴歸動畫.
					normal.set(inner.getLeft(), inner.getTop(),
							inner.getRight(), inner.getBottom());
				}
				// 移動佈局
				inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2,
						inner.getRight(), inner.getBottom() - deltaY / 2);
			}
			break;

		default:
			break;
		}
	}

	/***
	 * 開啓動畫移動
	 */
	public void animation() {
		// 開啓移動動畫
		TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(),
				normal.top);
		ta.setDuration(300);
		inner.startAnimation(ta);
		// 設置回到正常的佈局位置
		inner.layout(normal.left, normal.top, normal.right, normal.bottom);
		normal.setEmpty();// 清空矩形

	}

	/***
	 * 是否需要開啓動畫
	 * 
	 * 如果矩形不爲空,返回true,否則返回false.
	 * 
	 * 
	 * @return
	 */
	public boolean isNeedAnimation() {
		return !normal.isEmpty();
	}

	/***
	 * 是否需要移動佈局 inner.getMeasuredHeight():獲取的是控件的高度
	 * getHeight():獲取的是當前控件在屏幕中顯示的高度
	 * 
	 * @return
	 */
	public boolean isNeedMove() {
		int offset = inner.getMeasuredHeight() - getHeight();
		int scrollY = getScrollY();
		// 0是頂部,後面那個是底部
		if (scrollY == 0 || scrollY == offset) {
			return true;
		}
		return false;
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章