使用GridLayoutManager和RecyclerView更改列数

时间:2015-04-11 15:49:38

标签: android android-orientation android-gridlayout android-recyclerview

在我的片段中,我按以下方式设置GridLayout: mRecycler.setLayoutManager(new GridLayoutManager(rootView.getContext(), 2));

因此,我只想在用户旋转手机/平板电脑时为2更改4。我已经阅读了onConfigurationChanged,我试图让它适用于我的案例,但它并没有以正确的方式进行。当我旋转手机时,应用程序崩溃......

你能告诉我如何解决这个问题吗?

以下是我找到解决方案的方法,该方法无法正常工作:

  @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        int orientation = newConfig.orientation;

        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
        } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4));
        }
    }

提前致谢!

8 个答案:

答案 0 :(得分:75)

如果您有多个条件或在多个地方使用该值,这可能会非常快。我建议创建以下结构:

res
  - values
    - dimens.xml
  - values-land
    - dimens.xml

res/values/dimens.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="gallery_columns">2</integer>
</resources>

res/values-land/dimens.xml正在:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="gallery_columns">4</integer>
</resources>

然后代码变成(并永远保持)像这样:

final int columns = getResources().getInteger(R.integer.gallery_columns);
mRecycler.setLayoutManager(new GridLayoutManager(mContext, columns));

您可以轻松查看添加确定列数的新方法是多么容易,例如使用-w500dp / -w600dp / -w700dp资源文件夹而不是-land

将这些文件夹分组到单独的资源文件夹中也很容易,以防您不想混淆其他(更相关)的资源:

android {
    sourceSets.main.res.srcDir 'src/main/res-overrides' // add alongside src/main/res
}

答案 1 :(得分:63)

尝试在onCreateView方法中处理此问题,因为每次进行方向更改时都会调用它:

if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
}
else{
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4));
}

答案 2 :(得分:6)

回收视图支持AutofitRecycleView。

您需要在xml文件中添加android:numColumns="auto_fit"

您可以参考此AutofitRecycleViewLink

答案 3 :(得分:6)

更有力的方法来确定否。列将根据屏幕宽度和运行时计算它。我通常使用以下功能。

public static int calculateNoOfColumns(Context context) {
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
    int scalingFactor = 200; // You can vary the value held by the scalingFactor
    // variable. The smaller it is the more no. of columns you can display, and the
    // larger the value the less no. of columns will be calculated. It is the scaling
    // factor to tweak to your needs.
    int columnCount = (int) (dpWidth / scalingFactor);
    return (columnCount>=2?columnCount:2); // if column no. is less than 2, we still display 2 columns
}

准确计算no是一种更动态的方法。列。对于不同屏幕尺寸的用户而言,这将更具适应性,而不会仅限于两个可能的值。

NB:您可以更改 scalingFactor 变量所持有的值。它越小越不。您可以显示的列数,值越大,否则越少。列将被计算。这是根据您的需求调整的缩放因子。

答案 4 :(得分:2)

在onCreate()事件中,您可以使用StaggeredGridLayoutManager

mRecyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);      

mStaggeredGridLayoutManager = new StaggeredGridLayoutManager(
       1, //number of grid columns
       GridLayoutManager.VERTICAL);      

mRecyclerView.setLayoutManager(mStaggeredGridLayoutManager);

然后当用户旋转屏幕时捕获事件,并自动更改列数

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {           
            mStaggeredGridLayoutManager.setSpanCount(1);

    } else {           
            //show in two columns
            mStaggeredGridLayoutManager.setSpanCount(2);           
    }
}

答案 5 :(得分:2)

除了答案。也可以仅使用XML属性来完成。下面是代码。

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/pax_seat_map_rv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:spanCount="3"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" />

答案 6 :(得分:1)

我最终在onCreate方法中处理了这个问题。

private RecyclerView recyclerView = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    recyclerView.setHasFixedSize(true);
    Configuration orientation = new Configuration();
    if(this.recyclerView.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
    } else if (this.recyclerView.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
    }
            connectGetApiData();
}

它非常适合我的应用。

答案 7 :(得分:0)

您可以在recyclerView onMeasure中实现该方法。 首先,创建java类AutofitRecyclerView

public class AutofitRecyclerView extends RecyclerView {
//private GridLayoutManager manager;
private StaggeredGridLayoutManager manager;
private int columnWidth = -1;

public AutofitRecyclerView(Context context) {
    super(context);
    init(context, null);
}

public AutofitRecyclerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
}

public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
    if (attrs != null) {
        int[] attrsArray = {
                android.R.attr.columnWidth
        };
        TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
        columnWidth = array.getDimensionPixelSize(0, -1);
        array.recycle();
    }

    manager = new StaggeredGridLayoutManager(1, GridLayoutManager.VERTICAL);
    setLayoutManager(manager);

}

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
    super.onMeasure(widthSpec, heightSpec);
    if (columnWidth > 0) {
        int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
        manager.setSpanCount(spanCount);
    }
}}

在xlm布局文件activity_main.xml

<yourpackagename.AutofitRecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:columnWidth="@dimen/column_width"
            android:clipToPadding="false"/>

然后将变量设置为值文件夹值/ dimens.xml

的文件大小中每个项目的宽度
<resources>
  <dimen name="column_width">250dp</dimen>
</resources>

它可以用于不同的屏幕分辨率值-xxhdpi / dimens.xml

<resources>
 <dimen name="column_width">280dp</dimen>
</resources>

在onCreate事件的活动中,放置以下代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    recyclerView.addItemDecoration(new MarginDecoration(this));
    recyclerView.setHasFixedSize(true);
    recyclerView.setAdapter(new NumberedAdapter(50));
}