随手指拖动而变色的ScrollView
2015-06-27 21:26
363 查看
参考
关于view的概述
效果描述
在一个可以上下滚动的scrollview,当某一个新View出现时,随着它出现高度的增加而不断改变背影色。如下:最下面一个view会随着手指的移动由红色逐渐变成蓝色。
原理
在ScrollView滑动的过程中,会不断地调用onScrollChanged(),从而可以判断出某个显示的百分比,由该百分比计算出当前应该显示的背影色。简单点说,我们只需要自定义一个ScrollView,重写其中的onScrollChanged()即可。代码
public class CustomLinearLayout extends ScrollView{ private ArgbEvaluator mEvaluator; private ViewGroup mContainer; public CustomLinearLayout(Context context) { super(context); } public CustomLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CustomLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onFinishInflate() {//在这里获取ScrollView下的子View super.onFinishInflate(); mContainer = (ViewGroup)getChildAt(0); mEvaluator = new ArgbEvaluator(); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); for(int x= 0;x<mContainer.getChildCount();x++) { View child = mContainer.getChildAt(x); if (child.getTop() <= t + getHeight() && child.getBottom() >= t + getHeight()) { float fraction = (t + getHeight() - child.getTop()) / (float) child.getHeight(); child.setBackgroundColor((Integer) mEvaluator.evaluate(fraction, Color.RED, Color.BLUE)); }else{ child.setBackgroundColor(Color.BLUE); } } } private void log(String content){ Log.e("TAG",content); } }
在onScrollChanged()中,会不断地判断当前的View的背影是否应该进行变化。
设置背景色时,是通过ArgbEvaluator()进行计算的,这是系统提供的一个工具类,在属性动画中常用到。
与LayoutParams结合
与LayoutParams结合后,可以将上面的动画直接在子View中配置,就像相对布局的子view可以配置centerInParent属性一样。由于需要配置给子view,所以需要定义一个ViewGroup,用作ScrollView的子View;并且在该ViewGroup中自定义LayoutParams,保证它的子View关联的LayoutParams中有自定义的属性。首先自定义LayoutParams的属性:
<resources> <declare-styleable name="MyLinearLayout_LayoutParams"> <attr name="layout_animator"> <flag name="translate" value="0x2" /> <flag name="alpha" value="0x1"/> </attr> </declare-styleable> </resources>
上面自定义属性时使用flag标签,因为这些属性在使用时可以通过"|"进行连接。在自定义控件中获取这些属性
//本类继承于LinearLayout,构造方法略 @Override public LinearLayout.LayoutParams generateLayoutParams(AttributeSet attrs) { return new MyLayoutParams(getContext(), attrs); } public static class MyLayoutParams extends LinearLayout.LayoutParams{ int animatorType; public static final int TYPE_ALPHA = 0x1; public static final int TYPE_TRANSLATE = 0x2; public MyLayoutParams(Context c,AttributeSet set){ super(c,set); //加载对应的LayoutParams参数 TypedArray array = c.obtainStyledAttributes(set, R.styleable.MyLinearLayout_LayoutParams); for(int x = 0;x<array.getIndexCount();x++){ int index = array.getIndex(x); switch (index){ case R.styleable.MyLinearLayout_LayoutParams_layout_animator: animatorType = array.getInt(R.styleable.MyLinearLayout_LayoutParams_layout_animator,0); break; } } array.recycle(); } }
这样,一个含有自定义LayoutParams的自定义控件就完成了。在xml布局时,该控件的所有子View都可以使用自定义的layout_animator属性。
在将ScrllView中的onScrollChanged修改如下:
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); for (int x = 0; x < mContainer.getChildCount(); x++) { View child = mContainer.getChildAt(x);//mContainer便是上面自定义的LinearLayout //获取mContainer的各个子View的LayoutParames,并强转成自定义的MyLayoutParams,因为只 //有MyLayoutParams中才有自定义的layout_animator属性 MyLayoutParams params = (MyLayoutParams) child.getLayoutParams(); if (child.getTop() <= t + getHeight() && child.getBottom() >= t + getHeight()) { float fraction = (t + getHeight() - child.getTop()) / (float) child.getHeight(); //判断有没有该声明该类型的动画,如果有就进行相应的操作 if ((params.animatorType & MyLayoutParams.TYPE_ALPHA) == MyLayoutParams.TYPE_ALPHA) { child.setBackgroundColor((Integer) mEvaluator.evaluate(fraction, Color.RED, Color.BLUE)); } if ((params.animatorType & MyLayoutParams.TYPE_TRANSLATE) == MyLayoutParams.TYPE_TRANSLATE) { child.setTranslationX((fraction - 1) * child.getRight()); } } else { child.setBackgroundColor(Color.BLUE); } } }如此一套自定义的效果便完成了。使用如下:
<ImageView demo:layout_animator="translate|alpha" android:layout_width="wrap_content" android:src="@mipmap/ic_launcher" android:layout_height="100dp" /> <ImageView demo:layout_animator="translate" android:layout_width="wrap_content" android:src="@mipmap/ic_launcher" android:layout_height="100dp" /> <ImageView android:layout_width="wrap_content" android:src="@mipmap/ic_launcher" android:layout_height="100dp" /> <ImageView demo:layout_animator="alpha" android:layout_width="wrap_content" android:src="@mipmap/ic_launcher" android:layout_height="100dp" /> <ImageView android:layout_width="wrap_content" android:src="@mipmap/ic_launcher" android:layout_height="100dp" /> </com.example.hufeng.demo.MyLinearLayout> </com.example.hufeng.demo.CustomLinearLayout>布局中前面一部分被省略了。
相关文章推荐
- POJ 1987 Distance Statistics (树上点分治)
- linux vi编辑常用命令
- 在Ubuntu 15.04下安装Android Studio
- oracle口令管理之允许某个用户最多尝试三次登录
- oracle口令管理之允许某个用户最多尝试三次登录
- leetcode 33 Search in Rotated Sorted Array
- StoryBoard segue 使用步骤
- oracle口令管理之允许某个用户最多尝试三次登录
- AT&T汇编——在你开始写
- oracle口令管理之允许某个用户最多尝试三次登录
- 设计模式--浅谈命令模式
- LeetCode_58---Length of Last Word
- shell编程项目【邮件报警系统】
- Sql入门-----------组合多个查询
- google测试之道学习笔记(二)——测试工程师
- SQL执行原理
- poj 2017 Speed Limit
- 给定一个整数,求s=1+1/(1+2)+1/(1+2+3)+...+1/(1+2+3+...+n)
- 详细设计说明书编写规范
- iOS 5 ARC完全指南——深入浅出全面讲解ARC