自Android 2.3.1起,ScrollViews和Lists的新功能称为OverScroll。随着
android:overScrollMode="never"
我可以将其关闭,但如果我不想将其关闭,我该如何更改它的颜色?
答案 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) {
}
}