web-dev-qa-db-fra.com

Comment définir différentes colonnes pour les lignes dans Android gridview

Je veux avoir une vue de grille similaire à celle-ci

enter image description here

Chaque ligne impaire aura deux images de grande taille et les lignes paires auront quatre images plus petites. Comment puis-je y parvenir?

34
mungaih pk

J'ai quelque chose de similaire et j'ai résolu avec le nouveau RecyclerView.

J'ai créé un fragment avec un RecyclerView . RecyclerView sur xml:

<Android.support.v7.widget.RecyclerView xmlns:Android="http://schemas.Android.com/apk/res/Android" xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/filter_subtypes" Android:layout_width="match_parent" Android:layout_height="match_parent" />

Sur votre fragment/activité (OnViewCreated dans mon cas de fragment). Je trouve RecyclerView et définit un adaptateur - une classe d'adaptateur normale hérite de RecyclerView.Adapter <VOTRE classe VIEW HOLDER> - Et puis je crée un GridLayoutManager

final GridLayoutManager mng_layout = new GridLayoutManager(this.getActivity(), TOTAL_CELLS_PER_ROW/*In your case 4*/);


Ensuite, je remplace cette méthode pour définir un nombre dynamique de colonnes (cellules)

mng_layout.setSpanSizeLookup( new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                switch( adapterSubtype.getItemViewType(position) ) {
                    case FilterSubtypesAdapter.TYPE_LOW:
                        return TOTAL_CELLS_PER_ROW;
                    case FilterSubtypesAdapter.TYPE_HIGH:
                        return 2;
                    default:
                        return -1;
                }
            }
        });
myRecyclerView.setLayoutManager(mng_layout);

Avec cela, vous obtiendrez un nombre dynamique de cellules sur vos lignes.

EXTRA: Si vous utilisez la même vue vue/type sur votre adaptateur, vous obtiendrez la même vue w & h. Vous devrez créer 2 vues xml pour TYPE_HIGH et une autre vue pour TYPE_LOW.

Ainsi, dans votre adaptateur, vous devez disposer de 2 types de données (1 pour les images hautes et 1 pour les images basses). Vous devez remplacer ces méthodes

@Override
public SubtypeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = null;
    if (viewType==TYPE_HIGH) {
        view = inflater.inflate(R.layout.item_image_high, parent, false);
    } else {
        view = inflater.inflate(R.layout.item_image_low, parent, false);
    }
    return new SubtypeViewHolder(view, viewType);
}

 @Override
 public int getItemViewType(int position) {
     return (list.get(position).getType()==Subtype_type.HIGH) ? TYPE_HIGH : TYPE_LOW;
 }

J'espère que j'ai été clair, tout problème me le dit.

33
Sulfkain

Au lieu de considérer une seule image, je prends un groupe de trois images comme un seul élément de grille,

enter image description here

essayez ceci à l'intérieur de votre adaptateur de réseau

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/linear"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@color/green"
    Android:orientation="vertical">
<ImageView
    Android:id="@+id/image"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:scaleType="fitXY"
    Android:src="@drawable/user"
     />
    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="horizontal">
        <ImageView
            Android:id="@+id/image_1"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_weight="1"
            Android:scaleType="fitXY"
            Android:src="@drawable/user"

            />
        <ImageView
            Android:id="@+id/image_2"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:src="@drawable/user"
            Android:scaleType="fitXY"
            Android:layout_weight="1"
            />

        </LinearLayout>

    </LinearLayout>

et votre vue de grille serait comme

<GridView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/RelativeLayout1"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:numColumns="2"
    >

</GridView>

La seule chose dont vous devez vous occuper est la séquence de votre image. cela pourrait vous aider

22
Abhishek

Si vous utilisez RecyclerView pour GridView, alors il existe une solution qui devrait fonctionner pour vous:

GridLayoutManager layoutManager = new GridLayoutManager(this, 4);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
         int mod = position % 6;    

         if(position == 0 || position == 1)
              return 2;
         else if(position < 6)
              return 1;
         else if(mod == 0 || mod == 1)
              return 2;
         else
              return 1;
    }
});

recyclerView.setLayoutManager(layoutManager);

J'espère que ce travail pour vous!

10
Xcihnegn

Il y a comment ça marche dans mon projet j'ai différentes hauteurs de cellules et aussi en-tête

enter image description here

adaptateur:

public class AdapterRecViewMain
    extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private List<BaseMarkerElement> mainCardList;
private final int HEADER_VIEW = 0;
private final int FOOTER_VIEW = 1;

public AdapterRecViewMain() {
}

public void setData(List<BaseMarkerElement> mainCardList) {
    this.mainCardList = mainCardList;
}

@Override public int getItemViewType(int position) {
    if (position == 0) {
        return HEADER_VIEW;
    }
    return FOOTER_VIEW;
}

@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
    if (type == FOOTER_VIEW) {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.card_main_activity, viewGroup, false);
        return new MainCardViewHolder(v);
    } else {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.header_view_main_activity, viewGroup, false);
        return new HeaderViewHolder(v);
    }
}

@Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int positionItem) {
    final int position = viewHolder.getAdapterPosition();

    if (viewHolder instanceof HeaderViewHolder) {
        StaggeredGridLayoutManager.LayoutParams layoutParams =
                (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
        layoutParams.setFullSpan(true);

        BaseMarkerElement item = mainCardList.get(position);
        if (item instanceof HeaderView) {
            HeaderView header = (HeaderView) mainCardList.get(position);
            // need to add implementation
        }
    } else if (viewHolder instanceof MainCardViewHolder) {
        MainCardViewHolder currentView = (MainCardViewHolder) viewHolder;
        CardMainActivity currentCard = (CardMainActivity) mainCardList.get(position);

        currentView.ivMainCard.setImageResource(currentCard.getIvMainCard());
        currentView.tvBrandName.setText(currentCard.getTvBrandName());
        currentView.tvPrice.setText(currentCard.getTvPrice());
        currentView.tvType.setText(currentCard.getTvType());
    }
}

@Override public int getItemCount() {
    return mainCardList.size();
}

private class MainCardViewHolder extends RecyclerView.ViewHolder {
    ImageView ivMainCard;
    TextView tvBrandName;
    TextView tvType;
    TextView tvPrice;

    MainCardViewHolder(View view) {
        super(view);
        ivMainCard = (ImageView) view.findViewById(R.id.imageViewMainCard);
        tvBrandName = (TextView) view.findViewById(R.id.tvBrandName);
        tvType = (TextView) view.findViewById(R.id.tvType);
        tvPrice = (TextView) view.findViewById(R.id.tvPrice);
    }
}

private class HeaderViewHolder extends RecyclerView.ViewHolder {

    public HeaderViewHolder(View itemView) {
        super(itemView);

    }
}
}

Dans votre activité:

private AdapterRecViewMain adapter;
private RecyclerView rvMain;

@Override protected void onResume() {
    super.onResume();
    Logger.logGeneral("onResume()");

    if (adapter == null) {
        setUpRecView();
    }
}

private void setUpRecView() {
    adapter = new AdapterRecViewMain();
    adapter.setData(controller.loadData());
    rvMain = (RecyclerView) findViewById(R.id.rvMain);
    final StaggeredGridLayoutManager layoutManager =
            new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
    rvMain.setLayoutManager(layoutManager);

    rvMain.addOnScrollListener(scrollListener);
    rvMain.setAdapter(adapter);
    adapter.notifyDataSetChanged();
    rvMain.invalidate();
}
1
Aleksey Timoshchenko

Je suppose que la meilleure façon de faire est d'utiliser la vue du recycleur. De plus, il est préférable à la liste/grille pour les performances

Les liens ci-dessous peuvent être très utiles - Tous sont liés à la vue bidirectionnelle par Lucas

https://github.com/lucasr/twoway-view

https://plus.google.com/+LucasRocha/posts/WBaryNqAHiy

http://lucasr.org/2014/07/31/the-new-twowayview/

1
Chimu

Avez-vous essayé un RecyclerView en combinaison avec un StaggeredGridLayoutManager ?

Cette combinaison se traduit par quelque chose comme ceci: vidéo .

Je pense que c'est ce que vous recherchez.

0
ivtoto

Créez deux fichiers XML différents et gonflez en fonction de la position dans votre adaptateur comme ci-dessous.

if(position%2==0){
//Inflate Even number layout with 4 images
}else{
//Inflate ODD number layout with 2 images
}
0

Essaye ça ,

https://github.com/etsy/AndroidStaggeredGrid

Vue en grille décalée,

Extrêmement simple, facile à utiliser.

0
TheAnimatrix