美文网首页Android自定义控件Android开发经验谈Android开发
Android 自定义圆形ImageView——史上最简洁高效的

Android 自定义圆形ImageView——史上最简洁高效的

作者: afa1332 | 来源:发表于2018-04-29 13:07 被阅读449次

    ———继承自AppCompatImageView,没有附加属性,可像ImageView一样使用。

    如需下载源码,请访问
    https://github.com/fengchuanfang/CircleImageView

    文章原创,转载请注明出处:
    史上最简洁高效的圆形ImageView

    运行效果如下:


    circle_imageview.png
    实现思路:

    自定义CircleImageView继承自AppCompatImageView,重写onDraw方法,

    通过方法

        ((BitmapDrawable) getDrawable()).getBitmap()
    

    获取ImageView所展示图片的Bitmap

    通过此Bitmap创建一个着色器BitmapShader,

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

    根据图片Bitmap的宽高和控件CircleImageView的宽高,通过缩放矩阵Matrix对BitmapShader进行适当缩放,使图片撑满控件

        float scale = Math.max(width / bitmap.getWidth(), height / bitmap.getHeight());
        matrix.setScale(scale, scale);//将图片宽高等比例缩放,避免拉伸
        bitmapShader.setLocalMatrix(matrix);
    

    然后将着色器设置给画笔Paint,并通过Canvas的drawCircle方法,以控件中心为圆心画内切圆。

        paint.setShader(initBitmapShader());//将着色器设置给画笔
        canvas.drawCircle(width / 2, height / 2, radius, paint);//使用画笔在画布上画圆
    
    完整代码如下:
    package com.edward.feng.circleimageview.view;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapShader;
    import android.graphics.Canvas;
    import android.graphics.Matrix;
    import android.graphics.Paint;
    import android.graphics.Shader;
    import android.graphics.drawable.BitmapDrawable;
    import android.support.annotation.Nullable;
    import android.support.v7.widget.AppCompatImageView;
    import android.util.AttributeSet;
    
    /**
     * 功能描述:一个简洁而高效的圆形ImageView
     *
     * @author (作者) edward(冯丰枫)
     * @link http://www.jianshu.com/u/f7176d6d53d2
     * 创建时间: 2018/4/17 0017
     */
    public class CircleImageView extends AppCompatImageView {
        private float width;
        private float height;
        private float radius;
        private Paint paint;
        private Matrix matrix;
    
        public CircleImageView(Context context) {
            this(context, null);
        }
    
        public CircleImageView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            paint = new Paint();
            paint.setAntiAlias(true);   //设置抗锯齿
            matrix = new Matrix();      //初始化缩放矩阵
        }
    
        /**
         * 测量控件的宽高,并获取其内切圆的半径
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            width = getMeasuredWidth();
            height = getMeasuredHeight();
            radius = Math.min(width, height) / 2;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            paint.setShader(initBitmapShader());//将着色器设置给画笔
            canvas.drawCircle(width / 2, height / 2, radius, paint);//使用画笔在画布上画圆
        }
    
        /**
         * 获取ImageView中资源图片的Bitmap,利用Bitmap初始化图片着色器,通过缩放矩阵将原资源图片缩放到铺满整个绘制区域,避免边界填充
         */
        private BitmapShader initBitmapShader() {
            Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
            BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            float scale = Math.max(width / bitmap.getWidth(), height / bitmap.getHeight());
            matrix.setScale(scale, scale);//将图片宽高等比例缩放,避免拉伸
            bitmapShader.setLocalMatrix(matrix);
            return bitmapShader;
        }
    }
    
    
    
    在xml布局文件中,直接当imageview使用即可
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffeeeeff"
            android:orientation="vertical"
            android:padding="5dp"
            tools:context=".MainActivity">
        <com.edward.feng.circleimageview.view.CircleImageView
                android:id="@+id/girls01"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:src="@mipmap/natural_beauty_01"
                android:contentDescription="@string/app_name"/>
        <com.edward.feng.circleimageview.view.CircleImageView
                android:id="@+id/girls02"
                android:layout_width="130dp"
                android:layout_height="130dp"
                android:src="@mipmap/natural_beauty_02"
                android:contentDescription="@string/app_name"
                android:layout_marginTop="93dp"/>
        <com.edward.feng.circleimageview.view.CircleImageView
                android:id="@+id/girls03"
                android:layout_width="200dp"
                android:layout_height="200dp"
                android:src="@mipmap/natural_beauty_03"
                android:layout_below="@id/girls02"
                android:contentDescription="@string/app_name"/>
        <com.edward.feng.circleimageview.view.CircleImageView
                android:id="@+id/girls04"
                android:layout_width="250dp"
                android:layout_height="250dp"
                android:src="@mipmap/natural_beauty_05"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:contentDescription="@string/app_name"/>
        <com.edward.feng.circleimageview.view.CircleImageView
                android:id="@+id/girls05"
                android:layout_width="170dp"
                android:layout_height="170dp"
                android:src="@mipmap/natural_beauty_04"
                android:layout_below="@id/girls04"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:contentDescription="@string/app_name"/>
    </RelativeLayout>
    

    相关文章

      网友评论

      • 623dcc25f33a:code: Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
        error: java.lang.ClassCastException: android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
        afa1332:@千弘 是的,不指定ImageView的src的话,会有这个问题
        623dcc25f33a:这里自定义的imageview不指定src时,抛出上述异常。

      本文标题:Android 自定义圆形ImageView——史上最简洁高效的

      本文链接:https://www.haomeiwen.com/subject/grvolftx.html