關於
作者
戴定康
博客:個人博客
Csdn:戴定康的博客
NodeProgressView
用來顯示物節點進度的自定義View,仿淘寶
版本尚未發佈到Jcenter,後續將會逐一發布,讓你使用更簡潔
使用
先拷貝View包下面的文件到你的項目,記得樣式等Attr文件也要複製,不然會報錯
在你的XMl文件中:
<com.nodeprogress.nodeprogress.view.NodeProgressView
android:id="@+id/npv_NodeProgressView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:width="2dp"
app:nodeRadius="5dp"
/>
然後第一步,你的物流數據,我們先假設幾條,一般要從服務器獲取
List<LogisticsData> logisticsDatas;
logisticsDatas = new ArrayList<>();
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【相城中轉倉】裝車,正發往【無錫分撥中心】已簽收,簽收人是【王漾】,簽收網點是【忻州原平】"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【相城中轉倉】裝車,正發往【無錫分撥中心】"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鴻運良鄉站】的【010058.269】正在派件"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("快件到達【濰坊市中轉部】,上一站是【】"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【濰坊市中轉部】裝車,正發往【濰坊奎文代派】"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("快件到達【濰坊】,上一站是【濰坊市中轉部】"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【武漢分撥中心】裝車,正發往【晉江分撥中心】"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鴻運良鄉站】的【010058.269】正在派件"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鴻運良鄉站】的【010058.269】正在派件"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鴻運良鄉站】的【010058.269】正在派件"));
logisticsDatas.add(new LogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鴻運良鄉站】的【010058.269】正在派件"));
第二,找到你的控件併爲其設置NodeProgressAdapter適配器
NodeProgressView nodeProgressView = (NodeProgressView) findViewById(R.id.npv_NodeProgressView);
nodeProgressView.setNodeProgressAdapter(new NodeProgressAdapter() {
@Override
public int getCount() {
return logisticsDatas.size();
}
@Override
public List<LogisticsData> getData() {
return logisticsDatas;
}
});
OK,大功告成,剩下的就是交給控件了,有興趣的童鞋可以看看源碼,寫的不是很好,多多指教,是不是很簡單呢;
下面將源碼貼出,大家可以看一看
NodeProgressView.class
/**
* User: Daidingkang([email protected])
* Date: 2016-06-28
* Time: 09:43
* FIXME
*/
public class NodeProgressView extends View {
float width;
float nodeRadius;
Paint paint;
Context context;
/**
* 節點間隔
*/
int nodeInterval;
/**
* 邊距
*/
int left = 20;
int top = 30;
int dWidth;
int dHeight;
public NodeProgressView(Context context) {
super(context);
this.context = context;
init();
}
public NodeProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NodeProgressView);
width = typedArray.getDimension(R.styleable.NodeProgressView_width, 5);
nodeRadius = typedArray.getDimension(R.styleable.NodeProgressView_nodeRadius, 10);
init();
}
public NodeProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint();
paint.setColor(getResources().getColor(R.color.nodeColor));
paint.setAntiAlias(true);
nodeInterval = dip2px(context, 80);
WindowManager wm = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
dWidth = wm.getDefaultDisplay().getWidth();
dHeight = wm.getDefaultDisplay().getHeight();
}
NodeProgressAdapter nodeProgressAdapter;
/**
* 設置適配數據
*/
public void setNodeProgressAdapter(NodeProgressAdapter nodeProgressAdapter) {
this.nodeProgressAdapter = nodeProgressAdapter;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (nodeProgressAdapter == null || nodeProgressAdapter.getCount() == 0)
return;
List data = nodeProgressAdapter.getData();
// canvas.translate(20,30);偏移位置,防止遮擋
canvas.drawRect(left, top, width + left, nodeProgressAdapter.getCount() * nodeInterval + top, paint);
for (int i = 0; i < nodeProgressAdapter.getCount(); i++) {
if (i == 0) {
Paint mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(getResources().getColor(R.color.nodeTextColor));
//畫文字
mPaint.setTextSize(30);
canvas.drawText(((LogisticsData)data.get(i)).getTime()+"", left * 2 + nodeRadius * 2 + 10, (i + 1) * nodeInterval + top - 20, mPaint);
// canvas.drawText("不換行", left * 2 + nodeRadius * 2 + 10, i * nodeInterval + top + (nodeInterval / 3), mPaint);
//文字換行
TextPaint textPaint = new TextPaint();
textPaint.setColor(getResources().getColor(R.color.nodeTextColor));
textPaint.setTextSize(35.0F);
textPaint.setAntiAlias(true);
StaticLayout layout = new StaticLayout(((LogisticsData)data.get(i)).getContext()+"", textPaint, (int) (dWidth * 0.8), Layout.Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);
canvas.save();
canvas.translate(left * 2 + nodeRadius * 2 + 10, i * nodeInterval + top + (nodeInterval / 4));
layout.draw(canvas);
canvas.restore();//重置
//畫圓
canvas.drawCircle(width / 2 + left, i * nodeInterval + top, nodeRadius + 2, mPaint);
mPaint.setStyle(Paint.Style.STROKE);//設置爲空心
mPaint.setStrokeWidth(8);//空心寬度
mPaint.setAlpha(88);
canvas.drawCircle(width / 2 + left, i * nodeInterval + top, nodeRadius + 4, mPaint);
} else {
paint.setColor(getResources().getColor(R.color.nodeColor));
canvas.drawCircle(width / 2 + left, i * nodeInterval + top, nodeRadius, paint);
canvas.drawLine(left * 2 + nodeRadius * 2, i * nodeInterval + top, dWidth, i * nodeInterval + top, paint); //畫線
//畫文字
paint.setTextSize(30);
canvas.drawText(((LogisticsData)data.get(i)).getTime()+"", left * 2 + nodeRadius * 2 + 10, (i + 1) * nodeInterval + top - 20, paint);
//文字換行
TextPaint textPaint = new TextPaint();
textPaint.setColor(getResources().getColor(R.color.nodeColor));
textPaint.setTextSize(35.0F);
textPaint.setAntiAlias(true);
StaticLayout layout = new StaticLayout(((LogisticsData)data.get(i)).getContext()+"", textPaint, (int) (dWidth * 0.8), Layout.Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);
canvas.save();//很重要,不然會樣式出錯
canvas.translate(left * 2 + nodeRadius * 2 + 10, i * nodeInterval + top + (nodeInterval / 4));
layout.draw(canvas);
canvas.restore();//重置
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (nodeProgressAdapter == null || nodeProgressAdapter.getCount() == 0)
return;
setMeasuredDimension(widthMeasureSpec, nodeProgressAdapter.getCount() * nodeInterval + top);
}
/**
* 根據手機的分辨率從 dp 的單位 轉成爲 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
值得注意的是使用此控件的童鞋,裏面有一個JavaBean需要實現,你也可以繼承自此Bean
源碼下載
點擊即可下載 NodeProgressView
下載的童鞋希望多多star and fork;
實例: