項目需要,需要做一個自上而下的流程節點圖,實現過程如下,當然不是最終實現效果;
- 自定義屬性
首選在values文件下建一個attrs文件,內容如下
<resources>
<declare-styleable name="ProcessView">
<attr name="itemColor" format="color" />
<attr name="verticalNum" format="integer" />
<attr name="horizontalNum" format="string" />
<attr name="itemWidth" format="dimension" />
<attr name="itemHeight" format="dimension" />
<attr name="itemTextSize" format="dimension" />
<attr name="itemVerticalSpace" format="dimension" />
<attr name="itemHorizontalSpace" format="dimension" />
</declare-styleable>
</resources>
- 選擇和設置構造方法;
然後自定義的ProcessView 繼承view
public ProcessView(Context context) {
this(context, null);
}
public ProcessView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs);//初始化自定義屬性
}
- 重寫onMeasure()方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(View.MeasureSpec.getSize(widthMeasureSpec), measureSize(1));
}
- 重寫onDraw()方法
@Override
public void onDraw(Canvas canvas) {
for (int vIndex = 0; vIndex < verticalNum; vIndex++) {
List<Rect> list = new ArrayList<>();
int hNum = Integer.parseInt(horizontalNum[vIndex]);
// item實際寬度
int tempWidth = (getWidth() - horizontalSpace * (hNum - 1)) / hNum;
for (int hIndex = 0; hIndex < hNum; hIndex++) {
Rect rectBorder = new Rect();
String str = texts.get(vIndex).get(hIndex);
rectBorder.top = (vIndex) * itemHeight + (vIndex) * verticalSpace;
rectBorder.bottom = rectBorder.top + itemHeight;
if (tempWidth >= itemWidth) {
// 距離兩邊的距離
int margin = (getWidth() - (itemWidth * hNum + (hNum - 1) * horizontalSpace)) / 2;
rectBorder.left = margin + hIndex * itemWidth + hIndex * horizontalSpace;
rectBorder.right = itemWidth + rectBorder.left;
} else {
rectBorder.left = hIndex * tempWidth + hIndex * horizontalSpace;
rectBorder.right = tempWidth + rectBorder.left;
}
drawContent(canvas, rectBorder, str);
drawLinkLine(canvas, rectBorder, hNum, vIndex);
list.add(rectBorder);
}
rects.put(vIndex, list);
}
}
- 文字內容
public HashMap<Integer, List<String>> getTextShow() {
List<String> text1 = Arrays.asList("執行通知");
List<String> text2 = Arrays.asList("送達文書");
List<String> text3 = Arrays.asList("強行措施", "財產調查", "解除措施");
List<String> text4 = Arrays.asList("查詢存款", "搜查", "傳喚", "懸賞執行");
List<String> text5 = Arrays.asList("查明財產");
List<String> text6 = Arrays.asList("查封", "扣押", "凍結", "扣劃", "評估", "拍賣");
List<String> text7 = Arrays.asList("執行和解", "終本約談", "自動履行");
HashMap<Integer, List<String>> map = new HashMap<Integer, List<String>>();
map.put(0, text1);
map.put(1, text2);
map.put(2, text3);
map.put(3, text4);
map.put(4, text5);
map.put(5, text6);
map.put(6, text7);
return map;
}
- 畫文字
/**
* 畫文字和背景
*/
private void drawContent(Canvas canvas, Rect rect, String str) {
canvas.drawRect(rect, paint);
canvas.drawText(str
, (rect.right + rect.left) / 2f
, (rect.bottom + rect.top) / 2f + textHeight / 2 - paint.getFontMetrics().descent
, paint);
}
- 畫連線
/***
* 畫連接線
* @param rect 當前Item的Rect
* @param currHNum 當前的水平方向 有多少個Item
* @param vIndex 當前是垂直方向的第幾個
*/
private void drawLinkLine(Canvas canvas, Rect rect, int currHNum, int vIndex) {
int stopX = getX(rect);
int startX = getX(rect);
if (vIndex < verticalNum - 1) {
//畫Item下面一半的垂直連接線
canvas.drawLine(startX, rect.bottom, stopX, (rect.bottom + verticalSpace / 2f), paint);
//畫水平連接線
if (currHNum > 1 && lastItemRect != null && lastItemRect.top == rect.top) {
canvas.drawLine(getX(lastItemRect), (rect.bottom + verticalSpace / 2f), getX(rect), (rect.bottom + verticalSpace / 2f), paint);
}
}
if (vIndex != 0) {
//畫Item上面一半的垂直連接線
canvas.drawLine(startX, (rect.top - verticalSpace / 2f), stopX, rect.top, paint);
//畫水平連接線
if (currHNum > 1 && lastItemRect != null && lastItemRect.top == rect.top) {
canvas.drawLine(getX(lastItemRect), (rect.top - verticalSpace / 2f), getX(rect), (rect.top - verticalSpace / 2f), paint);
}
}
lastItemRect = rect;
}
- 佈局文件
<com.example.test.shundemo.ProcessView1
android:layout_marginTop="17dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="51dp"
android:id="@+id/process_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:horizontalNum="1,1,3,4,1,6,3"
app:itemColor="#303030"
app:itemHeight="35dp"
app:itemHorizontalSpace="15dp"
app:itemTextSize="14dp"
app:itemVerticalSpace="45dp"
app:itemWidth="80dp"
app:verticalNum="7" />
更多效果圖見下
Demo地址https://github.com/shunplus/ProcessView