Android_自定义HorizontalScrollView实现滑动子控件大小变化动画

项目需求实现的一个界面效果,觉得挺有意思,不好的地方,大家给点意见

先看下效果图:

其实很简单,就是继承HorizontalScrollView...

如果对ScrollView不是很熟悉,可以看一下郭神的Android Scroller完全解析

下面看下具体代码

@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		ViewGroup wrapper = (ViewGroup) getChildAt(0);
		oneView = (ViewGroup) wrapper.getChildAt(0);
		twoView = (ViewGroup) wrapper.getChildAt(1);
		// 获取第一个view的marginleft;
		MarginLayoutParams olp = (MarginLayoutParams) oneView.getLayoutParams();
		oneViewMarginLeft = olp.leftMargin;
		// 获取第一个view的宽度
		oneViewWidth = oneView.getMeasuredWidth();
		//oneViewHeight = oneView.getMeasuredHeight();

		MarginLayoutParams tlp = (MarginLayoutParams) twoView.getLayoutParams();
		int twoViewMarginLeft = tlp.leftMargin;

		// view的坐标
		twoPoint = oneViewMarginLeft + oneViewWidth + twoViewMarginLeft;

	}


注释也比较清楚,就是获取所有的子控件,子控件左边距(为了美观,通常会设置),宽高等等...
@Override
	public boolean onTouchEvent(MotionEvent ev) {
		
		//这里为了解决滑动冲突,如果不需要忽略即可
		requestDisallowInterceptTouchEvent(true);

		int action = ev.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			break;
		case MotionEvent.ACTION_UP:
			
			//记录滑动的位置
			int scrollX = getScrollX();
			
			//如果滑动的位置大于第一个控件的左边距加上宽度的1/3,那么就自动滑到第二个控件
			if (scrollX > (oneViewMarginLeft + oneViewWidth / 3)) {
				this.smoothScrollTo(twoPoint, 0);
				if (listener != null) {
					//第二个控件回调
					listener.secondViewShow();
				}
			} else {
				//反之,就滑到起始的位置
				this.smoothScrollTo(0, 0);
				if (listener != null) {
					//第一个控件回调
					listener.firstViewShow();
				}
			}
			return true;

		}
		return super.onTouchEvent(ev);
	}


手指滑动的时候处理控件自动滑动的位置,也比较简单

@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		super.onScrollChanged(l, t, oldl, oldt);

		if (!isAnim) {
			return;
		}
		//缩放比例
		float scale = l * 1.0f / oneViewWidth;
		
		//第一个控件真实缩放比例
		float leftScale = 1 - 0.1f * scale;
		
		//第二个控件真实缩放比例
		float rightScale = 0.9f + scale * 0.1f;

		//设置各自的缩放比例
		ViewHelper.setPivotX(oneView, 0);
		ViewHelper.setPivotY(oneView, oneView.getHeight() / 2);
		ViewHelper.setScaleY(oneView, leftScale);

		ViewHelper.setPivotX(twoView, 0);
		ViewHelper.setPivotY(twoView, twoView.getHeight() / 2);
		ViewHelper.setScaleY(twoView, rightScale);

	}

这里就是子控件切换的时候动画的实现,用的是nineold帮助类,第二个子控件展现的时候,第一个子控件相应的缩小一定比例,第一个子控件展现的时候同理,

核心代码就这么多,看下全部代码

package com.wjh.hscrollerview;

import com.nineoldandroids.view.ViewHelper;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;

public class MyHorizontalScrollView extends HorizontalScrollView {
	private int oneViewWidth;

	private Context context;
	private ViewGroup oneView;
	private ViewGroup twoView;
	private int twoPoint;
	private int oneViewMarginLeft;
	private int oneViewHeight;
	private OnViewChangedListener listener;
	private boolean isAnim = false;

	public MyHorizontalScrollView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);

	}

	public MyHorizontalScrollView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);
		this.context = context;

	}

	public MyHorizontalScrollView(Context context) {
		this(context, null, 0);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		ViewGroup wrapper = (ViewGroup) getChildAt(0);
		oneView = (ViewGroup) wrapper.getChildAt(0);
		twoView = (ViewGroup) wrapper.getChildAt(1);
		// 获取第一个view的marginleft;
		MarginLayoutParams olp = (MarginLayoutParams) oneView.getLayoutParams();
		oneViewMarginLeft = olp.leftMargin;
		// 获取第一个view的宽度
		oneViewWidth = oneView.getMeasuredWidth();
		//oneViewHeight = oneView.getMeasuredHeight();

		MarginLayoutParams tlp = (MarginLayoutParams) twoView.getLayoutParams();
		int twoViewMarginLeft = tlp.leftMargin;

		// view的坐标
		twoPoint = oneViewMarginLeft + oneViewWidth + twoViewMarginLeft;

	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
	}

	@Override
	protected void onFinishInflate() {
		// TODO Auto-generated method stub
		super.onFinishInflate();
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		
		//这里为了解决滑动冲突,如果不需要忽略即可
		requestDisallowInterceptTouchEvent(true);

		int action = ev.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			break;
		case MotionEvent.ACTION_UP:
			
			//记录滑动的位置
			int scrollX = getScrollX();
			
			//如果滑动的位置大于第一个控件的左边距加上宽度的1/3,那么就自动滑到第二个控件
			if (scrollX > (oneViewMarginLeft + oneViewWidth / 3)) {
				this.smoothScrollTo(twoPoint, 0);
				if (listener != null) {
					//第二个控件回调
					listener.secondViewShow();
				}
			} else {
				//反之,就滑到起始的位置
				this.smoothScrollTo(0, 0);
				if (listener != null) {
					//第一个控件回调
					listener.firstViewShow();
				}
			}
			return true;

		}
		return super.onTouchEvent(ev);
	}

	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		super.onScrollChanged(l, t, oldl, oldt);

		if (!isAnim) {
			return;
		}
		//缩放比例
		float scale = l * 1.0f / oneViewWidth;
		
		//第一个控件真实缩放比例
		float leftScale = 1 - 0.1f * scale;
		
		//第二个控件真实缩放比例
		float rightScale = 0.9f + scale * 0.1f;

		//设置各自的缩放比例
		ViewHelper.setPivotX(oneView, 0);
		ViewHelper.setPivotY(oneView, oneView.getHeight() / 2);
		ViewHelper.setScaleY(oneView, leftScale);

		ViewHelper.setPivotX(twoView, 0);
		ViewHelper.setPivotY(twoView, twoView.getHeight() / 2);
		ViewHelper.setScaleY(twoView, rightScale);

	}

	/** 滑到第一个view */
	public void scrollToFirstView() {
		this.smoothScrollTo(0, 0);
	}

	/** 滑到第二个view */
	public void scrollToSecondView() {
		this.smoothScrollTo(twoPoint, 0);
	}

	/** 是否开启动画,默认不打开 */
	public void setIsAnim(boolean isAnim) {
		this.isAnim = isAnim;
	}

	public void setOnViewChangedListener(OnViewChangedListener listener) {
		this.listener = listener;
	}

	/** 实现此借口监听view切换 */
	public interface OnViewChangedListener {
		void firstViewShow();

		void secondViewShow();
	}

}

新的一年,新的开始,先留下点痕迹

ok!  源码下载


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值