Je veux afficher 6 images sous forme de grille comme suit.
en orientation portrait, 2 colonnes, 3 rangées et en orientation paysage 3 colonnes, 2 rangées
En utilisant Android GridView et en définissant différentes dispositions de grille dans les répertoires layout-port et layout-land, j'ai pu obtenir cet effet.
Plus tard, conformément à mes exigences en matière d’activité, j’ai ajouté un paramètre dans le fichier manifest.xml, à savoir:
Android:configChanges = "mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale|screenSize"`
arrêter mon activité pour recréer une fois l'orientation de l'écran modifiée.
Après avoir ajouté ce paramètre, ma vue de grille ne se comporte pas comme prévu. Il affiche parfois 1 colonne, parfois 2 colonnes et parfois 3 colonnes.
Je place des méthodes gridView.setNumberOfColumns(2)
ou gridView.setNumberOfColumns(3)
dans la méthode d'affichage de mon adaptateur de grille, en fonction de l'orientation du périphérique.
Aidez-moi à obtenir cet effet sans supprimer le paramètre Android:configChanges
dans Manifest.xml.
Utilisez le puissant système de ressources.
Dans la présentation XML, définissez le nombre de colonnes sur une ressource entière, puis dans /values/integers.xml
, définissez-le sur 2 pour portrait et sur /values-land/integers.xml
, définissez-le sur 3 pour paysage.
// bon, si vous faites configChanges dans le manifeste, vous devrez changer le nombre de colonnes de Java dans onConfogurationChanged
@Override
public void onConfigurationChanged(Configuration newConfig) {
grid.setNumColumns(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ? 3 : 2);
super.onConfigurationChanged(newConfig);
}
vous pouvez définir le nombre de colonnes par programmation en utilisant
float scalefactor = getResources().getDisplayMetrics().density * 100;
int number = getWindowManager().getDefaultDisplay().getWidth();
int columns = (int) ((float) number / (float) scalefactor);
gridView.setNumColumns(columns);
Ma solution:
values / dimens.xml:
<resources>
<dimen name="grip_view_entry_size">160dp</dimen>
<dimen name="grip_view_spacing">10dp</dimen>
</resources>
layout/gridview.xml
<GridView Android:id="@+id/Android:list"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:numColumns="auto_fit"
Android:verticalSpacing="@dimen/grip_view_spacing"
Android:horizontalSpacing="@dimen/grip_view_spacing"
Android:stretchMode="columnWidth"
Android:gravity="center"
Android:scrollingCache="false"
Android:fastScrollEnabled="true"
Android:animationCache="false"/>
dans votre fragment:
private void refreshGridView() {
int gridViewEntrySize = getResources().getDimensionPixelSize(R.dimen.grip_view_entry_size);
int gridViewSpacing = getResources().getDimensionPixelSize(R.dimen.grip_view_spacing);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int numColumns = (display.getWidth() - gridViewSpacing) / (gridViewEntrySize + gridViewSpacing);
gridView.setNumColumns(numColumns);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
refreshGridView();
}
@Override
public void onResume() {
super.onResume();
refreshGridView();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
setContentView(R.layout.lay_vertical);
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.lay_horizontal);
}
};
Chargez ensuite à nouveau les données dans gridview en fonction de vos besoins.
Mettez Android: configChanges = "orientation" pour ce nœud d'activité dans le manifeste.
Lorsque vous utilisez Android: configChanges = "orientation" dans Manifest, votre activité ne recrée pas sur l'orientation modifiée (Paysage en Portrait ou inversement). Si vous ne souhaitez pas supprimer cette balise du manifeste, vous devez obligatoirement remplacer onConfigchanged et y insérer de la logique de code.
je l'ai fait en fonction de la taille de l'écran, pas en dpi
public static int getGridColumnsCount(Context context){
boolean landscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float hi=displayMetrics.heightPixels/displayMetrics.xdpi;
float wi=displayMetrics.widthPixels/displayMetrics.ydpi;
float screenWidthInch = landscape ? Math.max(wi, hi) : Math.min(wi, hi);
float screenWidthCm = screenWidthInch * 2.54f;
int columns = (int)(screenWidthCm/2);
return columns < 3 ? 3 : columns;
}
Voici le XML:
<GridLayout
Android:id="@+id/gridLayout"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:columnCount="@integer/num_columns"
Android:rowCount="@integer/num_rows"
Android:orientation="vertical">
<!-- TextViews, ImageViews, etc -->
</GridLayout>
Et ensuite dans votre fragment:
@BindView(R.id.gridLayout) GridLayout gridLayout;
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
final ArrayList<View> views = new ArrayList<>();
for (int i = 0; i < gridLayout.getChildCount(); i++) {
views.add(gridLayout.getChildAt(i));
}
gridLayout.removeAllViews();
gridLayout.setColumnCount(getContext().getResources().getInteger(R.integer.num_columns));
gridLayout.setRowCount(getContext().getResources().getInteger(R.integer.num_rows));
for (int i = 0; i < views.size(); i++) {
views.get(i).setLayoutParams(new GridLayout.LayoutParams());
gridLayout.addView(views.get(i));
}
}