如何基于元素大小动态地为每个行添加不同列宽的GridLayout元素?

我有一个可变大小的标签array ,我想在gridlayout显示。 问题是标签的长度不同,即使某些标签比其他标签大得多,将它们置于statically定义的网格中看起来也很麻烦。

因此,我希望能够在标记之后添加标记,直到没有剩余空间用于完整标记,然后转到下一行。 基本上是这样的:

 | *** ****** ****** ** ***** | | ** ***** *** ********* *** | | ********* ***** *** | | ************** ******** | | ****** ******** ******** | | ***************** | | ************** ***** ***** | 

我想你们明白了。

现在,我得到了类似的东西,但它并不是我所需要的。

 int total = tags.size(); int column = 3; int row = total / column; suggestedTagsLayout.setColumnCount(column); suggestedTagsLayout.setRowCount(row + 1); for (int i = 0, c = 0, r = 0; i < total; i++, c++) { if (c == column) { c = 0; r++; } TextView tag = createNewTag(tags.get(i)); tag.setBackgroundColor(Color.BLUE); tag.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); GridLayout.Spec rowSpan = GridLayout.spec(GridLayout.UNDEFINED, 1); GridLayout.Spec colspan = GridLayout.spec(GridLayout.UNDEFINED, 1); if (r == 0 && c == 0) { logger.e("spec"); colspan = GridLayout.spec(GridLayout.UNDEFINED, 1); rowSpan = GridLayout.spec(GridLayout.UNDEFINED, 1); } logger.d("\n\ntag = " + tag.getText().toString()); int width = tag.getWidth(); int height = tag.getHeight(); logger.d("width = " + width); logger.d("height = " + height); width = tag.getMeasuredWidth(); height = tag.getMeasuredHeight(); logger.d("getMeasuredWidth = " + width); logger.d("getMeasuredHeight = " + height); GridLayout.LayoutParams gridParam = new GridLayout.LayoutParams( rowSpan, colspan); suggestedTagsLayout.addView(tag, gridParam); } 

这看起来更像是:

 | ***** **** ******** **** | | **** ******** | | ******* ****** | 

所以我也试图获取每个TextView的宽度,以便我可以手动计算空间并相应地添加项目,但这也是失败的,因为尺寸仍然是0因为它们没有被绘制。 所以我似乎必须相应地使用API​​来获得所需的行为。

我仍然是这个GridLayout新手,api非常大,所以你们能帮助我吗?

好吧,我设法通过计算需要多少空间和剩余多少空间来解决我自己的问题。 当标签插入的空间太小时,它将转到下一行。

 private void fillSuggestedTagsLayout() { // get all strings to insert in tag ArrayList tagsText = getTagsList(); // maps for connecting string to textview and string to textview width HashMap tagMap = new HashMap<>(); HashMap tagWidthMap = new HashMap<>(); // total width float totalWidth = 0; // for each string for (String s : tagsText) { // create textview TextView txtView = createNewTag(s, false); // store textview with string tagMap.put(s, txtView); // store width also tagWidthMap.put(s, txtView.getMeasuredWidth()); logger.d("width of txtView = " + txtView.getMeasuredWidth()); // count all textview widths in order to calculate amount of rows needed for display totalWidth += txtView.getMeasuredWidth(); } // gridlayout width to calculate rows needed final float layoutWidth = suggestedTagsLayout.getWidth(); logger.e("gridlayout width = " + layoutWidth); logger.e("total = " + totalWidth); // amount of rows equals to totalwidth of elements / layout width final float rows = totalWidth / layoutWidth; int rowsRounded = (int) rows; // rows needed could be 1,2 or something meaning that we need extra space. // every decimal will need to get rounded up. 1.2 becomes 2 for example if (rows > rowsRounded) { rowsRounded++; } // total amount of elements int total = tagsText.size(); // column count, 200 in order to have great precision in position of elements final int columns = 200; // amount of space needed per column final float dpPerColumn = layoutWidth / (float) columns; // set layout specs suggestedTagsLayout.setColumnCount(columns); suggestedTagsLayout.setRowCount(rowsRounded); for (int item = 0, column = 0, row = 0; item < total; item++) { // get string String s = tagsText.get(item); // get txtview TextView tag = tagMap.get(s); tag.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); // calculate amount of columns needed for tag. // tagwidth/sizePerColumn float colsToSpan = tagWidthMap.get(s) / dpPerColumn; // again, round up above in order to accomodate space needed int colsToSpanRounded = (int) colsToSpan; if (colsToSpan < colsToSpanRounded) { colsToSpanRounded++; } // now that we know the amount space needed for tag, // check if there is enough space on this row if ((column + colsToSpanRounded) > columns) { column = 0; row++; } // put tag on row N, span 1 row only GridLayout.Spec rowSpan = GridLayout.spec(row, 1); // put tag on column N, span N rows GridLayout.Spec colSpan = GridLayout.spec(column, colsToSpanRounded); logger.d("tag: " + s + " is taking " + colsToSpanRounded + " columns"); logger.d("c = " + column + " colsToSpan =" + colsToSpanRounded); logger.d("spanning between " + column + " and " + (column + colsToSpanRounded)); logger.d(" "); // increment column column += colsToSpanRounded; GridLayout.LayoutParams gridParam = new GridLayout.LayoutParams( rowSpan, colSpan); // add tag suggestedTagsLayout.addView(tag, gridParam); } } 

标签已创建并使用以下内容进行测量:

 private TextView createNewTag(final String tagText, boolean withImage) { TextView textView = new TextView(getActivity()); textView.setPadding(8,8,8,8); textView.setTypeface(Typeface.DEFAULT); textView.setText(tagText, TextView.BufferType.SPANNABLE); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); textView.setBackground(getActivity().getResources().getDrawable(R.drawable.tag_background)); if(withImage) { Drawable img = getActivity().getResources().getDrawable(R.drawable.delete_tag_icon); textView.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null); } int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); textView.measure(widthMeasureSpec, heightMeasureSpec); logger.d(tagText); return textView; } 

deviceWith通过以下方式计算:

 DisplayMetrics metrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); deviceWidth = metrics.widthPixels; deviceHeight = metrics.heightPixels;