Android自定义控件(四)——让每一个Activity UI都具有弹性

前面我们已经介绍了如何让你的ScrollView,ListView具有弹性,

今天,我们在前面的基础上,做一下适当的修改,让那些既不是ScrollView,也不是ListView的Activity页面,也能具有弹性。

先上图:


图中是最简单的一个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应用在每一个角落都拥有弹性啦。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值