带有自适应内容项的RecyclerView

4

我需要实现下一个UI元素:

enter image description here

  • 未知大小的字符串列表(来自服务器调用)
  • 任何项都应该是包裹内容。
  • 如果一个项不适合行,他将在下一行。
  • 所有列表/网格都居中

我考虑使用RecyclerViewStaggeredGridLayoutManager

但我不知道这是否正确,有什么想法吗?


如果您的数据相对静态,可能最容易的方法是扩展ViewGroup,并覆盖onLayout()。您需要获取每个子元素的宽度,并将其放置在正确的行中。我以前没有使用过StaggeredGridLayoutManager,那也可能行。 - fractalwrench
Gaana应用程序在应用程序中搜索标签时使用相同的用户界面。数据不来自服务器,但数据也不是静态的。也许您想检查该应用程序以获取一些线索。 - Green goblin
@fractalwrench和^GreenGoblin谢谢你们,但正如我在问题中提到的那样,数据不是静态的,可能是1个字符串或90个。 - David
在这种情况下,您需要使用RecyclerView并子类化LayoutManager。 - fractalwrench
@fractalwrench 嗯,这个 LayoutManager 的子类应该包含什么内容? - David
2个回答

3
你每行单元格数量不同的事实意味着你需要非常努力地才能从回收方法中得到任何价值。因为为了知道哪些数据放在第17行,你必须(预)测量0-16行所有数据。
根据您的使用情况。如果列表项有合理数量的限制。使用一个单独的TextView,并巧妙地使用spans可能是更好的解决方案。只需将所有标签都收集到一个字符串中,并使用RoundedBackgroundSpan(参见链接)添加有色背景,然后将整个内容包装在ScrollView中。
编辑1:添加可能的解决方案代码。
public class RoundedBackgroundSpan extends ReplacementSpan {

    int mBackgroundColor;
    int mTextColor;
    float mRoundedCornerRadius;
    float mSidePadding = 10; // play around with these as needed
    float mVerticalPadding = 30; // play around with these as needed

    public RoundedBackgroundSpan(final int backgroundColor, final int textColor, final float roundedCornerRadius)
    {
        mBackgroundColor = backgroundColor;
        mTextColor = textColor;
        mRoundedCornerRadius = roundedCornerRadius;
    }

    @Override
    public int getSize(final Paint paint, final CharSequence text, final int start, final int end, final Paint.FontMetricsInt fm)
    {
        return Math.round(MeasureText(paint, text, start, end) + (2 * mSidePadding));
    }

    @Override
    public void draw(final Canvas canvas, final CharSequence text, final int start, final int end, final float x, final int top, final int y, final int bottom, final Paint paint)
    {
        // draw the rounded rectangle background
        RectF rect = new RectF(x, -mVerticalPadding + ((bottom + top) / 2) + paint.getFontMetrics().top, x + MeasureText(paint, text, start, end) + (2 * mSidePadding), mVerticalPadding + ((bottom + top) / 2) + paint.getFontMetrics().bottom);
        paint.setColor(mBackgroundColor);
        canvas.drawRoundRect(rect, mRoundedCornerRadius, mRoundedCornerRadius, paint);
        // draw the actual text
        paint.setColor(mTextColor);
        canvas.drawText(text, start, end, x + mSidePadding, ((bottom + top) / 2), paint);
    }

    private float MeasureText(Paint paint, CharSequence text, int start, int end)
    {
        return paint.measureText(text, start, end);
    }

}

在其他地方(很可能是活动/片段)

    SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
    for (String hashTag : hashTags)
    {
        stringBuilder.append(hashTag);
        stringBuilder.setSpan(new RoundedBackgroundSpan(getRandomColor(), getResources().getColor(android.R.color.darker_gray), 10), stringBuilder.length() - hashTag.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        stringBuilder.append(" ");
    }

    textView.setText(stringBuilder);

在你的xml文件中的某个位置(请注意android:lineSpacingMultiplier="3"和android:gravity="center")

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:lineSpacingMultiplier="3"
        android:gravity="center"
        android:padding="10dp"
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</ScrollView>

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接