随手指拖动而变色的ScrollView

来源:互联网 发布:ubuntu 桌面壁纸 编辑:程序博客网 时间:2024/05/17 03:19

参考

        关于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>
        布局中前面一部分被省略了。





0 0
原创粉丝点击