GridLayoutManager ve RecyclerView ile sütun sayısını değiştirme

Inside my fragment I'm setting my GridLayout in the following way: mRecycler.setLayoutManager(new GridLayoutManager(rootView.getContext(), 2));

Dolayısıyla, kullanıcı telefonu/tableti döndürdüğünde, 4 için bu 2 değerini değiştirmek istiyorum. onConfigurationChanged hakkında okudum ve davam için çalışmasını sağlamaya çalıştım, ancak doğru şekilde gitmiyor. Telefonumu döndürdüğümde uygulama çöküyor ...

Bana bu sorunu nasıl çözeceğimi söyler misiniz?

Doğru çalışmayan çözümü bulma yaklaşımım:

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

Şimdiden teşekkürler!

44
Temel olarak her iki cevabınızı da uyguladım. Bunun daha fazla dikkat çekmemesine şaşırdım. Bunu yapan birçok uygulama görüyorum.
katma yazar Jared Burrows, kaynak
Temel olarak her iki cevabınızı da uyguladım. Bunun daha fazla dikkat çekmemesine şaşırdım. Bunu yapan birçok uygulama görüyorum.
katma yazar Jared Burrows, kaynak
@fapps Sorunuz benim için çok iyi çalıştı, sizinkiler neden çöktü bilmiyorum. Neden olduğunu hiç düşündün mü?
katma yazar Jared Burrows, kaynak
@fapps Sorunuz benim için çok iyi çalıştı, sizinkiler neden çöktü bilmiyorum. Neden olduğunu hiç düşündün mü?
katma yazar Jared Burrows, kaynak
Yeni bir yönetici oluşturmazdım ama onun yerine mevcut olanı kullanırım. Geri dönüşüm görünümünüzde getLayoutManager() kullanın, onu GridLayoutManager'a aktarın. Bu yönetici çağrısı setSpanCount (orientation == portrait? 2: 4) Ve görünüm çağrısının yeniden çizilmesi uğruna adaper.notifyDatasetChanged() Görünümünüz her seferinde yeniden çizilmezse düzgün çalışmalıdır.
katma yazar Bojan Kseneman, kaynak
Yeni bir yönetici oluşturmazdım ama onun yerine mevcut olanı kullanırım. Geri dönüşüm görünümünüzde getLayoutManager() kullanın, onu GridLayoutManager'a aktarın. Bu yönetici çağrısı setSpanCount (orientation == portrait? 2: 4) Ve görünüm çağrısının yeniden çizilmesi uğruna adaper.notifyDatasetChanged() Görünümünüz her seferinde yeniden çizilmezse düzgün çalışmalıdır.
katma yazar Bojan Kseneman, kaynak
lütfen kilitlenme günlüğü ekle
katma yazar Bojan Kseneman, kaynak
Görünümü oluştururken yönlendirmeyi kontrol etmenin her zaman iyi bir fikir olduğunu unutmayın. Genellikle etkinlikler için onCreate veya fragmanlar için onCreateView'da yaptığınız. Bunu yaptığınızdan emin olun, çünkü kullanıcılarınız etkinliği yatay modda başlatabilir
katma yazar Bojan Kseneman, kaynak
Görünümü oluştururken yönlendirmeyi kontrol etmenin her zaman iyi bir fikir olduğunu unutmayın. Genellikle etkinlikler için onCreate veya fragmanlar için onCreateView'da yaptığınız. Bunu yaptığınızdan emin olun, çünkü kullanıcılarınız etkinliği yatay modda başlatabilir
katma yazar Bojan Kseneman, kaynak
Evet. Yönü değiştirdiğinizde görünüm varsayılan olarak yeniden çizilir, bu nedenle orada işlediğinizden emin olun.
katma yazar Bojan Kseneman, kaynak
Evet. Yönü değiştirdiğinizde görünüm varsayılan olarak yeniden çizilir, bu nedenle orada işlediğinizden emin olun.
katma yazar Bojan Kseneman, kaynak
@ SObaDeveloper'a bakın. OnResume() 'dan onCreateView ()' a değiştirdim
katma yazar fapps, kaynak
@ SObaDeveloper'a bakın. OnResume() 'dan onCreateView ()' a değiştirdim
katma yazar fapps, kaynak
İşe yaramadı, sanırım yeniden çizilmekten dolayı.
katma yazar fapps, kaynak
İşe yaramadı, sanırım yeniden çizilmekten dolayı.
katma yazar fapps, kaynak
VAOV! Aradığım ses bu ama nasıl başaracağımı bilmiyordum. Ben deneyeceğim ve size anlatacağım.
katma yazar fapps, kaynak
VAOV! Aradığım ses bu ama nasıl başaracağımı bilmiyordum. Ben deneyeceğim ve size anlatacağım.
katma yazar fapps, kaynak
Sadece logcat benim bir göz attım ve bu kazaya neden olmadı. Ama hala çalışmıyor.
katma yazar fapps, kaynak
Sadece logcat benim bir göz attım ve bu kazaya neden olmadı. Ama hala çalışmıyor.
katma yazar fapps, kaynak

13 cevap

Birden fazla durumunuz varsa veya değeri birden fazla yerde kullanıyorsanız, bu durum elinizden hızla çıkabilir. Aşağıdaki yapıyı oluşturmanızı öneriyorum:

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

res/values ​​/ dimens.xml ile:

<?xml version="1.0" encoding="utf-8"?>

    2

ve res/values-land/dimens.xml varlık:

<?xml version="1.0" encoding="utf-8"?>

    4

Ve kod daha sonra şöyle olur (ve sonsuza kadar kalır):

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

Sütun sayısını belirlemenin yeni yollarını eklemenin ne kadar kolay olduğunu kolayca görebilirsiniz, örneğin -w500dp / -w600dp / -w700dp -land yerine kaynak klasörler.

Diğer (daha alakalı) kaynaklarınızı karıştırmak istememeniz durumunda, bu klasörleri ayrı bir kaynak klasöründe gruplamak da oldukça kolaydır:

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

Birden fazla durumunuz varsa veya değeri birden fazla yerde kullanıyorsanız, bu durum elinizden hızla çıkabilir. Aşağıdaki yapıyı oluşturmanızı öneriyorum:

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

res/values ​​/ dimens.xml ile:

<?xml version="1.0" encoding="utf-8"?>

    2

ve res/values-land/dimens.xml varlık:

<?xml version="1.0" encoding="utf-8"?>

    4

Ve kod daha sonra şöyle olur (ve sonsuza kadar kalır):

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

Sütun sayısını belirlemenin yeni yollarını eklemenin ne kadar kolay olduğunu kolayca görebilirsiniz, örneğin -w500dp / -w600dp / -w700dp -land yerine kaynak klasörler.

Diğer (daha alakalı) kaynaklarınızı karıştırmak istememeniz durumunda, bu klasörleri ayrı bir kaynak klasöründe gruplamak da oldukça kolaydır:

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

Bunu, oryantasyon değişikliği her seferinde çağrılacağından, bunun yerine onCreateView yönteminizde kullanmayı deneyin:

if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
}
else{
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4));
}
58
katma
@ciccioska kaynak klasörler 'in getConfiguration() veya onConfigurationChanged 'da. Ayrıca bu soruya cevabımı gör.
katma yazar TWiStErRob, kaynak
Bu, bu görevi yapmak için doğru davranış mı? Teşekkürler
katma yazar ciccioska, kaynak
Teşekkürler! Bu harika çalıştı!
katma yazar fapps, kaynak
Ben deneyeceğim ve size anlatacağım. Teşekkürler!
katma yazar fapps, kaynak

Bunu, oryantasyon değişikliği her seferinde çağrılacağından, bunun yerine onCreateView yönteminizde kullanmayı deneyin:

if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 2));
}
else{
     mRecycler.setLayoutManager(new GridLayoutManager(mContext, 4));
}
58
katma
@ciccioska kaynak klasörler 'in getConfiguration() veya onConfigurationChanged 'da. Ayrıca bu soruya cevabımı gör.
katma yazar TWiStErRob, kaynak
Bu, bu görevi yapmak için doğru davranış mı? Teşekkürler
katma yazar ciccioska, kaynak
Teşekkürler! Bu harika çalıştı!
katma yazar fapps, kaynak
Ben deneyeceğim ve size anlatacağım. Teşekkürler!
katma yazar fapps, kaynak

Geri Dönüşüm Görünümü, AutofitRecycleView'ı destekler.

Xml dosyanıza android: numColumns = "auto_fit" eklemelisiniz.

You can refer to this AutofitRecycleViewLink

6
katma
Bu muhtemelen en mükemmel çözümdür, ancak tasarımcınız farklı bir şeye karar vermezse. Bazen tasarım bizi zor yoldan uygulamaya koyar.
katma yazar Sniper, kaynak
Mükemmel uygulama! dinamik olarak sütun sayısını değiştirmek için ekranı döndürün ve kaydırma konumunu korur
katma yazar Vladimir Salguero, kaynak

Geri Dönüşüm Görünümü, AutofitRecycleView'ı destekler.

Xml dosyanıza android: numColumns = "auto_fit" eklemelisiniz.

You can refer to this AutofitRecycleViewLink

6
katma
Bu muhtemelen en mükemmel çözümdür, ancak tasarımcınız farklı bir şeye karar vermezse. Bazen tasarım bizi zor yoldan uygulamaya koyar.
katma yazar Sniper, kaynak
Mükemmel uygulama! dinamik olarak sütun sayısını değiştirmek için ekranı döndürün ve kaydırma konumunu korur
katma yazar Vladimir Salguero, kaynak

Hayır belirlemek için daha sağlam bir yol. Sütunların sayısı, ekran genişliğine ve çalışma süresine göre hesaplamak olacaktır. Normalde bunun için aşağıdaki işlevi kullanın.

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 değerini doğru hesaplamak daha dinamik bir yöntemdir. Sütun Bu, yalnızca iki olası değere sınırlandırılmadan değişen ekran boyutları kullanıcıları için daha uyarlayıcı olacaktır.

NB: 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.

5
katma

OnCreate() olayında StaggeredGridLayoutManager kullanabilirsiniz

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

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

mRecyclerView.setLayoutManager(mStaggeredGridLayoutManager);

Sonra kullanıcı ekranı çevirdiğinde olayı yakalar ve sütun sayısını otomatik olarak değiştirir.

@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);           
    }
}
2
katma

OnCreate() olayında StaggeredGridLayoutManager kullanabilirsiniz

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

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

mRecyclerView.setLayoutManager(mStaggeredGridLayoutManager);

Sonra kullanıcı ekranı çevirdiğinde olayı yakalar ve sütun sayısını otomatik olarak değiştirir.

@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);           
    }
}
2
katma

Bunu onCreate yönteminde ele aldım.

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

Benim app için mükemmel çalıştı.

1
katma

Bunu onCreate yönteminde ele aldım.

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

Benim app için mükemmel çalıştı.

1
katma

Bu yöntemi recyclerView onMeasure ürününüzde uygulayabilirsiniz. İlk önce, java sınıfı AutofitRecyclerView oluşturun

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 düzen dosyanızdaki activity_main.xml


Ardından değişkeni, değerler klasörü değerlerinin dosya boyutunda her bir öğenin genişliğine ayarlayın/dimens.xml


  250dp

Farklı ekran çözünürlükleri için olabilir-xxhdpi/dimens.xml


 280dp

OnCreate etkinliğindeki etkinliğinize aşağıdaki kodu yerleştirin

@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));
}
0
katma

Bu yöntemi recyclerView onMeasure ürününüzde uygulayabilirsiniz. İlk önce, java sınıfı AutofitRecyclerView oluşturun

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 düzen dosyanızdaki activity_main.xml


Ardından değişkeni, değerler klasörü değerlerinin dosya boyutunda her bir öğenin genişliğine ayarlayın/dimens.xml


  250dp

Farklı ekran çözünürlükleri için olabilir-xxhdpi/dimens.xml


 280dp

OnCreate etkinliğindeki etkinliğinize aşağıdaki kodu yerleştirin

@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));
}
0
katma