在Android開發的過程中有時候涉及到顯示使用者頭像,不少APP上的使用者頭像都是顯示的圓形,但是圖檔都是一般矩形,想要實作這種效果,使用原生的控件怕是比較難,可能會有兩種想法,一種是把圖檔通過Bitmap進行處理,一種是自定義一個顯示圓形頭像的控件。如果每一張圖檔都用Bitmap處理,會造成資源浪費,自定義控件更簡單一些。本來想偷個懶,百度裡查了好久,沒有找到我想要的方案,沒辦法,還是自力更生吧。如圖:作圖沒考慮白色和背景灰白色不太明顯,具體應用可自行調整。
頭像框
進度條
具體思路:
重寫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();