【原创】【Andriod】自定义多行多列视图

【需求描述】最近要开发一个文本视图组件,满足如下几种样式:

 

 

                case 1: 三行两列,第一列的文字字数一样多

 

 

              case 2: 三行两列,第一列的文字字数不一样多,第一列的右边线与第二列的左边线的间距是一定的,第二列里的每一项,可能有1~3行

 

 

 

           case 3: 可能有1~3行

总结一下特点: 

1)第一列左对齐(每一项为单行文字),第二列左对齐(每一项为1~3行文字)
2)第二列距离第一列的最小间距是固定值
3)第一列第一条与第二列第一条顶对齐,以此类推,第一列第二条与第二列第二条顶对齐……

 

【技术方案】

         方案1:定义一个LinearLayout, 根据第一列文本的size和下发的文本来计算第一列的最大宽度,计算完成后,动态添加1~3个FrameLayout,1个FrameLayout中放每一行的子元素

         方案2:定义一个FrameLayout,根据第一列文本的size和下发的文本来计算第一列的最大宽度,然后计算出每一项的高度,分别对每个子元素进行布局。

  优点 缺点
方案1 方案简单,将每一行元素的高度计算交给FrameLayout 会多3个FrameLayout,需要多Measure和layout 3次
方案2 布局层次少,性能更优 需要考虑第二列的多行文本的高度计算

 

 方案1 核心代码如下:

 1 /**
 2      * 获取文本的长度
 3      *
 4      * @param displayText 待显示的文本
 5      * @return
 6      */
 7     private int getTextLength(String displayText) {
 8         Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 9         mTextPaint.setColor(getContext().getResources()
10                 .getColor(R.color.msg_pay_notify_producer_name_key_color));
11         mTextPaint.setTextSize(getContext().getResources().getDimensionPixelSize(
12                         R.dimen.msg_pay_notify_producer_name_size));
13         return (int) mTextPaint.measureText(displayText);
14     }
15 
16 
17 1、计算第一列的最大宽度
18         ArrayList<String> displayLists = new ArrayList<>();
19         for (PayCardModel.BodyItem item : bodys) {
20             displayLists.add(item.getMName());
21         }
22         
23         mFirstColumnWidth = 0;
24         for (String displayText : displayLists) {
25             mFirstColumnWidth = Math.max(mFirstColumnWidth, getTextLength(displayText));
26         }
27         
28         if (mFirstColumnWidth == 0) {
29             setVisibility(GONE);
30             return;
31         }
32         setVisibility(VISIBLE);
33         mFirstColumnWidth = mFirstColumnWidth > MAX_FIRST_COLUMN_WIDTH ?
34                 MAX_FIRST_COLUMN_WIDTH : mFirstColumnWidth;
35         mSecColumnLeftMargin = mFirstColumnWidth + getContext().getResources()
36                 .getDimensionPixelSize(R.dimen.msg_pay_notify_producer_name_margin_left);
37 
38 
39 2、动态添加子元素
40 /**
41      * 构造每一对数据需要的两个TextView
42      *
43      * @param item 数据对
44      * @return
45      */
46     private ViewGroup buildItemViews(PayCardModel.BodyItem item) {
47         if (!isDataValid(item)) {
48             return null;
49         }
50         FrameLayout layout = new FrameLayout(getContext());
51         LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
52                 ViewGroup.LayoutParams.WRAP_CONTENT);
53         TextView titleView = new TextView(getContext());
54         titleView.setText(item.getMName());
55         titleView.setTextColor(getContext().getResources()
56                 .getColor(R.color.msg_pay_notify_producer_name_key_color));
57         titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
58                 getContext().getResources().getDimensionPixelSize(
59                         R.dimen.msg_pay_notify_producer_name_size));
60         titleView.setMaxLines(MAX_TITLE_LINE);
61         titleView.setMaxEms(MAX_TITLE_EMS);
62         FrameLayout.LayoutParams titleParams = new FrameLayout.LayoutParams(mFirstColumnWidth,
63                 ViewGroup.LayoutParams.WRAP_CONTENT);
64         layout.addView(titleView, titleParams);
65     
66         TextView view = new TextView(getContext());
67         view.setText(item.getMValue());
68         view.setTextColor(getContext().getResources()
69                 .getColor(R.color.msg_pay_notify_source_color));
70         view.setTextSize(TypedValue.COMPLEX_UNIT_PX,
71                 getContext().getResources().getDimensionPixelSize(
72                         R.dimen.msg_pay_notify_producer_name_size));
73         view.setMaxLines(MAX_NAME_LINE);
74         view.setEllipsize(TextUtils.TruncateAt.END);
75         FrameLayout.LayoutParams viewParams = new FrameLayout.LayoutParams(
76                 ViewGroup.LayoutParams.WRAP_CONTENT,
77                 ViewGroup.LayoutParams.WRAP_CONTENT);
78         viewParams.leftMargin = mSecColumnLeftMargin;
79         layout.addView(view, viewParams);
80         addView(layout, layoutParams);
81         return layout;
82     }

 

 

 

posted on 2020-06-29 20:20  meizixiong  阅读(353)  评论(0编辑  收藏  举报