Android开发fadingEdge和fadingEdgeLength设置及屏蔽顶部阴影设置

本文介绍了如何在Android开发中设置fadingEdgeLength以实现滚动视图的边缘阴影效果,以及如何屏蔽顶部阴影,只保留底部阴影。通过分析源码并重写特定方法来实现定制,同时提到了修改EdgeEffect颜色的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设置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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值