您的位置:首页 > 移动开发 > Android开发

Android_自定义HorizontalScrollView实现滑动子控件大小伸缩

2016-02-16 15:14 579 查看
项目需求实现的一个界面效果,觉得挺有意思,不好的地方,大家给点意见

先看下效果图:



其实很简单,就是继承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! 源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: