web-dev-qa-db-fra.com

Augmenter la largeur de cellule dans un RecyclerView avec GridLayoutManager

J'ai un RecyclerView avec un GridLayoutManager avec spanCount=2 et une orientation Vertical.

Mes articles sont correctement affichés comme l'image ci-dessous:

Maintenant, je dois ajouter une animation qui dit qu’un clic sur l’un des éléments, par exemple le numéro "3", augmente sa largeur et que l’élément à côté (dans cet exemple, le nombre "4") se trouve en dehors du parent. /écran.

Visuellement, ce serait quelque chose comme ça:

Pour développer l'élément, je règle la visibilité sur VISIBLE en vue à l'intérieur de l'élément et pour le réduire, définissez la visibilité sur GONE.

Pour le moment, je peux afficher et masquer cette vue, mais cela ne prend que l'espace de l'élément, cela augmente la largeur en poussant l'élément à côté.

Donc mes questions sont: 

  • Est-ce possible d'utiliser le GridLayoutManager par défaut pour cela?
  • Quelle serait une bonne approche pour y parvenir?
6
amp

Il est possible d'utiliser GridLayoutManager comme suit:

  • Définissez la GridLayoutManager avec deux étendues.
  • Configurez une présentation d’élément intégrant la vue cliquable et la vue qui sera définie sur VISIBLE et GONE.
  • Dans l'adaptateur, lorsque vous cliquez sur la vue de gauche, définissez la vue extensible sur VISIBLE, augmentez la taille de la itemView de la largeur de la vue extensible. Traduisez la vue vers la droite en fonction de l’extension pour tenir compte de l’augmentation de la taille de la vue de gauche.
  • Faites un peu de ménage pour vous assurer que les vues recyclées sont réinitialisées.

Voici un exemple. Je suppose que seule la vue de gauche peut être cliquée. Le processus général est le même pour la vue de droite si vous pouvez également cliquer dessus, mais les détails diffèrent quant à ce qui doit être traduit, etc.

Cet exemple ne conserve pas les informations relatives au statut de la vue impliqué dans une extension. Par conséquent, si vous développez une vue, faites-la défiler vers le bas et la sauvegarder, la vue risque d'être réinitialisée.

 enter image description here

MainActivity.Java 

public class MainActivity extends AppCompatActivity {  
    private LinearLayoutManager mLayoutManager;  
    private RecyclerViewAdapter mAdapter;  
    private List<String> mItems = new ArrayList<>();  
    private RecyclerView mRecycler;  

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

        for (int i = 0; i < 100; i++) {  
            mItems.add(i + 1 + "");  
        }  

        mLayoutManager = new GridLayoutManager(this, 2);  
        mRecycler = findViewById(R.id.recyclerView);  
        mAdapter = new RecyclerViewAdapter(mItems);  
        mRecycler.setLayoutManager(mLayoutManager);  
        mRecycler.setAdapter(mAdapter);  
    }  
}

RecyclerViewAdapter.Java
Cet adaptateur de démonstration suppose qu’il existe un nombre pair d’éléments à afficher. Pour simplifier, les contrôles nuls n'ont pas été codés.

class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
    implements View.OnClickListener {
    private final List<String> mItems;
    private RecyclerView mRecyclerView;

    RecyclerViewAdapter(List<String> items) {
        mItems = items;
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
    }

    @Override
    public @NonNull
    RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
        return new ItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        ItemViewHolder vh = (ItemViewHolder) holder;

        vh.mItemTextView.setText(mItems.get(position));

        // Only allow clicks on left items which corresponds to even positions.
        vh.mItemTextView.setOnClickListener((position % 2 == 0) ? this : null);

        // Reset translation and expansion if viewholder is reused.
        vh.itemView.setTranslationX(0);
        if (vh.mExpansion != 0) {
            vh.itemView.getLayoutParams().width -= vh.mExpansion;
            vh.mExpansion = 0;
            vh.mGoneView.setVisibility(View.GONE);
        }

        int bgColor = (position % 2 == 0)
            ? Android.R.color.holo_blue_light
            : Android.R.color.holo_green_light;
        vh.mItemTextView.setBackgroundColor(vh.itemView.getContext().getResources().getColor(bgColor));
    }

    @Override
    public int getItemCount() {
        return (mItems == null) ? 0 : mItems.size();
    }

    @Override
    public int getItemViewType(int position) {
        return TYPE_ITEM;
    }

    @Override
    public void onClick(View v) {
        ItemViewHolder vh = (ItemViewHolder) mRecyclerView.findContainingViewHolder(v);
        View itemView = vh.itemView;

        // Get the child to the right. This child will be translated to the right to make room
        // for the expanded left view.
        View rightChild = mRecyclerView.getChildAt(findRightChildPos(vh.itemView));
        if (vh.mGoneView.getVisibility() == View.GONE) {
            // Reveal the "GONE" view, expand the itemView and translate the right-hand view.
            vh.mGoneView.setVisibility(View.VISIBLE);
            int translation = vh.mGoneView.getLayoutParams().width;
            itemView.getLayoutParams().width = itemView.getWidth() + translation;

            // Works with "GONE" view of fixed width. Make adjustments if width is variable.
            rightChild.setTranslationX(translation);
            vh.mExpansion = translation;
        } else { // View is expanded.
            // Undo the expansion changes.
            vh.mGoneView.setVisibility(View.GONE);
            itemView.getLayoutParams().width = itemView.getWidth() - vh.mExpansion;
            vh.mExpansion = 0;
            rightChild.setTranslationX(0);
        }
    }

    // Find the child to the right of a view within the RecyclerView.
    private int findRightChildPos(View view) {
        for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
            if (mRecyclerView.getChildAt(i) == view) {
                return i + 1;
            }
        }
        return RecyclerView.NO_POSITION;
    }

    static class ItemViewHolder extends RecyclerView.ViewHolder {
        final TextView mItemTextView;
        final View mGoneView;
        int mExpansion;

        ItemViewHolder(View item) {
            super(item);
            mItemTextView = item.findViewById(R.id.textView);
            mGoneView = item.findViewById(R.id.expandingView);
        }
    }

    private final static int TYPE_ITEM = 1;
}

recycler_item.xml

<LinearLayout 
    Android:id="@+id/item"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_margin="8dp"
    Android:clickable="true"
    Android:orientation="horizontal">

    <TextView
        Android:id="@+id/textView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_weight="1"
        Android:gravity="center"
        Android:textSize="48sp"
        tools:background="@Android:color/holo_blue_light"
        tools:text="1" />

    <View
        Android:id="@+id/expandingView"
        Android:layout_width="100dp"
        Android:layout_height="match_parent"
        Android:background="@Android:color/holo_purple"
        Android:visibility="gone" />

    <View
        Android:layout_width="10dp"
        Android:layout_height="match_parent"
        Android:background="@Android:color/holo_red_light" />
</LinearLayout>
4
Cheticamp

Je vois comment implémenter cela en utilisant HorizontalScrollView/RecyclerView avec LinearLayoutManager. Au lieu d'utiliser GridLayoutManager avec deux colonnes, vous pouvez utiliser LinearLayoutManager avec ces vues:

__|HorizontalScrollView/RecyclerView| | [Firts view] [Second view] | |---------------------------------|

Ensuite, il est facile d'implémenter des vues étendues.

Dans d'autres cas, vous aurez besoin d'un gestionnaire de disposition personnalisé, qui peut faire défiler horizontalement et verticalement.

0
Konstantin Berkow