自定义ImageView

来源:互联网 发布:五十音图软件 编辑:程序博客网 时间:2024/05/22 02:06

先看一下效果图:


下面是布局的代码:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.student0.www.mycircleimgview.MainActivity">
    <com.student0.www.mycircleimgview.CircularImageView        android:layout_width="100dp"        android:layout_height="100dp"        android:src="@mipmap/code"        android:padding="5dp"        />
</LinearLayout>
说明:虽然ImageView控件可以用不同的缩放类型(通过scaleType属性设置)显示图像,
但遗憾的是ImageView控件只能显示整个图像。所以要显示图像的某一部分,
则只能在原始图像的基础上建立一个新的,满足要求的Bitmap
然后将这个新的Bitmap显示在控件上。
实现原理图:
步骤说明:
1、获取原始的Bitmap资源对象
2、在原始Bitmap资源对象中通过拷贝对象,获取可调整的Bitmap对象副本
3、判断该可调整的Bitmap的大小是否满足ImagView需要的大小,不满足则通过Bitmap副本创建一个满足大小的Bitmap进入第四步,否则直接对第二步中得到的副本进行第四步操作
4、创建一个空白的大小为ImageView的Bitmap画布
5、使用画笔在画布上画上圆(padding在此处作用)
6、选择画笔的取舍模式
7、在画布上画上第三步中得到的Bitmap,返回第四步中的Bitmap
8、最后的setBitmap
9、利用重写onMeasure(),使得CircleImageView在MeasureSpec.EXACTLY 或MeasureSpec.AT_MOST下为正方形;
CircleImageView 代码:
public class CircularImageView extends android.support.v7.widget.AppCompatImageView {    private final String TAG = "CircularImageView-->";    private final int defaultSize = 50;    public CircularImageView(Context context) {        super(context);    }    public CircularImageView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public CircularImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onDraw(Canvas canvas) {        Drawable drawable = getDrawable();        if (drawable == null){            return;        }        if (!(drawable instanceof BitmapDrawable)){            Log.e(TAG, "drawable should be a BitmapDraw");            return;        }        //必要步骤,避免由于初始化之前导致的异常错误        if (getHeight() == 0 || getWidth() == 0 ){            return;        }        Bitmap mBmp = ((BitmapDrawable) drawable).getBitmap();        //Make a Mutable Bitmap from Source_bitmap        /***** below are the diff between  immutable and mutable******/        // it's about the same difference as on String vs StringBuilder        // - String is immutable so you can't change its content (well at least not without any hack),        // while for StringBuilder you can change its content.        Bitmap bitmap = mBmp.copy(Bitmap.Config.ARGB_8888, true);   //建立可操作图片对象        canvas.drawBitmap(getCircleBitMap(bitmap, getHeight()), 0, 0, null);    }    private Bitmap getCircleBitMap(Bitmap bitmap, int diameter) {        Bitmap sBmp;        float padding_1 = Math.min(getPaddingLeft(), getPaddingRight());        float padding_2 = Math.min(getPaddingTop(), getPaddingBottom());        float max_padding = Math.min(padding_1, padding_2);        //判断是否需要改变可操作图片的大小        if (bitmap.getHeight() != diameter || bitmap.getWidth() != diameter){            sBmp = bitmap.createScaledBitmap(bitmap, diameter, diameter, false);        }else{            sBmp = bitmap;        }        Bitmap outBmp = Bitmap.createBitmap(sBmp.getWidth(), sBmp.getHeight(), Bitmap.Config.ARGB_8888);    //目标图对象        Canvas canvas = new Canvas(outBmp);        Rect rect_get = new Rect(0, 0, sBmp.getWidth(), sBmp.getHeight());        Rect rect_set = new Rect(0, 0, outBmp.getWidth(), outBmp.getHeight());        Paint paint = new Paint();        paint.setAntiAlias(true);        paint.setDither(true);        paint.setFilterBitmap(true);        canvas.drawCircle(outBmp.getWidth()/2, outBmp.getHeight()/2, diameter/2 - max_padding, paint);    //首次绘制        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));      //提取模式选择        canvas.drawBitmap(sBmp, rect_get, rect_set, paint); //二次绘制        return outBmp;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        //保证CircularImageView为正方形        int min = Math.min(getSize(defaultSize, widthMeasureSpec), getSize(defaultSize, heightMeasureSpec));       setMeasuredDimension(min, min);    }    private int getSize(int defaultSize, int measureSpec){        int resultSize = defaultSize;        int size = MeasureSpec.getSize(measureSpec);        int mode = MeasureSpec.getMode(measureSpec);        switch (mode){            case MeasureSpec.AT_MOST:            case MeasureSpec.EXACTLY:                resultSize = size;                break;            case MeasureSpec.UNSPECIFIED:                resultSize = defaultSize;                break;            default:                break;        }        return resultSize;    }}

 

0 0