Android實現無序樹形結構圖,類似思維導圖和級聯分層圖(無序,隨機比特置)

芝麻粒兒 2021-08-15 13:37:23 阅读数:228

本文一共[544]字,预计阅读时长:1分钟~
android 比特

這是我參與8月更文挑戰的第14天,活動詳情查看:8月更文挑戰

關於作者

眾所周知,人生是一個漫長的流程,不斷克服困難,不斷反思前進的過程。在這個過程中會產生很多對於人生的質疑和思考,於是我决定將自己的思考,經驗和故事全部分享出來,以此尋找共鳴!!!
專注於Android/Unity和各種遊戲開發技巧,以及各種資源分享(網站、工具、素材、源碼、遊戲等)

即將學會

不實使用什麼框架,就用基礎的代碼,實現層級導圖。

背景

今天七夕快樂呀,小芝和小空今天一起吃了漢堡,很好吃哦!

實踐過程

最近公司的醫療項目需要用到這個,需求是病例之間的狀態跳轉,醫學方面比如急救的時候有一些比較成熟的操作流程和步驟,緊急情况下是可以略過的,所以軟件就要模擬出來狀態的跳轉。而項目展示的狀態就像親屬關系圖類似。

先看下我們的效果吧

剛開始的時候,小空腦子也是空空的,毫無頭緒,在諮詢了同事其他端實現的思路後,轉為Android的實現技術。

大致思路如下:

  1. 如何添加這些控件
  2. 如何比特置隨機
  3. 畫線和畫不封閉的箭頭
  4. 擴展性

有了這些想法,我們就要實際動手操作了:這些仍逃不出自定義的範圍:

public class BLzgView extends RelativeLayout {
private Button blzg_btn;
private TextView blzg_title_tv, blzg_describe_tv;
public BLzgView(Context context) {
this(context,null);
}
public BLzgView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.view_blzg, this, true);
blzg_describe_tv=(TextView) findViewById(R.id.blzg_describe_tv);
blzg_title_tv=(TextView) findViewById(R.id.blzg_title_tv);
blzg_btn=(Button) findViewById(R.id.blzg_btn);
}
public void setTitleText(String tString){
blzg_title_tv.setText(tString);
}
public void setDecribeText(String string){
blzg_describe_tv.setText(string);
}
public void setBtnClickListener(OnClickListener onClickListener){
if (onClickListener!=null) {
blzg_btn.setOnClickListener(onClickListener);
}
}
//更改btn背景
//如果需要其他的需求再接著寫
}
複制代碼

下面是我們的布局文件,1個Button和2個TextView:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="120dp"
android:layout_height="70dp"
android:layout_gravity="center_horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/blzg_btn"
android:layout_width="120dp"
android:layout_height="70dp"
android:layout_gravity="center_horizontal"
android:background="@mipmap/xxk_n" />
</LinearLayout>
<TextView
android:id="@+id/blzg_title_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_horizontal"
android:maxLines="1"
android:text="@string/blzg_title"
android:textColor="#ffffff" />
<TextView
android:id="@+id/blzg_describe_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center_horizontal"
android:maxLines="2"
android:text="內容描述"
android:textColor="@color/black" />
</merge>
複制代碼

有了這些基礎控件之後,就開始考慮不斷創建添加進去的問題了,其實不管是比特置隨機還是固定比特置都可以實現,具體看項目的需求了,小空做的項目應為要和其他端保持一致,所以給定了具體的畫布大小和比特置。

public class UnOrderTree extends Activity {
private DrawGeometryView line_view[] = new DrawGeometryView[30];
private RelativeLayout.LayoutParams[] layoutParams = new RelativeLayout.LayoutParams[15];
private RelativeLayout.LayoutParams[] layoutParams1 = new RelativeLayout.LayoutParams[15];
private BLzgView[] bLzgViews = new BLzgView[15];
private RelativeLayout insertLayout;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_unordertree);
insertLayout = (RelativeLayout) findViewById(R.id.layout_zone);
initData();//初始化數據
}
private int start_line_x = 0, start_line_y = 0;
private int topMargin = 0, leftMargin = 0;
private void initData() {
for (int i = 0; i < 6; i++) { // 開始繪制
topMargin = new Random().nextInt(20) * 30;
leftMargin = new Random().nextInt(10) * 40;
initUnOrder(start_line_x, start_line_y, topMargin, leftMargin, i, 0, 0, 2, 1, "");
start_line_x = leftMargin;
start_line_y = topMargin;
}
}
private void initUnOrder(int start_x, int start_y, int topMargin, int leftMargin, int i,
int line_start_x, int line_start_y, int tree_tier, int isleft, String data) {
bLzgViews[i] = new BLzgView(this);
bLzgViews[i].setBtnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(UnOrderTree.this, "功能快速開發中,敬請期待", Toast.LENGTH_SHORT).show();
}
});
bLzgViews[i].setTitleText("標題" + i);
bLzgViews[i].setDecribeText("內容" + i);
ScaleAnimation animation = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
animation.setInterpolator(new BounceInterpolator());
animation.setStartOffset(100);// 動畫秒數。
animation.setFillAfter(true);
animation.setDuration(700);
bLzgViews[i].startAnimation(animation);
layoutParams[i] = new RelativeLayout.LayoutParams(120, 70); // 大小
layoutParams[i].topMargin = topMargin;
layoutParams[i].leftMargin = leftMargin; // 設置的按鈕比特置
insertLayout.addView(bLzgViews[i], layoutParams[i]);
if (i != 0) { //第一個不用畫線(畫線方式為:當前的坐標去找上一個坐標,之後連線)
line_view[i] = new DrawGeometryView(this, start_x + 60, start_y + 70,
leftMargin + 40, topMargin, "線條", isleft);
layoutParams1[i] = new RelativeLayout.LayoutParams(800, 800);
line_view[i].invalidate();
layoutParams1[i].topMargin = 0;// line_y-600;//Math.min(line_y+100,button_y+100
layoutParams1[i].leftMargin = 0;// line_x+300;
insertLayout.addView(line_view[i], layoutParams1[i]);
}
}
}
複制代碼

從上段代碼可以看出,不管是添加狀態還是連線都是靠的基本的addView,然後利用數組初始多個最開始咱們自定義的那個View,坐標的比特置就是topMargin和leftMargin的值(相對於屏幕左上角,即給的坐標)。思路確實是挺另類的。

接著就是劃線了,當走到這的時候,我們就已經知道了各個自定義View的坐標比特置,畢竟靠的是上面的addView,那麼畫線的起點和終點我們稍加計算也就很明確了。

public class DrawGeometryView extends View {
private int beginx = 0;
private int beginy = 0;
private int stopx = 100;
private int stopy = 100;
/**
* @param context
* @param attrs
*/
public DrawGeometryView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* @param context
*/
public DrawGeometryView(Context context, int beginx, int beginy, int stopx, int stopy, String word, int isleft) {
super(context);
this.beginx = beginx;
this.beginy = beginy;
this.stopx = stopx;
this.stopy = stopy;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint redPaint = new Paint(); // 紅色畫筆
redPaint.setAntiAlias(true); // 抗鋸齒效果,顯得繪圖平滑
redPaint.setColor(Color.BLACK); // 設置畫筆顏色
redPaint.setStrokeWidth(2.0f);// 設置筆觸寬度
redPaint.setStyle(Style.STROKE);// 設置畫筆的填充類型(完全填充)
redPaint.setTextSize(50);// 字體
Path mPath = new Path();
mPath.reset();
// 起點
mPath.moveTo(beginx, beginy);
// 貝塞爾曲線
// mPath.cubicTo(beginx+80, beginy, beginx+80, stopy,stopx-100, stopy);
mPath.cubicTo(beginx, beginy + 30, stopx, stopy - 50, stopx, stopy);
// // 畫直線
// mPath.lineTo(stopx, stopy);
// 畫path
canvas.drawPath(mPath, redPaint);
//下面是畫箭頭線的
Paint left_paint = new Paint();
Paint right_paint = new Paint();
Path left_path = new Path();
Path right_path = new Path();
left_path.reset();
right_path.reset();
left_paint.setAntiAlias(true);
left_paint.setColor(Color.BLACK);
right_paint.setAntiAlias(true);
right_paint.setColor(Color.BLACK);
left_paint.setStrokeWidth(2.0f);
right_paint.setStrokeWidth(2.0f);
left_paint.setStyle(Style.STROKE);
right_paint.setStyle(Style.STROKE);
left_path.moveTo(stopx, stopy);
right_path.moveTo(stopx, stopy);
left_path.quadTo(stopx - 3, stopy - 3, stopx - 6, stopy - 6);
right_path.quadTo(stopx + 3, stopy - 3, stopx + 6, stopy - 6);
canvas.drawPath(left_path, left_paint);
canvas.drawPath(right_path, right_paint);
}
}
複制代碼

畫線使用自定義View的canvas,drawPath這些就好了,為了讓線條看起來更加的絲滑性感,小空加上了貝塞爾曲線,還有線頭(其實只要在起點重點坐標點延長出兩個線段就搞定了)

大致的效果出來了;恩 需求解决!若您有相近的需求或解决思路,歡迎在下方留下地址!

另外,既然是自定義的View,那加動畫肯定沒問題;除了這些,還能更完善:比如箭頭的平滑,大控件的各種事件等等,暫時待續.....

其他

作者:小空和小芝中的小空
轉載說明:務必注明來源:芝麻粒兒 的個人主頁 (juejin.cn)
歡迎點贊收藏留言

版权声明:本文为[芝麻粒兒]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/08/20210815133652428D.html