如何在Android 2.3.1中改变OverScroll的颜色?



从Android 2.3.1开始,ScrollViews和Lists有了一个新特性OverScroll。

android:overScrollMode="never"

我可以关闭它,但是如果我不想关闭它,我怎么改变它的颜色呢?

恐怕没有办法。所以我创造了一个;介绍:

Graeme's Amazing Custom List View v2

我已经创建了一个自定义视图,执行overscroll为ListViews和GridViews (XML的例子是稍微涉及GridView,但视图工作于两者):

<CustomGlowListView     android:id="@+id/searches"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:background="@android:color/black"
                        android:layout_margin="10dp"
                        android:tag="GridView"
                        android:numColumns="3"  
                        android:horizontalSpacing="8dp" 
                        android:verticalSpacing="8dp">
</CustomGlowListView>   

CustomGlowListView是这样的:

public class CustomGlowListView extends RelativeLayout{
private ImageView underscrollEdge; 
private ImageView underscrollGlow; 
private ImageView overscrollGlow;
private ImageView overscrollEdge;
private AbsListView listView;
private final   static float    MAX_EDGE_SIZE   = 11f;
private final   static float    MAX_GLOW_SIZE   = 93f;  
private         float   scrollDistanceSinceBoundary     = 0;
private Rect paddingRectangle = new Rect();
GestureDetector listViewGestureDetector;    
// Gives the option of short circuiting the overscroll glow fade (Such as by scrolling away from the overscrolled edge)
boolean interruptFade = false;
public CustomGlowListView(Context context, AttributeSet attrs) 
{ 
    super(context, attrs);
    listViewGestureDetector = new GestureDetector(new ListViewGestureDetector());
    if( getTag() == null ||
        getTag().toString().equalsIgnoreCase("ListView"))       {   listView = new ListView(context);   }
    else if(getTag().toString().equalsIgnoreCase("GridView"))   
    {   
        listView = new GridView(context, attrs);
        ((GridView)listView).getSelector().getPadding(paddingRectangle);
    }
    listView.setId(android.R.id.list);
    listView.setOverScrollMode(OVER_SCROLL_NEVER);
    addView(listView, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

    underscrollEdge = new ImageView(context);
    underscrollEdge.setImageResource(R.drawable.underscroll_edge);
    underscrollEdge.setScaleType(ScaleType.FIT_XY);
    underscrollGlow = new ImageView(context);
    underscrollGlow.setImageResource(R.drawable.underscroll_glow);
    underscrollGlow.setScaleType(ScaleType.FIT_XY);
    overscrollGlow = new ImageView(context);
    overscrollGlow.setImageResource(R.drawable.overscroll_glow);
    overscrollGlow.setScaleType(ScaleType.FIT_XY);
    overscrollEdge = new ImageView(context);
    overscrollEdge.setImageResource(R.drawable.overscroll_edge);
    overscrollEdge.setScaleType(ScaleType.FIT_XY);
    addView(underscrollGlow, getWideLayout(ALIGN_PARENT_TOP));      
    addView(underscrollEdge, getWideLayout(ALIGN_PARENT_TOP));  
    addView(overscrollGlow, getWideLayout(ALIGN_PARENT_BOTTOM));        
    addView(overscrollEdge, getWideLayout(ALIGN_PARENT_BOTTOM));    
}   
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if(ev.getAction() == MotionEvent.ACTION_DOWN) interruptFade = true;
    listViewGestureDetector.onTouchEvent(ev);
    if(ev.getAction() == MotionEvent.ACTION_UP) reset();
    return super.dispatchTouchEvent(ev);
}
private RelativeLayout.LayoutParams getWideLayout(int alignment)
{
    RelativeLayout.LayoutParams returnLayout = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0);
    returnLayout.addRule(alignment);
    return returnLayout;
}
public void reset()
{
    interruptFade = false;
    new GlowShrinker().execute(scrollDistanceSinceBoundary);    
    scrollDistanceSinceBoundary = 0;
}   
private class ListViewGestureDetector extends SimpleOnGestureListener
{       
    @Override
    public boolean onScroll(MotionEvent downMotionEvent, MotionEvent currentMotionEvent, float distanceX, float distanceY) 
    {
        float distanceTraveled = downMotionEvent.getY() - currentMotionEvent.getY();
        if(listIsAtTop() && distanceTraveled < 0) // At top and finger moving down
        {
            scrollDistanceSinceBoundary -= distanceY;
            scaleEdges(underscrollEdge, underscrollGlow, scrollDistanceSinceBoundary);
        }
        else if(listIsAtTop() && distanceTraveled > 0 && scrollDistanceSinceBoundary > 0) // At top and finger moving up while in overscroll
        {
            scrollDistanceSinceBoundary -= distanceY;
            scaleEdges(underscrollEdge, underscrollGlow, scrollDistanceSinceBoundary);
        }           
        else if(listIsAtBottom() && distanceTraveled > 0) // At bottom and finger moving up
        {
            scrollDistanceSinceBoundary += distanceY;
            scaleEdges(overscrollEdge, overscrollGlow, scrollDistanceSinceBoundary);
        }
        else if(listIsAtBottom() && distanceTraveled < 0 && scrollDistanceSinceBoundary > 0) // At bottom and finger moving up while in overscroll
        {
            scrollDistanceSinceBoundary += distanceY;
            scaleEdges(overscrollEdge, overscrollGlow, scrollDistanceSinceBoundary);
        }           
        else if(scrollDistanceSinceBoundary != 0) // Neither over scrolling or under scrolling but was at last check. Reset both graphics. 
        {
            reset();
        }           
        Log.v(CustomGlowListView.class.getSimpleName(), "boundaryDistance = " + scrollDistanceSinceBoundary);
        return false;
    }
    private boolean listIsAtTop()   {   return listView.getChildAt(0).getTop() - paddingRectangle.top == 0;     }
    private boolean listIsAtBottom(){ return listView.getChildAt(listView.getChildCount()-1).getBottom() + paddingRectangle.bottom == listView.getHeight(); } 
}
private class GlowShrinker extends AsyncTask<Float, Integer, Void>
{
    ImageView glow;
    ImageView edge;
    private final int SHRINK_SPEED = 4;
    private final int SHRINK_INCREMENT = 50;
    @Override
    protected void onPreExecute() {         
        if(underscrollGlow.getHeight() > 0)
        {
            glow = underscrollGlow;
            edge = underscrollEdge;
        }
        else if (overscrollGlow.getHeight() > 0)
        {
            glow = overscrollGlow;
            edge = overscrollEdge;
        }
        else
        {
            return;
        }
    }
    @Override
    protected Void doInBackground(Float... scrollDistanceSinceBoundary) {
        if(glow != null && edge != null)
        {
            int currentSize = (int) scrollDistanceSinceBoundary[0].floatValue();
            int shrinkRate  = (int) currentSize / SHRINK_INCREMENT;
            for(int i=0; i < SHRINK_INCREMENT; i++)
            {
                if(interruptFade) 
                {                       
                    publishProgress(0);
                    return null;
                }
                currentSize -= shrinkRate;
                publishProgress(currentSize);
                try {       Thread.sleep(SHRINK_SPEED);     } catch (InterruptedException e) {  }
            }               
        }
        return null;
    }
    @Override
    protected void onPostExecute(Void result) {
        if(glow != null && edge != null)
            CustomGlowListView.scaleEdges(edge, glow, 0);
    }
    @Override
    protected void onProgressUpdate(Integer... values) {
        CustomGlowListView.scaleEdges(edge, glow, values[0]);
    }   
}
private static void scaleEdges(ImageView scrollEdge, ImageView scrollGlow, float scrollBy)
{
    float edgeSize = scrollBy / 20;
    float glowSize = scrollBy / 2;
    if(edgeSize > MAX_EDGE_SIZE) edgeSize = MAX_EDGE_SIZE;
    if(glowSize > MAX_GLOW_SIZE) glowSize = MAX_GLOW_SIZE;
    setHeight(scrollEdge, edgeSize);
    setHeight(scrollGlow, glowSize);
}
private static void setHeight(ImageView viewIn, float height)
{
    ViewGroup.LayoutParams params = viewIn.getLayoutParams();
    params.height = (int) height;
    viewIn.setLayoutParams(params);
}   
public AbsListView getListView()
{
    return listView;
}
}

您可以从平台android-10datares draw- mdpi中抓取overscroll图像,然后更改Hue &饱和度改变颜色

我希望这能成为其他ListView自定义的一个有用的开始。

实际上,你可以简单地"hack"你的方式来改变颜色,而不是使用自定义的ListView,发光效果实际上是嵌入在操作系统资源中的Drawable,你可以在上面应用ColorFilter:

int glowDrawableId = context.getResources().getIdentifier("overscroll_glow", "drawable", "android");
Drawable androidGlow = context.getResources().getDrawable(glowDrawableId);
androidGlow.setColorFilter(brandColor, PorterDuff.Mode.MULTIPLY);

在这里阅读更多信息:http://evendanan.net/android/branding/2013/12/09/branding-edge-effect/

下面的方法覆盖标准的超滚动颜色,包括边缘线。
在onCreate中调用一次就足够了。

...
ChangeOverScrollGlowColor(getResources(), R.color.red);
...
public static final void ChangeOverScrollGlowColor( Resources res, int colorID ) {
    try {
        final int glowDrawableId = res.getIdentifier("overscroll_glow", "drawable", "android");
        final Drawable overscrollGlow = res.getDrawable(glowDrawableId);
        overscrollGlow.setColorFilter(res.getColor(colorID), android.graphics.PorterDuff.Mode.SRC_ATOP);
        final int edgeDrawableId = res.getIdentifier("overscroll_edge", "drawable", "android");
        final Drawable overscrollEdge = res.getDrawable(edgeDrawableId);
        overscrollEdge.setColorFilter(res.getColor(colorID), android.graphics.PorterDuff.Mode.SRC_ATOP);
    } catch (Exception e) {
    }
}

相关内容

  • 没有找到相关文章

最新更新