设置fadingEdgeLength及屏蔽顶部阴影
设置fadingEdge和fadingEdgeLength的效果图(上下阴影遮挡,也可设置左右阴影遮挡)
Android中所有的view都可设置,一般是可滚动的view设置了才有效果,不滚动的一般无效
例如(xml文件设置) : 设置fadingEdge和fadingEdgeLength :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_marginTop="@dimen/lay_20"
android:layout_marginRight="@dimen/lay_20"
android:layout_marginLeft="@dimen/lay_20"
android:id="@+id/activity_shop_terms_scroll"
android:layout_above="@id/activity_shop_terms_bottom"
android:layout_width="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdge="vertical"
android:fadingEdgeLength="@dimen/lay_50"
android:layout_height="match_parent">
<TextView
android:id="@+id/activity_shop_terms_details"
android:textSize="@dimen/font_15"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>
屏蔽顶部阴影
现在我想要的效果是只要下面的阴影,想屏蔽掉顶部只留下底部的阴影
发现这个没有可用的api设置,只能通过我们自己想办法实现
1.先找到源码里哪里使用了,通过NestedScrollView及子类哪里解析了fadingEdgeLength这个属性,发现View.java文件里有解析
这里解析并赋值
(android-28/view.java)
protected void initializeFadingEdgeInternal(TypedArray a) { //这里解析值
initScrollCache();
mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
R.styleable.View_fadingEdgeLength,
ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
}
在draw方法里找到 根据值设置并画出图形
public void draw(Canvas canvas) {
...... //省略代码
final ScrollabilityCache scrollabilityCache = mScrollCache;
final float fadeHeight = scrollabilityCache.fadingEdgeLength;
int length = (int) fadeHeight;
// clip the fade length if top and bottom fades overlap
// overlapping fades produce odd-looking artifacts
if (verticalEdges && (top + length > bottom - length)) {
length = (bottom - top) / 2;
}
// also clip horizontal fades if necessary
if (horizontalEdges && (left + length > right - length)) {
length = (right - left) / 2;
}
if (verticalEdges) { //(纵向)这里为设置阴影长度代码
topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
drawTop = topFadeStrength * fadeHeight > 1.0f;
bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
}
if (horizontalEdges) {//(横向)这里为设置阴影长度代码
leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
drawLeft = leftFadeStrength * fadeHeight > 1.0f;
rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
drawRight = rightFadeStrength * fadeHeight > 1.0f;
}
saveCount = canvas.getSaveCount();
int solidColor = getSolidColor();
if (solidColor == 0) {
if (drawTop) {
canvas.saveUnclippedLayer(left, top, right, top + length);
}
if (drawBottom) {
canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
}
if (drawLeft) {
canvas.saveUnclippedLayer(left, top, left + length, bottom);
}
if (drawRight) {
canvas.saveUnclippedLayer(right - length, top, right, bottom);
}
} else {
scrollabilityCache.setFadeColor(solidColor);
}
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 5, draw the fade effect and restore layers
final Paint p = scrollabilityCache.paint;
final Matrix matrix = scrollabilityCache.matrix;
final Shader fade = scrollabilityCache.shader;
if (drawTop) {
matrix.setScale(1, fadeHeight * topFadeStrength);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
canvas.drawRect(left, top, right, top + length, p);
}
if (drawBottom) {
matrix.setScale(1, fadeHeight * bottomFadeStrength);
matrix.postRotate(180);
matrix.postTranslate(left, bottom);
fade.setLocalMatrix(matrix);
p.setShader(fade);
canvas.drawRect(left, bottom - length, right, bottom, p);
}
if (drawLeft) {
matrix.setScale(1, fadeHeight * leftFadeStrength);
matrix.postRotate(-90);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
canvas.drawRect(left, top, left + length, bottom, p);
}
if (drawRight) {
matrix.setScale(1, fadeHeight * rightFadeStrength);
matrix.postRotate(90);
matrix.postTranslate(right, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
canvas.drawRect(right - length, top, right, bottom, p);
}
canvas.restoreToCount(saveCount);
......//省略代码
}
draw主要代码设置阴影代码
if (verticalEdges) { //(纵向)这里为设置阴影长度代码
topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
drawTop = topFadeStrength * fadeHeight > 1.0f;
bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
}
......
if (drawTop) { //要的效果就是要drawTop为false
matrix.setScale(1, fadeHeight * topFadeStrength);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
canvas.drawRect(left, top, right, top + length, p);
}
//如果要 drawTop=false,那么topFadeStrength * fadeHeight<=1.0f;
//fadeHeight = 50dp就是你设置的值 android:fadingEdgeLength="@dimen/lay_50";
// topFadeStrength*50*密度值<=1,那么最好 topFadeStrength=0;
//topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
//所以这个方法 getTopFadingEdgeStrength() 返回 0 最好;
2.屏蔽顶部阴影解决方法
//自定义你设置了阴影的滚动view 重写getTopFadingEdgeStrength方法
public class MyNestedScrollView extends NestedScrollView {
public MyNestedScrollView(@NonNull Context context) {
super(context);
}
public MyNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
protected float getTopFadingEdgeStrength() {
return 0f;
}
}
xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="match_parent">
<xxx.xxx.MyNestedScrollView
android:layout_marginTop="@dimen/lay_20"
android:layout_marginRight="@dimen/lay_20"
android:layout_marginLeft="@dimen/lay_20"
android:id="@+id/activity_shop_terms_scroll"
android:layout_above="@id/activity_shop_terms_bottom"
android:layout_width="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdge="vertical"
android:fadingEdgeLength="@dimen/lay_50"
android:layout_height="match_parent">
<TextView
android:id="@+id/activity_shop_terms_details"
android:textSize="@dimen/font_15"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</xxx.xxx.MyNestedScrollView >
</RelativeLayout>
解决这个一般就是你在哪个view里设置了fadingEdge你就自定义一个View继承并重写其中某个方法并返回0
getTopFadingEdgeStrength() 决定是否有顶部阴影 (return 0 就是否 return 1 为有)
getBottomFadingEdgeStrength() 决定是否有底部阴影
getLeftFadingEdgeStrength() 决定是否有左边阴影
getRightFadingEdgeStrength()决定是否有右边阴影
修改边缘效果EdgeEffect的颜色(api21以上)
在主题里加入 改变边缘颜色值(没有透明度值 设置透明度无效)
<item name="android:colorEdgeEffect">#0000ff</item>
或者屏蔽EdgeEffect 的颜色
滚动的view加入该模式
android:overScrollMode="never"
自定义边缘效果颜色
public class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
this(context, null);
}
public MyScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
// 通过ContextWrapperEdgeEffect里自定义的ResourcesEdgeEffect在系统获取R.drawable.overscroll_edge和R.drawable.overscroll_glow时替换为自己设置的图片
super(new ContextWrapperEdgeEffect(context), attrs, defStyleAttr);
setEdgeColor(Color.TRANSPARENT);
}
@Override
protected float getTopFadingEdgeStrength() {
return 0f; //屏蔽顶部模糊阴影效果
}
public void setEdgeColor(@ColorInt int color) {
//自定义模糊阴影效果 极限回弹颜色
if (Build.VERSION.SDK_INT >= 21) {
try {
Class<?> c = Class.forName("android.widget.ScrollView");
@SuppressLint("SoonBlockedPrivateApi") Field acEdgeGlowTop = c.getDeclaredField("mEdgeGlowTop");
@SuppressLint("SoonBlockedPrivateApi") Field acEdgeGlowBottom = c.getDeclaredField("mEdgeGlowBottom");
acEdgeGlowTop.setAccessible(true);
acEdgeGlowBottom.setAccessible(true);
EdgeEffect edgeEffect = new EdgeEffect(getContext());
edgeEffect.setColor(color);
acEdgeGlowTop.set(this, edgeEffect);
acEdgeGlowBottom.set(this, edgeEffect);
} catch (Exception e) {
e.printStackTrace();
LogUtils.e(e.getMessage());
}
} else {
this.setEdgeEffectColor(color);
}
}
public void setEdgeEffectColor(int edgeEffectColor) {
// 通过该方法修改颜色
((ContextWrapperEdgeEffect) getContext()).setEdgeEffectColor(edgeEffectColor);
}
/**
* 自定义滑动到顶部或者底部阴影颜色的ContextWrapper
*/
public static class ContextWrapperEdgeEffect extends ContextWrapper {
public static final String TAG = ContextWrapperEdgeEffect.class.getSimpleName();
private ResourcesEdgeEffect mResourcesEdgeEffect;
private int mColor;
private Drawable mEdgeDrawable;
private Drawable mGlowDrawable;
public ContextWrapperEdgeEffect(Context context) {
this(context, 0);
}
public ContextWrapperEdgeEffect(Context context, int color) {
super(context);
mColor = color;
Resources resources = context.getResources();
mResourcesEdgeEffect = new ResourcesEdgeEffect(resources.getAssets(), resources.getDisplayMetrics(), resources.getConfiguration());
}
public void setEdgeEffectColor(int color) {
mColor = color;
if (mEdgeDrawable != null) mEdgeDrawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY);
if (mGlowDrawable != null) mGlowDrawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY);
}
@Override
public Resources getResources() {
return mResourcesEdgeEffect;
}
private class ResourcesEdgeEffect extends Resources {
private int overscroll_edge = getPlatformDrawableId("overscroll_edge");
private int overscroll_glow = getPlatformDrawableId("overscroll_glow");
public ResourcesEdgeEffect(AssetManager assets, DisplayMetrics metrics, Configuration config) {
//super(metrics, localConfiguration);
super(assets, metrics, config);
}
private int getPlatformDrawableId(String name) {
try {
int i = ((Integer) Class.forName("com.android.internal.R$drawable").getField(name).get(null)).intValue();
return i;
} catch (ClassNotFoundException e) {
Log.e(TAG, "Cannot find internal resource class");
return 0;
} catch (NoSuchFieldException e1) {
Log.e(TAG, "Internal resource id does not exist: " + name);
return 0;
} catch (IllegalArgumentException e2) {
Log.e(TAG, "Cannot access internal resource id: " + name);
return 0;
} catch (IllegalAccessException e3) {
Log.e(TAG, "Cannot access internal resource id: " + name);
}
return 0;
}
@Override
public Drawable getDrawable(int resId) throws Resources.NotFoundException {
Drawable ret = null;
if (resId == this.overscroll_edge) {
mEdgeDrawable = ContextWrapperEdgeEffect.this.getBaseContext().getResources().getDrawable(R.drawable.ic_launcher_background);
// mEdgeDrawable = ContextWrapperEdgeEffect.this.getBaseContext().getResources().getDrawable(R.drawable.community_overscroll_edge);
ret = mEdgeDrawable;
} else if (resId == this.overscroll_glow) {
// mGlowDrawable = ContextWrapperEdgeEffect.this.getBaseContext().getResources().getDrawable(R.drawable.community_overscroll_glow);
mGlowDrawable = ContextWrapperEdgeEffect.this.getBaseContext().getResources().getDrawable(R.drawable.ic_launcher_background);
ret = mGlowDrawable;
} else return super.getDrawable(resId);
if (ret != null) {
ret.setColorFilter(mColor, PorterDuff.Mode.MULTIPLY);
}
return ret;
}
}
}
}
使用
<com.example.test.MyScrollView
android:layout_width="match_parent"
android:layout_height="100dp"
android:requiresFadingEdge="vertical"
android:fadingEdge="vertical"
android:fadingEdgeLength="30dp"
android:scrollbars="none"
android:background="@null"
android:overScrollMode="never"
android:layout_marginBottom="50dp"
android:scrollbarTrackVertical="@null"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:id="@+id/activity_shop_terms_details"
android:textSize="25sp"
android:textColor="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="你好啊积分卡基督教ad阿斯顿发送到发大奖的积分卡时间段你好啊积你好啊积分卡基督教ad阿斯顿发送到发大奖的积分卡时间段你好啊积你好啊积分卡基督教ad阿斯顿发送到发大奖的积分卡时间段你好啊积你好啊积分卡基督教ad阿斯顿发送到发大奖的积分卡时间段你好啊积"/>
</com.example.test.MyScrollView>