问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

android 如何重写imageview 让图片有圆角效果

发布网友 发布时间:2022-04-23 01:34

我来回答

7个回答

热心网友 时间:2022-04-19 00:14

android 自定义圆角ImageView以及锯齿的处理

看到很多人开发过程中要使用圆角图片时,解决方法有:


1.重新绘制一张图片


2.通过布局来配置


3.通过重写View来实现


其中1,2在这里就不讲了,重点讲讲方法三的实现。



实现一:通过截取画布一个圆形区域与图片的相交部分进行绘制,缺点:锯齿明显,设置Paint,Canvas抗锯齿无效。

package com.open.circleimageview.widget;


import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.graphics.PaintFlagsDrawFilter;

import android.graphics.Path;

import android.graphics.Rect;

import android.graphics.Region;

import android.util.AttributeSet;

import android.view.View;


public class CircleImageViewA extends View {


public CircleImageViewA(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

}


public CircleImageViewA(Context context, AttributeSet attrs) {

super(context, attrs);

}


public CircleImageViewA(Context context) {

super(context);

}


private Bitmap bitmap;

private Rect bitmapRect=new Rect();

private PaintFlagsDrawFilter pdf=new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);

private Paint paint = new Paint();

    {

   paint.setStyle(Paint.Style.STROKE);

   paint.setFlags(Paint.ANTI_ALIAS_FLAG);

   paint.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了 

    }

    private Path mPath=new Path();

    

public void setImageBitmap(Bitmap bitmap)

{

this.bitmap=bitmap;

}

@Override

protected void onDraw(Canvas canvas) {


if(null==bitmap)

{

return;

}

bitmapRect.set(0, 0, getWidth(), getHeight());

        canvas.save();

        canvas.setDrawFilter(pdf);

        mPath.reset();

        canvas.clipPath(mPath); // makes the clip empty

        mPath.addCircle(getWidth()/2, getWidth()/2, getHeight()/2, Path.Direction.CCW);

        canvas.clipPath(mPath, Region.Op.REPLACE);

        canvas.drawBitmap(bitmap, null, bitmapRect, paint);

        canvas.restore();

}

}


实现二:通过PorterDuffXfermode 方式(注意要设置硬件加速,否则部分机子无效),优点:锯齿基本没有

package com.open.circleimageview.widget;


import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.PaintFlagsDrawFilter;

import android.graphics.PorterDuff;

import android.graphics.PorterDuffXfermode;

import android.graphics.Rect;

import android.graphics.RectF;

import android.util.AttributeSet;

import android.view.View;


public class CircleImageViewB extends View {


public CircleImageViewB(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init();

}


public CircleImageViewB(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}


public CircleImageViewB(Context context) {

super(context);

init();

}


private Bitmap bitmap;

private Rect bitmapRect=new Rect();

private PaintFlagsDrawFilter pdf=new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);

private Paint paint = new Paint();

    {

   paint.setStyle(Paint.Style.STROKE);

   paint.setFlags(Paint.ANTI_ALIAS_FLAG);

   paint.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了 

    }

    private Bitmap mDstB=null;

    private PorterDuffXfermode xfermode=new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY);

    

    

    private void init()

    {

    try {

if(android.os.Build.VERSION.SDK_INT>=11)

{

setLayerType(LAYER_TYPE_SOFTWARE, null);

}

} catch (Exception e) {

e.printStackTrace();

}

    }

public void setImageBitmap(Bitmap bitmap)

{

this.bitmap=bitmap;

}


private Bitmap makeDst(int w, int h) 

    {

        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

        Canvas c = new Canvas(bm);

        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        p.setColor(Color.parseColor("#ffffffff"));   

        c.drawOval(new RectF(0, 0, w, h), p);

        return bm;

    }

@Override

protected void onDraw(Canvas canvas) {


if(null==bitmap)

{

return;

}

if(null==mDstB)

{

mDstB=makeDst(getWidth(), getHeight());

}


bitmapRect.set(0, 0, getWidth(), getHeight());

        canvas.save();

        canvas.setDrawFilter(pdf);

        canvas.drawBitmap(mDstB, 0, 0, paint);

        paint.setXfermode(xfermode);

        canvas.drawBitmap(bitmap, null, bitmapRect, paint);

        paint.setXfermode(null);

        canvas.restore();

}

}


热心网友 时间:2022-04-19 01:32

方法1:自定义view,使用BitmapShader

首先自定义一些view的属性

下面定义了一个枚举和一个圆角的大小borderRadius。

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <attr name="borderRadius" format="dimension" />  
    <attr name="type">  
        <enum name="circle" value="0" />  
        <enum name="round" value="1" />  
    </attr>  
    <declare-styleable name="RoundImageView">  
        <attr name="borderRadius" />  
        <attr name="type" />  
    </declare-styleable>  
</resources>


自定义View代码如下

public class RoundImageView extends ImageView  
{  
  
    /** 图片的类型,圆形or圆角  */  
    private int type;  
    private static final int TYPE_CIRCLE = 0;  
    private static final int TYPE_ROUND = 1;  
  
    /** 圆角大小的默认值  */  
    private static final int BODER_RADIUS_DEFAULT = 10;  
    /**  * 圆角的大小 */  
    private int mBorderRadius;  
  
    /**  * 绘图的Paint */  
    private Paint mBitmapPaint;  
    /** * 圆角的半径 */  
    private int mRadius;  
    /** * 3x3 矩阵,主要用于缩小放大 */  
    private Matrix mMatrix;  
    /**  * 渲染图像,使用图像为绘制图形着色 */  
    private BitmapShader mBitmapShader;  
    /** * view的宽度  */  
    private int mWidth;  
    private RectF mRoundRect;  
  
    public RoundImageView(Context context, AttributeSet attrs)  
    {  
        super(context, attrs);  
        mMatrix = new Matrix();  
        mBitmapPaint = new Paint();  
        mBitmapPaint.setAntiAlias(true);  
        TypedArray a = context.obtainStyledAttributes(attrs,  
                R.styleable.RoundImageView);  
        mBorderRadius = a.getDimensionPixelSize(  
                R.styleable.RoundImageView_borderRadius, (int) TypedValue  
                        .applyDimension(TypedValue.COMPLEX_UNIT_DIP,  
                                BODER_RADIUS_DEFAULT, getResources()  
                                        .getDisplayMetrics()));// 默认为10dp  
        type = a.getInt(R.styleable.RoundImageView_type, TYPE_CIRCLE);// 默认为Circle 
        a.recycle();  
    }  
    
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
    {  
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);   
        if (type == TYPE_CIRCLE)  
        {  
            mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());  
            mRadius = mWidth / 2;  
            setMeasuredDimension(mWidth, mWidth);  
        }  
  
    }
    
    private void setUpShader()  
    {  
        Drawable drawable = getDrawable();  
        if (drawable == null)    return;  
        Bitmap bmp = drawableToBitamp(drawable);  
        // 将bmp作为着色器,就是在指定区域内绘制bmp  
        mBitmapShader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP);  
        float scale = 1.0f;  
        if (type == TYPE_CIRCLE)  
        {  
            int bSize = Math.min(bmp.getWidth(), bmp.getHeight());  
            scale = mWidth * 1.0f / bSize;  
  
        } else if (type == TYPE_ROUND)  
        {    
            scale = Math.max(getWidth() * 1.0f / bmp.getWidth(), getHeight()  
                    * 1.0f / bmp.getHeight());  
        }  
        // shader的变换矩阵,我们这里主要用于放大或者缩小  
        mMatrix.setScale(scale, scale);  
        // 设置变换矩阵  
        mBitmapShader.setLocalMatrix(mMatrix);  
        // 设置shader  
        mBitmapPaint.setShader(mBitmapShader);  
    }  
    
    private Bitmap drawableToBitamp(Drawable drawable)  
    {  
        if (drawable instanceof BitmapDrawable)  
        {  
            BitmapDrawable bd = (BitmapDrawable) drawable;  
            return bd.getBitmap();  
        }  
        int w = drawable.getIntrinsicWidth();  
        int h = drawable.getIntrinsicHeight();  
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
        Canvas canvas = new Canvas(bitmap);  
        drawable.setBounds(0, 0, w, h);  
        drawable.draw(canvas);  
        return bitmap;  
    }  
    
    @Override  
    protected void onDraw(Canvas canvas)  
    {  
        if (getDrawable() == null)  return;  
        setUpShader();  
        if (type == TYPE_ROUND)  
        {  
            canvas.drawRoundRect(mRoundRect, mBorderRadius, mBorderRadius,  
                    mBitmapPaint);  
        } else  
        {  
            canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint);  
        }  
    }  
      
    @Override  
    protected void onSizeChanged(int w, int h, int oldw, int oldh)  
    {  
        super.onSizeChanged(w, h, oldw, oldh);  
        // 圆角图片的范围  
        if (type == TYPE_ROUND)  
            mRoundRect = new RectF(0, 0, getWidth(), getHeight());  
    }  
}



方法2:自定义view,使用Xfermode

依然是自定义属性

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <attr name="borderRadius" format="dimension" />  
    <attr name="type">  
        <enum name="circle" value="0" />  
        <enum name="round" value="1" />  
    </attr>  
    <declare-styleable name="RoundImageViewByXfermode">  
        <attr name="borderRadius" />  
        <attr name="type" />  
    </declare-styleable>  
  
</resources>

代码:

public class RoundImageViewByXfermode extends ImageView  
{  
  
    private Paint mPaint;  
    private Xfermode mXfermode = new PorterDuffXfermode(Mode.DST_IN);  
    private Bitmap mMaskBitmap;  
    private WeakReference<Bitmap> mWeakBitmap;  
  
    private int type;  
    public static final int TYPE_CIRCLE = 0;  
    public static final int TYPE_ROUND = 1;  
    
    /** * 圆角大小的默认值 */  
    private static final int BODER_RADIUS_DEFAULT = 10;  
    private int mBorderRadius;  
  
    public RoundImageViewByXfermode(Context context)  
    {  
        this(context,null);  
  
        mPaint = new Paint();  
        mPaint.setAntiAlias(true);  
    }  
  
    public RoundImageViewByXfermode(Context context, AttributeSet attrs)  
    {  
        super(context, attrs);  
  
        mPaint = new Paint();  
        mPaint.setAntiAlias(true);  
  
        TypedArray a = context.obtainStyledAttributes(attrs,  
                R.styleable.RoundImageViewByXfermode);  
  
        mBorderRadius = a.getDimensionPixelSize(  
                R.styleable.RoundImageViewByXfermode_borderRadius, (int) TypedValue  
                        .applyDimension(TypedValue.COMPLEX_UNIT_DIP,  
                                BODER_RADIUS_DEFAULT, getResources()  
                                        .getDisplayMetrics()));// 默认为10dp  
        Log.e("TAG", mBorderRadius+"");  
        type = a.getInt(R.styleable.RoundImageViewByXfermode_type, TYPE_CIRCLE);// 默认为Circle  
  
        a.recycle();  
    }  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
    {  
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
        /** 果类型是圆形,则强制改变view的宽高一致,以小值为准*/  
        if (type == TYPE_CIRCLE)  
        {  
            int width = Math.min(getMeasuredWidth(), getMeasuredHeight());  
            setMeasuredDimension(width, width);  
        }  
  
    }  
    
    @Override  
    protected void onDraw(Canvas canvas)  
    {  
        Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get();  
  
        if (null == bitmap || bitmap.isRecycled())  
        {  
            Drawable drawable = getDrawable();  
            int dWidth = drawable.getIntrinsicWidth();  
            int dHeight = drawable.getIntrinsicHeight();  
  
            if (drawable != null)  
            {  
                //创建bitmap  
                bitmap = Bitmap.createBitmap(getWidth(), getHeight(),  
                        Config.ARGB_8888);  
                float scale = 1.0f;  
                Canvas drawCanvas = new Canvas(bitmap);  
                //按照bitmap的宽高,以及view的宽高,计算缩放比例;因为设置的src宽高比例可能和imageview的宽高比例不同,这里我们不希望图片失真;  
                if (type == TYPE_ROUND)  
                {  
                    // 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;  
                    scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()  
                            * 1.0f / dHeight);  
                } else  
                {  
                    scale = getWidth() * 1.0F / Math.min(dWidth, dHeight);  
                }  
                //根据缩放比例,设置bounds,相当于缩放图片了  
                drawable.setBounds(0, 0, (int) (scale * dWidth),  
                        (int) (scale * dHeight));  
                drawable.draw(drawCanvas);  
                if (mMaskBitmap == null || mMaskBitmap.isRecycled())  
                {  
                    mMaskBitmap = getBitmap();  
                }  
                // Draw Bitmap.  
                mPaint.reset();  
                mPaint.setFilterBitmap(false);  
                mPaint.setXfermode(mXfermode);  
                //绘制形状  
                drawCanvas.drawBitmap(mMaskBitmap, 0, 0, mPaint);  
                mPaint.setXfermode(null);  
                //将准备好的bitmap绘制出来  
                canvas.drawBitmap(bitmap, 0, 0, null);  
                //bitmap缓存起来,避免每次调用onDraw,分配内存  
                mWeakBitmap = new WeakReference<Bitmap>(bitmap);  
            }  
        }  
        //如果bitmap还存在,则直接绘制即可  
        if (bitmap != null)  
        {  
            mPaint.setXfermode(null);  
            canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint);  
            return;  
        }  
  
    }  
    /** 
     * 绘制形状 
     * @return 
     */  
    public Bitmap getBitmap()  
    {  
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),  
                Bitmap.Config.ARGB_8888);  
        Canvas canvas = new Canvas(bitmap);  
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
        paint.setColor(Color.BLACK);  
  
        if (type == TYPE_ROUND)  
        {  
            canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()),  
                    mBorderRadius, mBorderRadius, paint);  
        } else  
        {  
            canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2,  
                    paint);  
        }  
  
        return bitmap;  
    }  
    
    @Override  
    public void invalidate()  
    {  
        mWeakBitmap = null;  
        if (mMaskBitmap != null)  
        {  
            mMaskBitmap.recycle();  
            mMaskBitmap = null;  
        }  
        super.invalidate();  
    }  
    
}

热心网友 时间:2022-04-19 03:07

在drawable下建一个xml文件,如image_corner_round.xml,把下面的写进去,

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#B5E7B8"
android:endColor="#76D37B"
android:angle="270"/>
<corners android:topLeftRadius="4dip"
android:topRightRadius="4dip"
android:bottomLeftRadius="4dip"
android:bottomRightRadius="4dip"/>
</shape>

然后在imageview的background属性设置为 @drawable/image_corner_round

热心网友 时间:2022-04-19 04:58

给你提供一个思路吧,如果你的图片都是一样大的话,你可以做一个中间透明,四个角黑色的图片作为遮罩层,覆盖在图片上

热心网友 时间:2022-04-19 07:06

DisplayImageOptions option = new DisplayImageOptions.Builder().showStubImage(R.drawable.avatar_default).displayer(new RoundedBitmapDisplayer(4)).cacheOnDisc(true).build();

热心网友 时间:2022-04-19 09:31

使用paint函数画出来

热心网友 时间:2022-04-19 12:12

这个好像得 截取 bitmap, 把bitmap截取成圆角的
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
企业培训学到了什么 培训感悟简短 有关培训的感悟 通过培训学到什么 培训你学到了什么 领导问培训学到什么怎么回复 Linux系统安装FTP服务器 Linux系统的网络文件共享 建筑的七盏明灯的内容简介 面向对象设计七大原则 简单说 交互设计七大定律 Android图片太多,而出异常,哪位高手给解决一下啊? 有人知道怎么解决安卓模拟器的内存溢出问题吗 winrar.是压缩软件?可我不会用?怎么用? 在Android开发中,有哪些好的内存优化方式 怎么防止imagecreatefromjpeg内存溢出 关于android里的 recycle()解释 Java如何读取文件夹中所有图片,并显示出来 android,程序中如何改变ImageView大小 如何自动创建自解压格式压缩文件 recycleview怎么使用 android怎么压缩一个bitmap占用空间大小 android 图片占用内存大小怎么计算 电脑进水怎么办 电脑主机装风扇是风对里面吹好?还是把主机里面热吸出来好? 笔记本电脑进水了,吹风扇吹了一天一夜了。可以拿到太阳底下晒吗?求 电脑里的风扇正面是往里吸风还是往外排风? 电脑主机的电源风扇的风是吹进去还是吹出来的呀? 电脑散热的风扇是把外面的空气吸进来还是排出去,严重迷惑中。。 电脑机箱风扇是往里吹还是往外吸的好? 高速强制办理ETC,不办理就不让上高速,这样做你能接受吗? 肉酱时蔬米线的做法,肉酱时蔬米线怎么做好吃 蔬菜米线的做法步骤图,蔬菜米线怎么做好吃 win7窗口预览怎么设置 在家做米线放什么蔬菜 关闭Win7中的任务栏窗口预览功能 上海话叫米线的蔬菜怎么做好吃? W7怎么设置预览窗口 重庆的三鲜米线是怎么做的哦? win7系统任务栏预览不能显示所有的窗口 win7任务栏窗口预览功能没了 三鲜米线是哪三鲜 android studio 怎么检查内存溢出 win7窗口没有预览图是什么情况? 煮三鲜米线有那些蔬菜? android 怎样释放ImageView中的图片 如何制作u盘启动盘安装xp系统 求 做米线的配方 如何让win7的窗口预览功能显示全部窗口 如何实现让RecyclerView有不同尺寸的item 哪家过桥米线好?