您的位置:

Android自定义View实现圆形ImageView

一、常见问题

圆形ImageView是Android开发中比较常见的一个需求,但是Android原生的ImageView并不支持直接绘制圆形,所以需要使用自定义View。

下面是一些常见问题:

1、怎样绘制一个圆形ImageView?

2、怎样使圆形ImageView具有边框?

3、怎样对圆形ImageView进行动画操作?

二、原理与实现

绘制一个圆形的ImageView可以分为以下几步:

1、继承ImageView

2、重写onDraw方法,在其中绘制一个圆形的Bitmap

3、设置ImageView的ScaleType为CENTER_CROP,保证图片的宽高比被保持且填充满整个View

4、可以根据需求在绘制的Bitmap周围添加边框或者做动画效果

下面是代码示例:

public class CircleImageView extends ImageView {

    private Bitmap mBitmap;
    private Paint mPaint;

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

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

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            super.onDraw(canvas);
        } else {
            mBitmap = drawableToBitmap(drawable);
            mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, mPaint);
        }
    }

    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }
}

三、常用功能实现

1、添加边框

在上面的代码基础上,我们可以在绘制Bitmap的周围添加一些边框来增强视觉效果。

下面是添加边框的代码示例:

public class CircleImageView extends ImageView {

    private Bitmap mBitmap;
    private Paint mPaint;
    private Paint mBorderPaint;
    private int mBorderColor;
    private int mBorderWidth;

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

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

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyleAttr, 0);
        mBorderColor = a.getColor(R.styleable.CircleImageView_borderColor, Color.WHITE);
        mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_borderWidth, 0);
        a.recycle();
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

        mBorderPaint = new Paint();
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setStrokeWidth(mBorderWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            super.onDraw(canvas);
        } else {
            mBitmap = drawableToBitmap(drawable);
            mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - mBorderWidth, mPaint);
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - mBorderWidth / 2, mBorderPaint);
        }
    }

    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }
}

2、添加动画

我们也可以为这个圆形ImageView添加一些动画效果,比如旋转、缩放、渐变等。

下面是旋转动画和缩放动画的代码示例:

public class CircleImageView extends ImageView {

    private Bitmap mBitmap;
    private Paint mPaint;
    private Matrix mMatrix;
    private float mRotation;
    private float mScale = 1f;

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

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

    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

        mMatrix = new Matrix();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            super.onDraw(canvas);
        } else {
            mBitmap = drawableToBitmap(drawable);
            mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

            int width = getWidth();
            int height = getHeight();
            int size = Math.min(width, height);

            mMatrix.reset();
            mMatrix.postScale(mScale, mScale);
            mMatrix.postRotate(mRotation, size / 2f, size / 2f);
            mMatrix.postTranslate((width - size) / 2f, (height - size) / 2f);

            canvas.drawCircle(size / 2f, size / 2f, size / 2f, mPaint);
        }
    }

    public void setRotation(float rotation) {
        mRotation = rotation;
        invalidate();
    }

    public void setScale(float scale) {
        mScale = scale;
        invalidate();
    }

    public void rotate(float from, float to, long duration) {
        ObjectAnimator animator = ObjectAnimator.ofFloat(this, "rotation", from, to);
        animator.setDuration(duration);
        animator.start();
    }

    public void scale(float from, float to, long duration) {
        ValueAnimator animator = ValueAnimator.ofFloat(from, to);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mScale = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator.setDuration(duration);
        animator.start();
    }

    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }
}
Android自定义View实现圆形ImageView

2023-05-14
Android自定义View实现圆形进度条

2023-05-14
实现Android ImageView控件圆角显示

2023-05-14
Android自定义View:掌握Canvas和Paint实

2023-05-14
Android圆形图片

2023-05-19
Android自定义View详解

2023-05-22
android圆角全方位了解

2023-05-19
Android Studio中ImageView的常见用法举

一、常规用法 在Android Studio中,总的来说,ImageView就是用来显示图片的控件。如果你想要显示一张图片,首先需要将图片放入到项目的res/drawable文件夹下。然后,设置Ima

2023-12-08
Android应用UI设计:如何实现圆角图片效果

2023-05-14
Android圆角背景

2023-05-19
让你的Android头像更出众:制作圆形头像

众所周知,人们在社交媒体上的头像素材对于给别人留下良好的第一印象非常重要。所以,如何制作一个简约、高颜值的圆形头像,成为了一项非常有实用性的技能。那么,在Android系统上,该如何制作这样的头像呢?

2023-12-08
Android绘制圆角矩形实现视觉效果的优化

2023-05-14
android自定义控件

2023-05-17
让Android图形加速起来

2023-05-14
Android开发:使用ShapeDrawable实现圆形背

2023-05-14
Android如何自定义Toast消息

2023-05-17
Android自定义View实现导航栏

导航栏是Android应用的一个重要组成部分,它可以帮助用户快速切换应用内的页面,提高用户体验。在实际开发中,我们经常会遇到导航栏的定制需求,而自定义View就成了一个很好的选择。本文将介绍如何使用自

2023-12-08
Android自定义注解指南

2023-05-17
Android ImageView重要性与使用方法

2023-05-17
Android悬浮窗实现详解

2023-05-19