天天看点

Android开发自定义圆形头像框以及圆形进度条完

在Android开发的过程中有时候涉及到显示用户头像,不少APP上的用户头像都是显示的圆形,但是图片都是一般矩形,想要实现这种效果,使用原生的控件怕是比较难,可能会有两种想法,一种是把图片通过Bitmap进行处理,一种是自定义一个显示圆形头像的控件。如果每一张图片都用Bitmap处理,会造成资源浪费,自定义控件更简单一些。本来想偷个懒,百度里查了好久,没有找到我想要的方案,没办法,还是自力更生吧。如图:作图没考虑白色和背景灰白色不太明显,具体应用可自行调整。

头像框

Android开发自定义圆形头像框以及圆形进度条完

                                           进度条

Android开发自定义圆形头像框以及圆形进度条完

具体思路:

重写ImageView控件,在表面画一个充满的矩形,然后中间挖去一个空心圆,这样就把图片只显出一个圆形。我这里把圆形头像框以及圆形进度条整合到一起方便使用。

话不多说上干货。

values文件夹里随便选一个资源文件打开,或者新建一个attr.xml的文件,在<resources> </resources>中间加入如下代码

<declare-styleable name="OvalfullProgress">
    <!--调试进度效果参数 -->
    <attr name="progress" format="integer"/>
    <!--边框颜色-->
    <attr name="framecolor" format="reference"/>
    <!--头像框false,进度条true-->
    <attr name="isprogress" format="boolean"/>
</declare-styleable>
           

然后java重写ImageView代码:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import androidx.annotation.Nullable;

public class OvalfullProgress  extends androidx.appcompat.widget.AppCompatImageView {
    private Context context;
    private Paint p;
    private boolean ispro;
    private int progress=0;
    private int framecolor;

    public OvalfullProgress(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context=context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.OvalfullProgress);
        progress=typedArray.getInt(R.styleable.OvalfullProgress_progress,0);
        framecolor=typedArray.getColor(R.styleable.OvalfullProgress_framecolor,Color.WHITE);
        ispro=typedArray.getBoolean(R.styleable.OvalfullProgress_isprogress,false);
        typedArray.recycle();
        init();

    }
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }


    public void init(){
        p = new Paint();
        p.setAntiAlias(true);
//      Shader shader=new BitmapShader(BitmapFactory.decodeResource(this.getResources(),R.drawable.app_icon),Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
//      p.setShader(shader);//这里是用来填充不规则图形的方法,未用到



    }
    @SuppressWarnings("Duplicates")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        p.setColor(framecolor);
        p.setStrokeWidth(2);
        p.setStrokeCap(Paint.Cap.ROUND);
        Path path=new Path();
        //这里设置路径的填充效果
        //EVEN_ODD  
        //WINDING (默认值)
        //INVERSE_EVEN_ODD
        //INVERSE_WINDING
        path.setFillType(Path.FillType.EVEN_ODD);
        path.moveTo(0,0);
        path.lineTo(canvas.getWidth(),0);
        path.lineTo(canvas.getWidth(),canvas.getHeight());
        path.lineTo(0,canvas.getHeight());
        path.lineTo(0,0);
        RectF f;
        float cw=canvas.getWidth();
        float ch=canvas.getHeight();
        if(cw>ch){
            f=new RectF(cw/2-ch/2,0,ch/2+cw/2,ch);
        }else{
            f=new RectF(0,ch/2-cw/2,cw,ch/2+cw/2);
        }
        path.addOval(f,Path.Direction.CW);
        canvas.drawPath(path,p);
        if(ispro==true){
            int h1= (int) (ch-(ch*progress/100));
            canvas.drawRect(0,0,cw,h1,p);
        }

    }    
    public void setProgress(int pro){
        this.progress=pro;
        if(progress>100) {
            progress=100;
        }else if(progress<0){
            progress=0;
        }
        invalidate();
    }
}
           

然后使用很简单,layout文件里

<包名.OvalfullProgress
    android:id="@+id/jindu"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_below="@+id/center_a"
    android:layout_centerInParent="true"
    android:src="@color/blue"
    app:framecolor="@color/white"
    app:isprogress="true"
    />
           

android:src="@color/blue"放置展示图片

app:isprogress="true"头像框设置false或者不设置默认false,进度条设置true

app:framecolor="@color/white"边框颜色

这里给出操作进度条的方法,java调用代码:

OvalfullProgress jindu;
           
jindu=findViewById(R.id.jindu);
new CountDownTimer(10000, 100) {
    @Override
    public void onTick(long millisUntilFinished) {
        jindu.setProgress((int) (100-millisUntilFinished/100));
    }
    @Override
    public void onFinish() {
        Toast.makeText(DrawPanel.this,"加载完成",Toast.LENGTH_SHORT).show();
    }
}.start();
           

重点是调用  setProgress(int)方法,设置0~100.