Как изменить цвет OverScroll в Android 2.3.1?

Начиная с Android 2.3.1 появилась новая функция для ScrollViews и списков под названием OverScroll. С

android:overScrollMode="never" 

Я могу отключить его, но если я не хочу отключить его, как я могу изменить его цвет?

Solutions Collecting From Web of "Как изменить цвет OverScroll в Android 2.3.1?"

Афайк не может этого сделать. Поэтому я создал его; Предъявление:

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-10 \ data \ res \ drawable-mdpi \, а затем изменить Hue & Saturation, чтобы изменить цвет.

Надеюсь, это может быть полезным началом для других настроек ListView. Будьте интересны, чтобы услышать о них.

Фактически вместо использования настраиваемого 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) { } }