【问题标题】:Make Image view rounded (not the image)使图像视图变圆(不是图像)
【发布时间】:2014-03-05 14:29:39
【问题描述】:

要求是:

要求 1:从 url 获取图片

R2:将它们保存在缓存中

R3: 使 ImageView 变成圆形而不是图像

所以对于 R1 和 R2,我找到了一个库: http://loopj.com/android-smart-image-view/

对于 R3,我做了很多研发工作,我发现的所有东西都转换了图像而不是 ImageView。这是我搜索过的:

Mask ImageView with round corner background

How to make an ImageView with rounded corners?

https://github.com/vinc3m1/RoundedImageView

https://github.com/lopspower/CircularImageView

我知道可以使用 ImageView 位图并获得四舍五入的图像,但对于我想使用的特定库,这是不可能的(可能使用非常复杂的线程)。

所以请帮我把 ImageView 弄圆而不是图像。

【问题讨论】:

  • 圆形图像视图和圆形图像有什么区别?
  • Round ImageView 表示将 ImageView 小部件实际制作为圆形 & round image 表示将 jpg 或 png 制作为圆形

标签: android android-imageview


【解决方案1】:

所以这是极简版:

class RoundImageView extends ImageView {
    private static final int RADIUS = 32;
    private Paint mPaint;
    private Paint mSrcIn;
    private RectF mRect;

    public RoundImageView(Context context) {
        super(context);
//        setBackgroundColor(0xffffffff);
        mSrcIn = new Paint();
        mSrcIn.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRect = new RectF();
    }

    @Override
    public void onDraw(Canvas canvas) {
        Drawable dr = getDrawable();
        if (dr != null) {
            mRect.set(dr.getBounds());
            getImageMatrix().mapRect(mRect);
            mRect.offset(getPaddingLeft(), getPaddingTop());

            int rtc = canvas.saveLayer(mRect, null, Canvas.ALL_SAVE_FLAG);
            // draw DST
            canvas.drawRoundRect(mRect, RADIUS, RADIUS, mPaint);

            canvas.saveLayer(mRect, mSrcIn, Canvas.ALL_SAVE_FLAG);
            // draw SRC
            super.onDraw(canvas);
            canvas.restoreToCount(rtc);
        }
    }
}

或者在不使用硬件加速的情况下使用更短的,你可以使用 Canvas.clipPath:

class RoundImageViewClipped extends ImageView {
    private static final int RADIUS = 32;
    private RectF mRect;
    private Path mClip;

    public RoundImageViewClipped(Context context) {
        super(context);
//        setBackgroundColor(0xffffffff);
        mRect = new RectF();
        mClip = new Path();
    }

    @Override
    public void onDraw(Canvas canvas) {
        Drawable dr = getDrawable();
        if (dr != null) {
            mRect.set(dr.getBounds());
            getImageMatrix().mapRect(mRect);
            mRect.offset(getPaddingLeft(), getPaddingTop());
            mClip.reset();
            mClip.addRoundRect(mRect, RADIUS, RADIUS, Direction.CCW);

            canvas.clipPath(mClip);
            super.onDraw(canvas);
        }
    }
}

【讨论】:

  • 我没有使用 ImageView。我正在使用我提到的外部库中的 SmartImageView。所以这没有成功。
  • 什么没有帮助?你尝试了什么?
  • 我使用的是来自外部库而不是 ImageView 的 SmartImageView。所以我尝试创建一个类:RoundImageViewClipped 类扩展 SmartImageView,但正如预期的那样给出了 ClassCastException。
  • ClassCastException 在哪里?
  • RoundImageView temp = (RoundImageView) findViewById(R.id.smartImageView);
【解决方案2】:

我很确定你不能“让 ImageView 变成圆形”,因为所有视图实际上都是矩形的,所以你要做的就是伪造它。

使用这样的方法从图像中切出一个圆圈:

public Bitmap getRoundedBitmap(Bitmap scaleBitmapImage) {
    int targetRadius = scaleBitmapImage.getWidth();
    if(targetRadius > scaleBitmapImage.getHeight()) targetRadius = scaleBitmapImage.getHeight();

    Bitmap targetBitmap = Bitmap.createBitmap(targetRadius, targetRadius, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(targetBitmap);
    Path path = new Path();
    path.addCircle(((float) scaleBitmapImage.getWidth() - 1) / 2, ((float) scaleBitmapImage.getHeight() - 1) / 2, (Math.min(((float) scaleBitmapImage.getWidth()), ((float) scaleBitmapImage.getHeight())) / 2), Path.Direction.CCW);

    canvas.clipPath(path);
    Bitmap sourceBitmap = scaleBitmapImage;
    canvas.drawBitmap(sourceBitmap, new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()), new Rect(0, 0, scaleBitmapImage.getWidth(), scaleBitmapImage.getHeight()), null);

    return targetBitmap;
}

由于被剪裁的部分是透明的,所以它看起来就像实际的 View 是一个圆形一样。还要确保视图的边界是平方的(或 adjustViewBounds="true"),否则您可能会在宽度或高度方面出现视觉扭曲。

很确定这与您实际获得的“圆形视图”一样接近。

【讨论】:

  • 呃。我无法使用 SmartImageView 获取位图。我知道这可以通过一些棘手的线程来完成。你能看看吗?
  • 无法获取位图是什么意思?
  • 我知道 image.getDrawable()).getBitmap();可用于获取位图,但由于图像是在我无法控制的某个不同线程中获取的,因此位图总是被检索为 null 并最终给我 NPE。
  • 这真的不是一个好方法,如果你没有让 NPE 这样做,我会更惊讶。您应该研究一个惰性加载器解决方案,并从应用程序内存中的引用中获取位图;不是来自您尝试更改的视图...
【解决方案3】:

Romain Guy to use a custom Drawable 给出的解决方案怎么样?您的 ImageView 不会是圆形的,您的源图像将不会受到影响。

class StreamDrawable extends Drawable {

    private final float mCornerRadius;
    private final RectF mRect = new RectF();
    private final BitmapShader mBitmapShader;
    private final Paint mPaint;
    private final int mMargin;

    StreamDrawable(Bitmap bitmap, float cornerRadius, int margin) {
        mCornerRadius = cornerRadius;

        mBitmapShader = new BitmapShader(bitmap,
                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(mBitmapShader);

        mMargin = margin;
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);


    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        mPaint.setColorFilter(cf);
    }       
}

【讨论】:

  • 在 StreamDrawable 构造函数中,我必须为图像提供位图,这是由于我正在使用的 SmartImageView 库而无法提供的(可能使用非常复杂的线程)
【解决方案4】:

您可以使用 GradientDrawable 在 android 视图中添加圆角。 所以,

GradientDrawable gd = new GradientDrawable();
gd.setColor(Color.TRANSPARENT);
gd.setCornerRadius(15f);
gd.setStroke(1f,Color.BLACK);
yourImageView.setBackground(gd);

【讨论】:

  • yourImageView.setBackground(gd);要求最低 API 级别 16,即 4.1 版。这会严重降低我应用的可用性。
  • 而且这个方法仍然显示矩形图像,而不是圆形。
【解决方案5】:

SmartImageView 扩展自 ImageView .. 所以你只需要扩展 SmartImageView

这是一个可行的解决方案(基于 pskink 代码和 smartImageView 库)

创建一个新类

public class RoundedCornersSmartImageView extends SmartImageView{

private int RADIUS = 0;
private RectF mRect;
private Path mClip;

public RoundedCornersSmartImageView(Context context) {
    super(context);
    init();
}

public RoundedCornersSmartImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public RoundedCornersSmartImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

@Override
public void onDraw(Canvas canvas) {
    Drawable dr = getDrawable();
    if (dr != null) {
        mRect.set(dr.getBounds());
        getImageMatrix().mapRect(mRect);
        mRect.offset(getPaddingLeft(), getPaddingTop());
        mClip.reset();
        mClip.addRoundRect(mRect, RADIUS, RADIUS, Path.Direction.CCW);

        canvas.clipPath(mClip);
        super.onDraw(canvas);
    }
}

public void setRadius(int radius){
    this.RADIUS = radius;
}

private void init(){
    mRect = new RectF();
    mClip = new Path();
}
}

用法

在您的布局文件中,您的 SmartimageView 应如下所示

<your.package.path.RoundedCornersSmartImageView
        android:id="@+id/list_image"
        android:layout_width="60dip"
        android:layout_height="60dip"
        android:src="@drawable/profile_anonyme_thumb"/>

..并以这种方式在代码中初始化视图

RoundedCornersSmartImageView thumb_image=(RoundedCornersSmartImageView) findViewById(R.id.list_image);

thumb_image.setRadius(4);
//SmartImageView methode 
thumb_image.setImageUrl(bla.MY_THUMB_URL));

编辑圆形图像的半径..

【讨论】:

  • 抱歉回复晚了。不幸的是,它没有成功。我认为问题是因为 thumb_image.setImageUrl();从网上获取需要一些时间。不知何故,我们不得不使用 setradius(4);在 setImageUrl() 之后;已完全执行。
  • 它对你有用吗?如果是,则从您的代码中删除 android:src 并使其工作
  • 首先将半径设置为 32! .. 然后加载图像.. 使用 thumb_image.setImageUrl(...) .. 我会用大图为您尝试...
  • 我先设置半径
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多