How can I change the OverScroll color in Android 2.3.1?

后端 未结 3 1580
一整个雨季
一整个雨季 2020-11-30 23:33

Since Android 2.3.1 there is a new feature for ScrollViews and Lists called OverScroll. With

android:overScrollMode=\"never\"

I can turn i

相关标签:
3条回答
  • 2020-12-01 00:13

    Actually, instead of using a customized ListView, you can simply "hack" your way to changing the color, the glow effect is actually a Drawable embedded in the OS's resources, you can apply a ColorFilter on that:

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

    Read more about it here: http://evendanan.net/android/branding/2013/12/09/branding-edge-effect/

    0 讨论(0)
  • 2020-12-01 00:16

    The following method overrides the standard overscroll color including the edge line.
    Calling it once in onCreate is enough.

    ...
    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) {
        }
    }
    
    0 讨论(0)
  • 2020-12-01 00:19

    Afaik there is no way to do this. So I created one; presenting:

    Graeme's Amazing Custom List View v2

    I've created a custom view which performs overscroll for ListViews and for GridViews (XML example is for slightly more involved GridView but view works for both):

    <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>   
    

    The CustomGlowListView looks like this:

    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;
    }
    }
    

    The overscroll images you can grab from platforms\android-10\data\res\drawable-mdpi\ and then change Hue & Saturation to change color.

    I hope this can be a useful start for other ListView customisations - Be interesting to hear of any.

    0 讨论(0)
提交回复
热议问题