天天看點

Android自定義控件(四)——讓每一個Activity UI都具有彈性

前面我們已經介紹了如何讓你的ScrollView,ListView具有彈性,

今天,我們在前面的基礎上,做一下适當的修改,讓那些既不是ScrollView,也不是ListView的Activity頁面,也能具有彈性。

先上圖:

Android自定義控件(四)——讓每一個Activity UI都具有彈性

圖中是最簡單的一個Android測試程式。預設的效果TextView是無法劃動的。

進過我們小小的改造,就能讓整個UI具有彈性效果。

改動如下:

protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		View view = getLayoutInflater().inflate(R.layout.activity_main, null);
		view.setOnTouchListener(new ElasticTouchListener());
		setContentView(view);
	}
           

我們僅僅隻需要在需要彈性的Root VIew 上加上監聽。就能達到如果的效果了。

ElasticTouchListener源碼:

public class ElasticTouchListener implements OnTouchListener {
	private View inner;
	View[] children;
	private float y;
	private Rect normal = new Rect();
	private boolean animationFinish = true;
	private int[] tops;
	private int[] bottoms;

	@Override
	public boolean onTouch(View v, MotionEvent ev) {
		if (inner == null && children == null) {
			if (v instanceof ViewGroup) {
				ViewGroup group = (ViewGroup) v;
				int count = group.getChildCount();
				if (count > 0) {
					children = new View[count];
					tops = new int[count];
					bottoms = new int[count];
					for (int i = 0; i < count; i++) {
						children[i] = group.getChildAt(i);
						tops[i] = children[i].getTop();
						bottoms[i] = children[i].getBottom();
					}
				}
			}
			inner = v;
		}
		if (animationFinish && (inner != null || children != null)) {
			int action = ev.getAction();
			switch (action) {
			case MotionEvent.ACTION_DOWN:
//				System.out.println("ACTION_DOWN");
				y = ev.getY();
				break;
			case MotionEvent.ACTION_UP:
//				System.out.println("ACTION_UP");
				y = 0;
				if (isNeedAnimation()) {
					animation();
				}
				inner.invalidate();
				break;
			case MotionEvent.ACTION_MOVE:
//				System.out.println("ACTION_MOVE");
				final float preY = y == 0 ? ev.getY() : y;
				float nowY = ev.getY();
				int deltaY = (int) (preY - nowY);
				y = nowY;
				// 當滾動到最上或者最下時就不會再滾動,這時移動布局
				if (isNeedMove()) {
					if (normal.isEmpty()) {
						// 儲存正常的布局位置
						normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom());
					}
					if (children != null) {
						View view = null;
						for (int i = 0; i < children.length; i++) {
							view = children[i];
							view.layout(view.getLeft(), view.getTop() - deltaY / 2, view.getRight(), view.getBottom() - deltaY / 2);
						}
					} else {
						// 移動布局
						inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2, inner.getRight(), inner.getBottom() - deltaY / 2);
					}
				}
				inner.invalidate();
				break;
			default:
				break;
			}
		} else {
			return false;
		}
		return true;
	}

	// 開啟動畫移動

	public void animation() {
		if (children == null) {
			// 開啟移動動畫
			TranslateAnimation trans = new TranslateAnimation(0, 0, 0, normal.top - inner.getTop());
			trans.setDuration(200);
			trans.setAnimationListener(new AnimationListener() {
				@Override
				public void onAnimationStart(Animation animation) {
					animationFinish = false;
				}
				@Override
				public void onAnimationRepeat(Animation animation) {
				}
				@Override
				public void onAnimationEnd(Animation animation) {
					inner.clearAnimation();
					// 設定回到正常的布局位置
					inner.layout(normal.left, normal.top, normal.right, normal.bottom);
					normal.setEmpty();
					animationFinish = true;
				}
			});
			inner.startAnimation(trans);
		} else {
			for (int i = 0; i < children.length; i++) {
				final View view = children[i];
				if (view.getVisibility() == View.VISIBLE) {
					final int index = i;
					// 開啟移動動畫
					TranslateAnimation trans = new TranslateAnimation(0, 0, 0, tops[i] - view.getTop());
					trans.setDuration(200);
					trans.setAnimationListener(new AnimationListener() {
						@Override
						public void onAnimationStart(Animation animation) {
							animationFinish = false;
						}
						@Override
						public void onAnimationRepeat(Animation animation) {

						}
						@Override
						public void onAnimationEnd(Animation animation) {
							view.clearAnimation();
							// 設定回到正常的布局位置
							view.layout(view.getLeft(), tops[index], view.getRight(), bottoms[index]);
							normal.setEmpty();
							animationFinish = true;
						}
					});
					view.startAnimation(trans);
				}
			}
		}

	}

	// 是否需要開啟動畫
	public boolean isNeedAnimation() {
		return !normal.isEmpty();
	}

	// 是否需要移動布局
	public boolean isNeedMove() {
//		int offset = inner.getMeasuredHeight() - getHeight();
//		int scrollY = getScrollY();
//		if (scrollY == 0 || scrollY == offset) {
//			return true;
//		}
//		return false;
		
//		if (children != null && children.length > 0
//				&& (children[children.length - 1].getBottom() <= inner.getPaddingTop()/*inner.getTop()*/
//				|| children[0].getTop() >= inner.getHeight()
//				)) {
//			return false;
//		}
		
		return true;
	}
}
           

本次教程就到此,

經過有彈性的ScrollView,有彈性的ListView,以及本文的介紹,就可以讓你的Android應用在每一個角落都擁有彈性啦。