如何在Android 2.3.1中更改OverScroll颜色?

时间:2011-05-05 12:47:58

标签: android user-interface mobile scrollview

自Android 2.3.1起,ScrollViews和Lists的新功能称为OverScroll。随着

android:overScrollMode="never"

我可以将其关闭,但如果我不想将其关闭,我该如何更改它的颜色?

3 个答案:

答案 0 :(得分:21)

Afaik没有办法做到这一点。所以我创造了一个;呈现:

Graeme的惊人自定义列表视图v2

我创建了一个自定义视图,它为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-10 \ data \ res \ drawable-mdpi \中获取的过度滚动图像,然后更改Hue&amp;饱和度改变颜色。

我希望这可以成为其他ListView自定义的一个有用的开始 - 听到任何有趣的事情。

答案 1 :(得分:6)

实际上,您可以简单地“破解”改变颜色的方式,而不是使用自定义的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/

答案 2 :(得分:0)

以下方法会覆盖标准过卷颜色,包括边线 在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) {
    }
}