美文网首页具体自定义控件
Android实现圆形头像效果

Android实现圆形头像效果

作者: 秀叶寒冬 | 来源:发表于2020-03-16 16:47 被阅读0次

    效果截图


    image.png

    实现原理

    对于圆形头像的实现,其实就是对方形图像做某些处理,以达到圆形头像的效果。一般我们会通过Canvas和Paint结合来实现这种效果。

    自定义View来实现

    因为圆形头像是视觉方面的需求,一般我们会考虑能否从自定义View的角度来解决问题。自定义的核心有两点:视觉和交互。视觉由onMeasureonLayoutonDraw这三个方法来完成,而交互则是由dispatchTouchEventonInterceptTouchEventonTouchEvent等这几个方法来控制,只要处理好这几个方法,就能实现形态各异的自定义View了。

    方式一 BitmapShader

    package com.yds.myapplication;
    
    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.drawable.BitmapDrawable;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    
    import androidx.appcompat.widget.AppCompatImageView;
    
    /**
     * Created by yds
     * on 2020/3/10.
     */
    public class CircleImageView extends AppCompatImageView {
    
        private int mSize;
        private Paint mPaint;
    
        public CircleImageView(Context context) {
            this(context,null);
        }
    
        public CircleImageView(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public CircleImageView(Context context,AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init(){
            mPaint = new Paint();
            mPaint.setDither(true);
            mPaint.setAntiAlias(true);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int width = getMeasuredWidth();
            int height = getMeasuredHeight();
            mSize = Math.min(width,height);  //取宽高的最小值
            setMeasuredDimension(mSize,mSize);    //设置CircleImageView为等宽高
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            //获取sourceBitmap,即通过xml或者java设置进来的图片
            Drawable drawable = getDrawable();
            if (drawable == null) return;
    
            Bitmap sourceBitmap = ((BitmapDrawable)getDrawable()).getBitmap();
            if (sourceBitmap != null){
                //对图片进行缩放,以适应控件的大小
                Bitmap bitmap = resizeBitmap(sourceBitmap,getWidth(),getHeight());
                drawCircleBitmapByShader(canvas,bitmap);    //利用BitmapShader实现
            }
        }
    
        private Bitmap resizeBitmap(Bitmap sourceBitmap,int dstWidth,int dstHeight){
            int width = sourceBitmap.getWidth();
            int height = sourceBitmap.getHeight();
    
            float widthScale = ((float)dstWidth) / width;
            float heightScale = ((float)dstHeight) / height;
    
            //取最大缩放比
            float scale = Math.max(widthScale,heightScale);
            Matrix matrix = new Matrix();
            matrix.postScale(scale,scale);
    
            return Bitmap.createBitmap(sourceBitmap,0,0,width,height,matrix,true);
        }
    
        private void drawCircleBitmapByShader(Canvas canvas,Bitmap bitmap){
            BitmapShader shader = new BitmapShader(bitmap,BitmapShader.TileMode.CLAMP,BitmapShader.TileMode.CLAMP);
            mPaint.setShader(shader);
            canvas.drawCircle(mSize / 2,mSize /2 ,mSize / 2,mPaint);
        }
    }
    
    

    方式二 PorterDuffXfermode

    package com.yds.myapplication;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.util.AttributeSet;
    
    import androidx.appcompat.widget.AppCompatImageView;
    
    /**
     * Created by yds
     * on 2020/3/10.
     */
    public class CircleImageViewPD extends AppCompatImageView {
    
        private int mWidth;
        private int mHeight;
        private Paint mPaint;
        private Bitmap CircleBitmap;
    
        public CircleImageViewPD(Context context) {
            super(context);
        }
    
        public CircleImageViewPD(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CircleImageViewPD(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        private void ImgCircle(){
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setAntiAlias(true);
            paint.setFilterBitmap(true);
            paint.setColor(Color.GRAY);
            paint.setStrokeWidth(5);
            paint.setStyle(Paint.Style.FILL);
            CircleBitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(CircleBitmap);
            canvas.drawCircle(mWidth/2,mHeight/2,mWidth/2,paint);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            mWidth = getMeasuredWidth();
            mHeight = getMeasuredHeight();
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setFilterBitmap(true);
            ImgCircle();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            int count = canvas.saveLayerAlpha(0, 0, mWidth, mHeight, 250, Canvas.ALL_SAVE_FLAG);
            super.onDraw(canvas);
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            canvas.drawBitmap(CircleBitmap,0,0, mPaint);
            canvas.restoreToCount(count);
        }
    }
    
    

    方式三 继承自Drawable

    package com.yds.myapplication;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapShader;
    import android.graphics.Canvas;
    import android.graphics.ColorFilter;
    import android.graphics.Paint;
    import android.graphics.PixelFormat;
    import android.graphics.Shader;
    import android.graphics.drawable.Drawable;
    
    /**
     * Created by yds
     * on 2020/3/10.
     */
    public class CircleImageViewDrawable extends Drawable {
        private Paint mPaint;
        private BitmapShader mBitmapShader;
        private int mSize;
        private int mRadius;
        public CircleImageViewDrawable(Bitmap bitmap){
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
            mPaint.setShader(mBitmapShader);
            mSize = Math.min(bitmap.getWidth(),bitmap.getHeight());
            mRadius = mSize/2;
        }
        @Override
        public void draw(Canvas canvas) {
            canvas.drawCircle(mRadius,mRadius,mRadius,mPaint);
        }
    
        @Override
        public void setAlpha(int alpha) {
            mPaint.setAlpha(alpha);
        }
    
        @Override
        public void setColorFilter(ColorFilter colorFilter) {
            mPaint.setColorFilter(colorFilter);
        }
    
        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }
    
        @Override
        public int getIntrinsicHeight() {
            return mSize;
        }
    
        @Override
        public int getIntrinsicWidth() {
            return mSize;
        }
    }
    
    

    使用

    public class MainActivity extends AppCompatActivity {
        private ImageView mImageView;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mImageView = findViewById(R.id.img);
    
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.img);
            Drawable drawable = new CircleImageViewDrawable(bitmap);
            mImageView.setImageDrawable(drawable);
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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:orientation="vertical"
        tools:context=".MainActivity">
        <ImageView
            android:id="@+id/img"
            android:layout_width="120dp"
            android:layout_height="120dp" />
    
        <com.yds.myapplication.CircleImageView
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:src="@drawable/img"/>
        <com.yds.myapplication.CircleImageViewPD
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:src="@drawable/img"/>
    </LinearLayout>
    

    地址:https://github.com/ydslib/CircleImageView.git

    相关文章

      网友评论

        本文标题:Android实现圆形头像效果

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