【问题标题】:Changing number of columns with GridLayoutManager and RecyclerView使用 GridLayoutManager 和 RecyclerView 更改列数
【发布时间】:2015-06-17 06:10:44
【问题描述】:

在我的片段中,我通过以下方式设置我的 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));
        }
    }

提前致谢!

【问题讨论】:

  • 请添加崩溃日志
  • 我刚刚查看了我的 logcat,但这并没有导致崩溃。但它仍然无法正常工作。
  • 我不会创建新的经理,而是使用现有的经理。在您的 recyclerview 上使用 getLayoutManager(),将其转换为 GridLayoutManager。在该经理调用 setSpanCount(orientation == Portrait ? 2 : 4) 并且为了重绘视图调用 adaper.notifyDatasetChanged() 如果您的视图不是每次都重绘,这应该可以正常工作。
  • 哇!这听起来像是我在寻找,但我不知道如何实现。我会尝试并告诉你。
  • 请注意,在创建视图本身时检查方向总是一个好主意。您通常在活动的 onCreate 或片段的 onCreateView 中执行此操作。确保您这样做,因为您的用户可能会以横向模式启动活动

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


【解决方案1】:

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

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
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我会尝试并告诉你。谢谢!
    • 这是执行此任务的正确行为吗?谢谢
    • @ciccioska 我认为resource folders 比在getConfiguration()onConfigurationChanged 上执行条件更好。另请参阅我对这个问题的回答。
    【解决方案3】:

    回收视图支持 AutofitRecycleView。

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

    你可以参考这个AutofitRecycleViewLink

    【讨论】:

    • 出色的实现!旋转屏幕动态改变列数并保持滚动位置
    • 这可能是最完美的解决方案,但如果您的设计师做出不同的决定,则不是。有时设计只是让我们很难实现
    【解决方案4】:

    确定编号的更可靠方法。的列将根据屏幕宽度和运行时计算。我通常使用以下函数。

    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
    }
    

    这是一种更动态的方法来准确计算编号。的列。这将更适合不同屏幕尺寸的用户,而不会仅限于两个可能的值。

    注意:您可以改变 scalingFactor 变量的值。越小越没有。您可以显示的列数,值越大,编号越少。将计算列数。它是根据您的需求调整的比例因子。

    【讨论】:

      【解决方案5】:

      除了答案。也可以仅使用 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】:

        在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);           
            }
        }
        

        【讨论】:

          【解决方案7】:

          我最终在 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();
          }
          

          它非常适合我的应用程序。

          【讨论】:

            【解决方案8】:

            您可以在您的 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"/>
            

            然后将变量设置为values文件夹values/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));
            }
            

            【讨论】:

              【解决方案9】:

              我将尝试一步一步地解释它。您可以查看我分享的 github 项目的 integers.xml、integers.xml (land) 和 MainFragment 文件。您将看到列数会根据方向或屏幕尺寸(平板电脑与手机)而变化(我将仅解释在方向改变时如何做,因为问题只是关于它)。 https://github.com/b-basoglu/NewsApp/blob/master/app/src/main/java/com/news/newsapp/ui/main/MainFragment.kt

              1. 创建一个名为 integers.xml 的资源文件。 -> 在 Project > Android 窗格中打开 res 文件夹,右键单击 values 文件夹,然后选择 New > Values 资源文件。

              2. 将文件命名为 integers.xml 并单击“确定”。

              3. 在标签之间创建一个名为 grid_column_count 的整数常量,并将其设置为等于 2:

                2整数>

              4. 创建另一个值资源文件,再次称为 integers.xml;但是,当您从可用限定符窗格添加资源限定符时,名称将被修改。资源限定符用于标记各种情况下的资源配置。

              5. 在可用限定符窗格中选择方向,然后按对话框中间的 >> 符号来分配此限定符。

              6. 将屏幕方向菜单更改为横向,并注意目录名称 values-land 的显示方式。这是资源限定符的本质:目录名称告诉 Android 何时使用该特定布局文件。在这种情况下,即手机旋转到横向模式时。

              7. 点击确定生成新的布局文件。

              8. 将您创建的整数常量复制到这个新资源文件中,但将值更改为 4。

                4整数>

              [你有这些文件][1]

              1. 现在您所要做的就是在配置更改时重新分配跨度计数,如下所示:
                  override fun onConfigurationChanged(newConfig: Configuration) {
                      super.onConfigurationChanged(newConfig)
                      gridLayoutManager?.let {
                          it.spanCount = resources.getInteger(R.integer.grid_column_count)
                      }
                  }
                  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
                      super.onViewCreated(view, savedInstanceState)
                      gridLayoutManager = GridLayoutManager(requireContext(), 
                                              resources.getInteger(R.integer.grid_column_count))
                      ${yourRecyclerView}.layoutManager = gridLayoutManager
                      ...
                [1]: https://i.stack.imgur.com/3NZdq.png
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多