Skip to content

Repository files navigation

关于

作者


戴定康

博客:个人博客

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 = newArrayList<>();
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【相城中转仓】装车,正发往【无锡分拨中心】已签收,签收人是【王漾】,签收网点是【忻州原平】"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【相城中转仓】装车,正发往【无锡分拨中心】"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鸿运良乡站】的【010058.269】正在派件"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("快件到达【潍坊市中转部】,上一站是【】"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【潍坊市中转部】装车,正发往【潍坊奎文代派】"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("快件到达【潍坊】,上一站是【潍坊市中转部】"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("快件在【武汉分拨中心】装车,正发往【晋江分拨中心】"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鸿运良乡站】的【010058.269】正在派件"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鸿运良乡站】的【010058.269】正在派件"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鸿运良乡站】的【010058.269】正在派件"));
logisticsDatas.add(newLogisticsData().setTime("2016-6-28 15:13:02").setContext("【北京鸿运良乡站】的【010058.269】正在派件"));

第二,找到你的控件并为其设置NodeProgressAdapter适配器

NodeProgressViewnodeProgressView = (NodeProgressView) findViewById(R.id.npv_NodeProgressView);
nodeProgressView.setNodeProgressAdapter(newNodeProgressAdapter() {
@OverridepublicintgetCount() {
returnlogisticsDatas.size();
}
@OverridepublicList<LogisticsData> getData() {
returnlogisticsDatas;
}
});

OK,大功告成,剩下的就是交给控件了,有兴趣的童鞋可以看看源码,写的不是很好,多多指教,是不是很简单呢;


下面将源码贴出,大家可以看一看

NodeProgressView.class

/** * User: Daidingkang(ddk19941017@Gmail.com) * Date: 2016-06-28 * Time: 09:43 * FIXME */publicclassNodeProgressViewextendsView {
floatwidth;
floatnodeRadius;
Paintpaint;
Contextcontext;
/** * 节点间隔 */intnodeInterval;
/** * 边距 */intleft = 20;
inttop = 30;
intdWidth;
intdHeight;
publicNodeProgressView(Contextcontext) {
super(context);
this.context = context;
init();
}
publicNodeProgressView(Contextcontext, AttributeSetattrs) {
super(context, attrs);
this.context = context;
TypedArraytypedArray = context.obtainStyledAttributes(attrs, R.styleable.NodeProgressView);
width = typedArray.getDimension(R.styleable.NodeProgressView_width, 5);
nodeRadius = typedArray.getDimension(R.styleable.NodeProgressView_nodeRadius, 10);
init();
}
publicNodeProgressView(Contextcontext, AttributeSetattrs, intdefStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
privatevoidinit() {
paint = newPaint();
paint.setColor(getResources().getColor(R.color.nodeColor));
paint.setAntiAlias(true);
nodeInterval = dip2px(context, 80);
WindowManagerwm = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
dWidth = wm.getDefaultDisplay().getWidth();
dHeight = wm.getDefaultDisplay().getHeight();
}
NodeProgressAdapternodeProgressAdapter;
/** * 设置适配数据 */publicvoidsetNodeProgressAdapter(NodeProgressAdapternodeProgressAdapter) {
this.nodeProgressAdapter = nodeProgressAdapter;
}
@OverrideprotectedvoidonDraw(Canvascanvas) {
super.onDraw(canvas);
if (nodeProgressAdapter == null || nodeProgressAdapter.getCount() == 0)
return;
Listdata = nodeProgressAdapter.getData();
// canvas.translate(20,30);偏移位置,防止遮挡canvas.drawRect(left, top, width + left, nodeProgressAdapter.getCount() * nodeInterval + top, paint);
for (inti = 0; i < nodeProgressAdapter.getCount(); i++) {
if (i == 0) {
PaintmPaint = newPaint();
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);//文字换行TextPainttextPaint = newTextPaint();
textPaint.setColor(getResources().getColor(R.color.nodeTextColor));
textPaint.setTextSize(35.0F);
textPaint.setAntiAlias(true);
StaticLayoutlayout = newStaticLayout(((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);
//文字换行TextPainttextPaint = newTextPaint();
textPaint.setColor(getResources().getColor(R.color.nodeColor));
textPaint.setTextSize(35.0F);
textPaint.setAntiAlias(true);
StaticLayoutlayout = newStaticLayout(((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();//重置
}
}
}
@OverrideprotectedvoidonMeasure(intwidthMeasureSpec, intheightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (nodeProgressAdapter == null || nodeProgressAdapter.getCount() == 0)
return;
setMeasuredDimension(widthMeasureSpec, nodeProgressAdapter.getCount() * nodeInterval + top);
}
/** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */publicstaticintdip2px(Contextcontext, floatdpValue) {
finalfloatscale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}

值得注意的是使用此控件的童鞋,里面有一个JavaBean需要实现,你也可以继承自此Bean

源码下载

点击即可下载 NodeProgressView
下载的童鞋希望多多star and fork;

实例:

About

用来显示物流进度节点的自定义View,类似于淘宝

Resources

Stars

174 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages