Изменение количества столбцов в RecyclerView gridlayout
Я пытаюсь изменить количество столбцов, отображаемых в представлении recycler (макет сетки) на основе размера экрана. Однако я не мог найти подходящего способа его достижения. В настоящее время я использую treeViewObserver
для изменения количества столбцов на основе изменения размера экрана (во время ориентации). Поэтому, если приложение открывается в портретном режиме, количество столбцов (по телефону), оно решает быть одним, что хорошо выглядит, но этот метод не работает, когда приложение открывается прямо в ландшафтном режиме, когда одна сетчатая карта в сетке отображается на экране.
Здесь recList - это RecyclerView, а glm - GridLayoutManager, используемый в RecyclerView
viewWidth = recList.getMeasuredWidth();
cardViewWidthZZ = recList.getChildAt(0).getMeasuredWidth();
if (oldWidth == 0) {
oldWidth = cardViewWidthZZ;
}
if (oldWidth <= 0)
return;
int newSpanCount = (int) Math.floor(viewWidth / (oldWidth / 1.3f));
if (newSpanCount <= 0)
newSpanCount = 1;
glm.setSpanCount(newSpanCount);
glm.requestLayout();
С наилучшими пожеланиями
Ответы
Ответ 1
public class VarColumnGridLayoutManager extends GridLayoutManager {
private int minItemWidth;
public VarColumnGridLayoutManager(Context context, int minItemWidth) {
super(context, 1);
this.minItemWidth = minItemWidth;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler,
RecyclerView.State state) {
updateSpanCount();
super.onLayoutChildren(recycler, state);
}
private void updateSpanCount() {
int spanCount = getWidth() / minItemWidth;
if (spanCount < 1) {
spanCount = 1;
}
this.setSpanCount(spanCount);
}}
Ответ 2
Если вы указали фиксированную ширину столбца, вы можете расширить RecyclerView
и установить счетчик span в onMeasure
соответственно:
public AutofitRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
if (attrs != null) {
// Read android:columnWidth from xml
int[] attrsArray = {
android.R.attr.columnWidth
};
TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
columnWidth = array.getDimensionPixelSize(0, -1);
array.recycle();
}
manager = new GridLayoutManager(getContext(), 1);
setLayoutManager(manager);
}
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
if (columnWidth > 0) {
int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
manager.setSpanCount(spanCount);
}
}
Смотрите мой блог для получения дополнительной информации:
http://blog.sqisland.com/2014/12/recyclerview-autofit-grid.html
Ответ 3
Здесь мое решение.
public class ResponsiveGridLayoutManager extends GridLayoutManager {
boolean hasSetupColumns;
int columnWidthPx;
public ResponsiveGridLayoutManager(Context context, int orientation,
boolean reverseLayout, int columnWidthUnit, float columnWidth) {
super(context, 1, orientation, reverseLayout);
Resources r;
if (context == null) {
r = Resources.getSystem();
} else {
r = context.getResources();
}
float colWidthPx = TypedValue.applyDimension(columnWidthUnit,
columnWidth, r.getDisplayMetrics());
this.columnWidthPx = Math.round(colWidthPx);
}
public ResponsiveGridLayoutManager(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
int[] requestedValues = {
android.R.attr.columnWidth,
};
TypedArray a = context.obtainStyledAttributes(attrs, requestedValues);
this.columnWidthPx = a.getDimensionPixelSize(0, -1);
a.recycle();
}
@Override
public int getWidth() {
int width = super.getWidth();
if (!hasSetupColumns && width > 0) {
this.setSpanCount((int)Math.floor(width / this.columnWidthPx));
}
return width;
}
}
Вы можете использовать его с XML:
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="com.caff.localflix.ResponsiveGridLayoutManager"
android:columnWidth="148dp" />
Или Java:
ResponsiveGridLayoutManager layoutManager = new ResponsiveGridLayoutManager(
this,
GridLayoutManager.VERTICAL,
false,
TypedValue.COMPLEX_UNIT_DIP,
148f
);
Ответ 4
Вы можете создать файл ресурсов, зависящий от экрана, и загрузить его. Например, booleans.xml в папке значений-w820p. Или, возможно, просто создайте макет для больших экранов и сделайте с ним.