问题
I need to implement next UI element:
- Unknown size list of strings (That came from a server call)
- Any item should be wrap content.
- If an item is not fits to row, he will be in the next row.
- All list/grid is centered
I thought of using RecyclerView
with StaggeredGridLayoutManager
But I don't know if it the right way, any ideas?
回答1:
I don't sure that method would be helpful for you, but instead of
using RecyclerView with StaggeredGridLayoutManager
you can use third-party FlowLayout
:
First implementation (Android flow layout)
Second implementation (Flow layout)
Check this gist for full example:
https://github.com/davidbeloo/Hashtags
回答2:
The fact that you have a varying number of cells in each row means you would have to work rather hard to get any value from a recycling approach. Because in order to know which data goes in row 17 you have to (pre) measure all the data in rows 0 - 16.
Depending on your use case. If the list is bounded at some reasonable number of items. Using a single TextView
, with some clever use of spans may be a better solution. Just collect all your hashtags into a single string, and use RoundedBackgroundSpan
(see link) to add the colored backgrounds. then wrap the whole thing in a ScrollView
.
EDIT 1: Added possible solution code.
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);
}
}
And somewhere else (activity / fragment most likely)
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);
And somewhere in your xml (note android:lineSpacingMultiplier="3" and 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>
来源:https://stackoverflow.com/questions/34245154/recyclerview-with-wrap-content-items