将淡出边缘应用于ImageView

8

有没有办法在 ImageView 组件上应用垂直/水平渐变边缘?

我已经尝试了 android:fadingEdge,但不幸的是该属性已被弃用,并且从 API 级别 14 开始将被忽略。有什么想法吗?

5个回答

20

我找到了一个非常巧妙的解决方法,对我来说完美地解决了问题。我需要淡化(这种方法适用于任何一侧,只需创建不同的渐变) ImageView 的顶部和底部。我将ImageView装在一个FrameLayout中,并在上下各放置了2个View,然后为每个背景创建了渐变的XML,并将它们简单地设置为背景。看起来就像这样:

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="centerCrop"
            android:adjustViewBounds="true" />
        <View
            android:layout_width="match_parent"
            android:layout_height="@dimen/fade_effect_heigth"
            android:layout_gravity="bottom"
            android:background="@drawable/custom_gradient_bottom"/>
        <View
            android:layout_width="match_parent"
            android:layout_height="@dimen/fade_effect_heigth"
            android:layout_gravity="top"
            android:background="@drawable/custom_gradient_top"/>
</FrameLayout>

现在两个视图位于图像视图之上,它们的渐变xml背景文件如下所示(这是顶部的渐变,底部相同,只需翻转起始/结束颜色):

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<gradient
    android:angle="90"
    android:startColor="#00000000" <- black with 0 alpha, so transparent
    android:endColor="#000000" <- black color
    android:type="linear" />

你可以选择适合自己的淡出高度,我选择了120dp,并且它满足了我的需求。这是我模拟器中仅含 ImageView 的截图:

输入图像描述


1
这个解决方案在2023年仍然有帮助!感谢@vucko提供的答案。 - Sakhawat Hossain

5

我创建了以下扩展ImageView,以将其与水平淡出结合,您可以轻松更改此类并添加垂直淡出。(已使用最新的Android版本4.4.2进行测试

基类:

public class FadingImageView extends ImageView {
    private FadeSide mFadeSide;

    private Context c;

    public enum FadeSide {
        RIGHT_SIDE, LEFT_SIDE
    }

    public FadingImageView(Context c, AttributeSet attrs, int defStyle) {
        super(c, attrs, defStyle);

        this.c = c;

        init();
    }

    public FadingImageView(Context c, AttributeSet attrs) {
        super(c, attrs);

        this.c = c;

        init();
    }

    public FadingImageView(Context c) {
        super(c);

        this.c = c;

        init();
    }

    private void init() {
        // Enable horizontal fading
        this.setHorizontalFadingEdgeEnabled(true);
        // Apply default fading length
        this.setEdgeLength(14);
        // Apply default side
        this.setFadeDirection(FadeSide.RIGHT_SIDE);
    }

    public void setFadeDirection(FadeSide side) {
        this.mFadeSide = side;
    }

    public void setEdgeLength(int length) {
        this.setFadingEdgeLength(getPixels(length));
    }

    @Override
    protected float getLeftFadingEdgeStrength() {
        return mFadeSide.equals(FadeSide.LEFT_SIDE) ? 1.0f : 0.0f;
    }

    @Override
    protected float getRightFadingEdgeStrength() {
        return mFadeSide.equals(FadeSide.RIGHT_SIDE) ? 1.0f : 0.0f;
    }

    @Override
    public boolean hasOverlappingRendering() {
        return true;
    }

    @Override
    public boolean onSetAlpha(int alpha) {
        return false;
    }

    private int getPixels(int dipValue) {
        Resources r = c.getResources();

        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dipValue, r.getDisplayMetrics());
    }
}

用法:

- 在您的XML中创建以下对象:

<com.your.package.FadingImageView
    android:id="@+id/fade_image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/some_drawable" />

- 然后应用您想要的淡出效果:
    FadingImageView mFadingImageView = (FadingImageView) findViewById(R.id.fade_image_view);

    mFadingImageView.setEdgeLength(28);

    mFadingImageView.setFadeDirection(FadeSide.RIGHT_SIDE);

有没有办法淡化两侧?还可能包括顶部和底部? - buradd

2
Vucko的回答有个小补充。这个类可以同时为多个边缘添加淡入淡出效果。最初的回答请见此处
public class FadingImageView extends AppCompatImageView {


    private boolean mFadeRight;
    private boolean mFadeLeft;
    private boolean mFadeTop;
    private boolean mFadeBottom;

    private Context c;



    public FadingImageView(Context c, AttributeSet attrs, int defStyle) {
        super(c, attrs, defStyle);

        this.c = c;

        init();
    }

    public FadingImageView(Context c, AttributeSet attrs) {
        super(c, attrs);

        this.c = c;

        init();
    }

    public FadingImageView(Context c) {
        super(c);

        this.c = c;

        init();
    }

    private void init() {
        // Enable horizontal fading
        this.setHorizontalFadingEdgeEnabled(true);
        this.setVerticalFadingEdgeEnabled(true);
        // Apply default fading length
        this.setEdgeLength(14);
        // Apply default side
        this.setFadeRight(true);
    }




    public void setFadeRight(boolean fadeRight) {
        mFadeRight = fadeRight;
    }



    public void setFadeLeft(boolean fadeLeft) {
        mFadeLeft = fadeLeft;
    }


    public void setFadeTop(boolean fadeTop) {
        mFadeTop = fadeTop;
    }

    public void setFadeBottom(boolean fadeBottom) {
        mFadeBottom = fadeBottom;
    }

    public void setEdgeLength(int length) {
        this.setFadingEdgeLength(getPixels(length));
    }


    @Override
    protected float getTopFadingEdgeStrength() {
        return mFadeTop ? 1.0f : 0.0f;
    }

    @Override
    protected float getBottomFadingEdgeStrength() {
        return mFadeBottom ? 1.0f : 0.0f;
    }

    @Override
    protected float getLeftFadingEdgeStrength() {
        return mFadeLeft ? 1.0f : 0.0f;
    }

    @Override
    protected float getRightFadingEdgeStrength() {
        return mFadeRight ? 1.0f : 0.0f;
    }

    @Override
    public boolean hasOverlappingRendering() {
        return true;
    }

    @Override
    public boolean onSetAlpha(int alpha) {
        return false;
    }

    private int getPixels(int dipValue) {
        Resources r = c.getResources();

        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dipValue, r.getDisplayMetrics());
    }
}

最初的回答是:添加淡出效果到所有边缘。
 mFadingImageView.setFadeTop(true);
 mFadingImageView.setFadeBottom(true);
 mFadingImageView.setFadeLeft(true);
 mFadingImageView.setFadeRight(true);

边缘太锐利了,对于那些非常敏感的人来说不太好。最好将其边缘变得模糊一些。 - Otieno Rowland

0

只需在自定义的drawable中将可绘制对象与边缘颜色合并,就像这样... fade_image_background.xml

<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/abc" />
<item>
    <shape android:shape="rectangle">
        <gradient
            android:angle="270"
            android:endColor="#000000"
            android:startColor="#00000000"
            android:type="linear" />
    </shape>
</item>

然后像这样使用自定义的可绘制对象。

android:background="@drawable/fade_image_background"

0
尝试这个解决方法:不需要扩展ImageView。
imageView.scrollTo();
imageView.setHorizontalFadingEdgeEnabled(true);
imageView.setFadingEdgeLength(40);

Jitendra,使用这个解决方法可以实现4个渐变边缘吗? - carl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接