您的位置:首页 > 其它

随手指拖动而变色的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>
布局中前面一部分被省略了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: