Android_自定义HorizontalScrollView实现滑动子控件大小伸缩
2016-02-16 15:14
579 查看
项目需求实现的一个界面效果,觉得挺有意思,不好的地方,大家给点意见
先看下效果图:
其实很简单,就是继承HorizontalScrollView(废话)...
如果对ScrollView不是很熟悉,可以看一下郭神的Android Scroller完全解析
下面看下具体代码
注释也比较清楚,就是获取所有的子控件,子控件左边距(为了美观,通常会设置),宽高等等...
手指滑动的时候处理控件自动滑动的位置,也比较简单
这里就是子控件切换的时候动画的实现,用的是nineold帮助类,第二个子控件展现的时候,第一个子控件相应的缩小一定比例,第一个子控件展现的时候同理,
核心代码就这么多,看下全部代码
新的一年,新的开始,先留下点痕迹
ok! 源码下载
先看下效果图:
其实很简单,就是继承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! 源码下载
相关文章推荐
- Android Studio 常用快捷键
- Android之TypedArray 为什么需要调用recycle()
- android使用NDK编译curl库
- Android 如何判断CPU是32位还是64位
- Android Activity 生命周期
- Android:储存方式之SharePreferences
- Caused by: java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.int
- Android中自定义控件
- Android Socket实例(2)
- Android NDK开发<一>:第一个demo
- Android51--电源管理之省电模式分析
- Android 谷歌官方Gson解析和阿里巴巴fastJson解析
- 1. Android源代码下载编译
- 试用android studio
- Android图片圆角 用简单的方法实现
- RoboBinding:一个实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架
- Android Json解析
- Android HAL实例解析
- Android 系统上一款开源的图表库
- AndroidAsync :基于nio的异步通信库