編輯:關於Android編程
最近在做項目的時候,有個功能是訂單流程每個階段的時間段,這個和購物或者外賣的時候的下單、接單、配送類似!請看下圖
剛開始的做的時候,沒有想過自定義還是按照之前的想法,ui作圖根據狀態替換圖片之類的,後面做著做著感覺好煩,而且這個為了以後方便人調用之類的,所以開始自定義封裝!
分析:
1:總共有五個狀態,已支付、已接單、等待配送、已簽收、待評價
這五個點根據屏幕五等分,每個圓心按照比例相加畫大空心圓和小的實心圓。
2:畫實線和虛線,根據五等分的比例算出每兩個相鄰的圓之間的x
長度,左右兩邊分別加2和減2(留出縫隙處理),這樣就可以畫出
實線和虛線(實線和虛線根據數據來處理)虛線處理稍微復雜一點,見代碼注解
3:現在畫時間和狀態,這裡需要居中處理,剛開始的沒有處理,導致字體和圓心沒有垂直居中!具體的處理的方法代碼有明確說明
給出自定義類:
package org.yidont.ylife.send.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathEffect; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import org.yidont.ylife.send.R; import org.yidont.ylife.send.bean.OrderStatusDescribeInfo; import java.util.ArrayList; import java.util.List; /** * Created by li4236 on 16/6/21. * [email protected] */ public class CustomRoundTrue extends View { private final Paint paint; private final Context context; public CustomRoundTrue(Context context) { // TODO Auto-generated constructor stub this(context, null); } public CustomRoundTrue(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub this.context = context; this.paint = new Paint(); this.paint.setAntiAlias(true); //消除鋸齒 this.paint.setStyle(Paint.Style.FILL); //繪制空心圓 } // int number = 5; int radius = 30;//圓的半徑 int vivio = 4;//控制顯示多少個實心圓 // int state = 2;//控制底部文字顯示 float mFloat[]; @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub //平分控件的高度,每段的高度 radius = dip2px(15); int height =getHeight() / 2; //平分寬度十等分 int width = getWidth() / (5 * 2); //畫虛線的設置////////start/////////// int cc = 2 * width - 2 * radius - 4;//計算虛線或者實線的寬度 ,-4是因為左右兩邊圓各自留出2的距離 查看99和100行 mFloat = new float[cc / 2]; for (int i = 0; i < cc / 2; i++) { mFloat[i] = 3;//虛線的寬度初始化 } //畫虛線的大小////////end/////////// //1 畫最上層的圓///////////////start////////////// int circleY = height - radius - radius / 2; for (int i = 0; i < mornal.size(); i++) { OrderStatusDescribeInfo info = mornal.get(i); int circleX = width + i * 2 * width; this.paint.setARGB(255, 153, 153, 153); this.paint.setStrokeWidth(2); if (info.getStatus().equals("0")) { //畫虛圓 canvas.drawCircle(circleX, circleY, radius, this.paint); } else { //畫實圓 drawReal(circleX, circleY, canvas); } } boolean really = false; for (int j = 0; j < mornal.size()-1; j++) { //畫線 really = true; int n = j+1; if (n < mornal.size()) { OrderStatusDescribeInfo info1 = mornal.get(n); if (info1.getStatus().equals("0"))//獲取下一個數據是空的 really = false; } int lineX = width + j * 2 * width + radius + 2; //+2是為了留出縫隙 int lineX1 = (width + j * 2 * width) + 2 * width - radius - 2;//-2是為了留出縫隙 if (!really) { //畫虛線 Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.DKGRAY); Path path = new Path(); path.moveTo(lineX, circleY);//起點 x/y path.lineTo(lineX1, circleY);//終點 x/y PathEffect effects = new DashPathEffect(mFloat, 1);//虛線數組 paint.setPathEffect(effects); canvas.drawPath(path, paint); } else {//畫實線 this.paint.setARGB(255, 255, 108, 0); canvas.drawLine(lineX, circleY, lineX1, circleY, paint); } } //1 畫最上層的圓///////////////end////////////// //2 畫最下層的文字///////////////start////////////// int txtY = height + radius;//第一行文字的Y高度 Paint mPaintLines = new Paint(Paint.ANTI_ALIAS_FLAG); mPaintLines.setStrokeWidth(3); mPaintLines.setTextSize(dip2px(14)); mPaintLines.setTextAlign(Paint.Align.LEFT); Rect rect = new Rect(); for (int i = 0; i < mornal.size(); i++) { OrderStatusDescribeInfo info = mornal.get(i); int lineX = width + i * 2 * width;//每個字符串x坐標 mPaintLines.getTextBounds(info.getText(), 0, 1, rect);//可以獲取字體寬高 float awayY2 = txtY + rect.height() + radius / 2;//底層文字y高度計算 if (info.getStatus().equals("1")) {//需要顯示的時間和文字 //畫時間 mPaintLines.setColor(getResources().getColor(R.color.send_time)); mPaintLines.getTextBounds(info.getTime(), 0, info.getTime().length(), rect); canvas.drawText(info.getTime(), lineX - rect.width() / 2, txtY, mPaintLines); //畫送貨的狀態 mPaintLines.setColor(getResources().getColor(R.color.send_state)); mPaintLines.getTextBounds(info.getText(), 0, info.getText().length(), rect); canvas.drawText(info.getText(), lineX - rect.width() / 2, awayY2, mPaintLines); } else { //單個送貨的狀態 mPaintLines.setColor(getResources().getColor(R.color.send_state_gray)); mPaintLines.getTextBounds(info.getText(), 0, info.getText().length(), rect); canvas.drawText(info.getText(), lineX - rect.width() / 2, awayY2, mPaintLines); // //單個送貨的狀態 ======= 居中顯示 // mPaintLines.setColor(getResources().getColor(R.color.send_state_gray)); // mPaintLines.getTextBounds(info.getText(), 0, info.getText().length(), rect); // // float awayY = awayY2 / 2 + height / 2 + rect.height() / 2;//設置字體垂直居中計算高度 // canvas.drawText(info.getText(), lineX - rect.width() / 2, awayY, mPaintLines); } } //2 畫最下層的文字///////////////end////////////// super.onDraw(canvas); } public void drawReal(int x, int y, Canvas canvas) { // 繪制外圓 this.paint.setARGB(255, 255, 108, 0); this.paint.setStrokeWidth(2); canvas.drawCircle(x, y, radius, this.paint); //繪制圓環 this.paint.setColor(Color.WHITE); // this.paint.setStrokeWidth(ringWidth); canvas.drawCircle(x, y, radius - 3, this.paint); //繪制內圓 this.paint.setARGB(255, 255, 108, 0); this.paint.setStrokeWidth(2); canvas.drawCircle(x, y, radius / 3, this.paint); } /** * 根據手機的分辨率從 dp 的單位 轉成為 px(像素) */ public int dip2px( float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } public Listmornal = new ArrayList<>(); public void setMornal(List mornal) { this.mornal = mornal; vivio = mornal.size();//控制顯示多少個實心圓 invalidate(); } }
實體類:
package org.yidont.ylife.send.bean; /** * Created by li4236 on 16/7/28. * [email protected] */ public class OrderStatusDescribeInfo { private String status; private String time; private String text; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } public String getText() { return text; } public void setText(String text) { this.text = text; } }
布局使用:
使用方法:
CustomRoundTrue mRoundTrue = (CustomRoundTrue) findViewById(R.id.send_round); Listmornal = new ArrayList<>(); mRoundTrue.setMornal(mornal);
實際項目效果圖
行為變更Android N 除了提供諸多新特性和功能外,還對系統和 API 行為做出了各種變更。本文重點介紹您應該了解並在開發應用時加以考慮的一些重要變更。如果您之前發布
效果說明:滑竿指示器,是一段彎曲的圓弧,要求在桿上,有滑動小球事件,小球會根據下標文字的起始角度與終止角度,是否選擇滑倒下一個位置。當點擊下標文字時,小球也要做出相應的
字體管家是最好的字體下載工具,提供字體下載、字體備份、字體預覽、字體修復功能,永久免費的好軟件,為您提供最好用的字體下載字體備份字體安裝軟件。我們來看看如何
首先看看效果圖(錄制的gif有點卡,真實的效果還是很流暢的)實現思路通過上面的gif圖可以得出結論,其實它就是同時繪制兩條文本信息,然後通過動畫不斷的改變兩條文本信息距離