編輯:關於Android編程
先看一組加載效果圖,有點粉粉的加載圈:
自定義這樣的圓形加載圈還是比較簡單的,主要是用到Canvans的繪制文本,繪制圓和繪制圓弧的api:
/** * 繪制圓 * @param cx 圓心x坐標 * @param cy 圓心y坐標 * @param radius 圓的半徑 * @param paint 畫筆 */ public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) { ... } /** * 繪制圓弧 * @param oval 決定圓弧范圍的矩形區域 * @param startAngle 開始角度 * @param sweepAngle 繪制的角度 * @param useCenter 是否需要連接圓心,true連接,false不連接 * @param paint 畫筆 */ public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint) { ... } /** * 繪制文本 * @param text 需要繪制的字符串 * @param x 繪制文本起點x坐標,注意文本比較特殊,它的起點是左下角的x坐標 * @param y 繪制文本起點y坐標,同樣是左下角的y坐標 * @param paint 畫筆 */ public void drawText(String text, float x, float y, Paint paint) { ... }
開始繪圖前需要考慮的以下幾點:
1.獲取控件的寬和高,這個是決定圓的半徑大小的,半徑大小等於寬高的最小值的1/2,為什麼是最小值呢?因為這樣就不會受布局文件中寬高屬性不一樣的影響,當然我們自己在使用的時候肯定是寬高都是會寫成一樣的,這樣就剛好是一個正方形,繪制出來的圓就剛好在該正方形區域內.做了這樣的處理,其他人在用的時候就不用當心圓會不會超出控件范圍的情況了.
2.確定圓心的坐標,有了半徑和圓心坐標就可以確定一個圓了,布局中的控件區域其實都是一個矩形區域,如果想要繪制出來的圓剛好處於控件的矩形區域內並且和矩形的最短的那條邊相切,那麼圓心坐標的就是該矩形寬高的1/2,即剛好位於矩形區域的中心點.
3.繪制圓弧,注意這裡的圓弧指的是進度圈,看上面的示例圖是有2種樣式,分別是實心的加載圈和空心加載圈,這個其實就是paint的樣式決定,如果是實心圓,paint設置為Paint.Style.FILL(填充模式),同時drawArc的useCenter設置為true;如果是空心圓則paint設置為Paint.Style.STROKE(線性模式),同時drawArc的useCenter設置為false即可.值得一提的是繪制空心圓的時候還需要考慮圓弧的寬度,寬度有多大將決定進度圈的厚度.因此在定義空心圓的矩形區域的時候需要減去進度圈的厚度,否則畫出來的進度圈會超出控件的區域.
4.繪制文本,需要定位起始點,文本的起始點比較特殊,它是以左下角為起始點的,起點x坐標=圓心x坐標-文本寬度1/2;起始點y坐標=圓心y坐標+文本高度1/2;至於文本的寬高獲取可以通過paint的getTextBounds()方法獲取,具體等下看代碼.
ok,直接上代碼,注釋已經很詳細了.
圓形加載圈
public class CircleProgressView extends View { private int width;//控件寬度 private int height;//控件高 private float radius;//半徑 private float pointX;//圓心x坐標 private float pointY;//圓心y坐標 private int circleBackgroundColor;//背景顏色 private int circleBackgroundAlpha; //背景透明度 private int circleRingColor;//進度顏色 private int progressTextColor;//進度文本的顏色 private int progressTextSize;//進度文本的字體大小 private int circleRingWidth; //進度的寬度 private Paint mPaint; private int progress;//進度值 private boolean isRingStyle;//是否是空心的圓環進度樣式 public CircleProgressView(Context context) { this(context, null); } public CircleProgressView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); circleBackgroundColor = Color.WHITE; circleRingColor = Color.parseColor("#3A91FF"); progressTextColor = Color.BLACK; circleBackgroundAlpha = 128; progressTextSize = 32; circleRingWidth = 10; mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getMeasuredWidth(); height = getMeasuredHeight(); radius = Math.min(width, height) / 2.0f; pointX = width / 2.0f; pointY = height / 2.0f; } @Override protected void onDraw(Canvas canvas) { drawBackground(canvas); drawCircleRing(canvas); drawProgressText(canvas); } /** * 繪制背景色 * * @param canvas */ private void drawBackground(Canvas canvas) { mPaint.setColor(circleBackgroundColor); mPaint.setAlpha(circleBackgroundAlpha); canvas.drawCircle(pointX, pointY, radius, mPaint); } /** * 繪制圓環 * * @param canvas */ private void drawCircleRing(Canvas canvas) { mPaint.setColor(circleRingColor); RectF oval = new RectF(); if (isRingStyle) { mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(circleRingWidth); mPaint.setStrokeCap(Paint.Cap.ROUND); //注意:定義圓環的矩形區域是需要考慮圓環的寬度 oval.left = circleRingWidth / 2.0f; oval.top = height / 2.0f - radius + circleRingWidth / 2.0f; oval.right = 2 * radius - circleRingWidth / 2.0f; oval.bottom = height / 2.0f + radius - circleRingWidth / 2.0f; canvas.drawArc(oval, 0, 360 * progress / 100, false, mPaint); } else { mPaint.setStyle(Paint.Style.FILL); oval.left = 0; oval.top = height / 2.0f - radius; oval.right = 2 * radius; oval.bottom = height / 2.0f + radius; canvas.drawArc(oval, 0, 360 * progress / 100, true, mPaint); } } /** * 繪制進度文本 * * @param canvas */ private void drawProgressText(Canvas canvas) { mPaint.setColor(progressTextColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setTextSize(progressTextSize); Rect textBound = new Rect(); String text = progress + "%"; //獲取文本的矩形區域到textBound中 mPaint.getTextBounds(text, 0, text.length(), textBound); int textWidth = textBound.width(); int textHeight = textBound.height(); float x = pointX - textWidth / 2.0f; float y = pointY + textHeight / 2.0f; canvas.drawText(text, x, y, mPaint); } /** * 更新進度 * * @param progress */ public void setValue(int progress) { this.progress = progress; invalidate(); } /** * 設置進度圓環的樣式 * * @param isRing true是空心的圓環,false表示實心的圓環 */ public void setCircleRingStyle(boolean isRing) { this.isRingStyle = isRing; } /** * 設置背景透明度 * * @param alpha 0~255 */ public void setCircleBackgroundAlpha(int alpha) { this.circleBackgroundAlpha = alpha; } /** * 設置進度文本的大小 * @param progressTextSize */ public void setProgressTextSize(int progressTextSize) { this.progressTextSize = progressTextSize; } /** * 設置進度文本的顏色 * @param progressTextColor */ public void setProgressTextColor(int progressTextColor) { this.progressTextColor = progressTextColor; } }
測試類
public class MainActivity extends AppCompatActivity { private CircleProgressView mCircleProgressView; private int progress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCircleProgressView = (CircleProgressView) findViewById(R.id.progressView); mCircleProgressView.setCircleRingStyle(false);//實心圓 HandlerThread thread = new HandlerThread("draw-thread"); thread.start(); Handler tHandler = new Handler(thread.getLooper()) { @Override public void handleMessage(Message msg) { runOnUiThread(new Runnable() { @Override public void run() { mCircleProgressView.setValue(progress++); } }); if (progress <100) { sendEmptyMessageDelayed(0, 100); } } }; tHandler.sendEmptyMessage(0); } }
XML使用方式
<?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="@color/colorAccent" tools:context="mchenys.net.csdn.blog.progressview.MainActivity"> <mchenys.net.csdn.blog.progressview.CircleProgressView android:id="@+id/progressView" android:layout_width="100dp" android:layout_height="200dp" android:layout_centerInParent="true" /> </RelativeLayout>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
本篇總結了Android開發常見過程中的內存洩漏問題。集合類洩漏??集合類如果僅僅有添加元素的方法,而沒有相應的刪除機制,導致內存被占用。如果這個集合類是全局性的變量 (
關於Android Studio的好處我就不用說了,下面兩點就足矣讓你轉投Android Studio了: 1、Andro
Android人臉識別技術用到的底層庫:android/external/neven/,framework 層:frameworks/base/media/java/an
本文講介紹android在3.0之後推出的一種新的動畫機制,屬性動畫,對動畫不了解的同學,可以先去看看繪圖篇——android動畫基礎這篇文章。好