web-dev-qa-db-fra.com

Android RecyclerView: changez la liste des fichiers de mise en page en GRID onOptionItemSelected

Je développe une Android pour les achats en ligne. J'ai créé la vue suivante pour la liste des produits en utilisant RecyclerView, en ce que je souhaite changer de vue en sélectionnant l'option élément de men:

J'ai créé ce qui suit adaptateur nommé ProductAdapter, en ce que j'ai implémenté du code pour changer la disposition dans onCreateViewHolder pour sélectionner le fichier de disposition en fonction de la valeur booléenne.

Code de l'adaptateur ProductAdapter:

    /***
     * ADAPTER for Product to binding rows in List
     */
    private class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductRowHolder> {

        private List<Product> productList;

        private Context mContext;

        public ProductAdapter(Context context, List<Product> feedItemList) {
            this.productList = feedItemList;
            this.mContext = context;
        }

        @Override
        public ProductRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            View v = LayoutInflater.from(viewGroup.getContext()).inflate(isProductViewAsList ? R.layout.product_row_layout_list : R.layout.product_row_layout_grid, null);
            ProductRowHolder mh = new ProductRowHolder(v);
            return mh;
        }

        @Override
        public void onBindViewHolder(ProductRowHolder  productRowHolder, int i) {
            Product prodItem = productList.get(i);

//            Picasso.with(mContext).load(feedItem.getName())
//                    .error(R.drawable.ic_launcher)
//                    .placeholder(R.drawable.ic_launcher)
//                    .into(productRowHolder.thumbnail);


            double price = prodItem.getPrice();
            double discount = prodItem.getDiscount();
            double discountedPrice = price - (price * discount / 100);

            String code = "";
            if(prodItem.getCode() != null)
                code = "[" + prodItem.getCode() + "] ";

            productRowHolder.prodIsNewView.setVisibility(prodItem.getIsNew() == 1 ? View.VISIBLE : View.INVISIBLE);
            productRowHolder.prodNameView.setText(code + prodItem.getName());
            productRowHolder.prodOriginalRateView.setText("Rs." + new BigDecimal(price).setScale(2,RoundingMode.DOWN));
            productRowHolder.prodDiscView.setText("" + new BigDecimal(discount).setScale(2,RoundingMode.DOWN) + "% off");
            productRowHolder.prodDiscRateView.setText("Rs." + new BigDecimal(discountedPrice).setScale(2,RoundingMode.DOWN));

            productRowHolder.prodOriginalRateView.setPaintFlags(productRowHolder.prodOriginalRateView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
        }

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

        public class ProductRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
            //Declaration of Views

            public ProductRowHolder(View view) {
                super(view);

                view.setOnClickListener(this);

                //Find Views
            }

            @Override
            public void onClick(View view) {
               //Onclick of row
            }
        }
    }

Après cela, j'ai fait du code pour changer la disposition de RecyclerView de List en Grid et vice-versa dans onOptionsItemSelected, ici j'appelle mAdapter.notifyDataSetChanged(); donc il appellera à nouveau l'adaptateur et changera la valeur.

onOptionsItemSelected:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        switch (id) {
            case R.id.action_settings:
                return true;
            case Android.R.id.home:
                finish();
                break;
            case R.id.product_show_as_view:
                isProductViewAsList = !isProductViewAsList;
                supportInvalidateOptionsMenu();
                mRecyclerView.setLayoutManager(isProductViewAsList ? new LinearLayoutManager(this) : new GridLayoutManager(this, 2));
                mAdapter.notifyDataSetChanged();
                break;
        }

        return super.onOptionsItemSelected(item);
    }

J'ai eu un petit succès comme:

Image de la disposition Grid:

enter image description here

Image de la disposition List:

enter image description here

MAIS MAINTENANT QUAND JE DÉFILE, puis CHANGER DE VUE s'affiche comme:

Grid mise en page:

enter image description here

List mise en page:

enter image description here

Je ne sais pas pourquoi cela se produit après le défilement. Y a-t-il une autre façon de changer la vue comme ça.

Aujourd'hui, je viens de voir que ce problème est dû à ImageView, sans qu'il fonctionne parfaitement.

Aidez s'il vous plaît, votre aide sera appréciée.

33

J'ai trouvé une solution avec le démarrage de l'activité que j'ai définie LinearLayoutManager comme:

mLayoutManager = new LinearLayoutManager(this);
mProductListRecyclerView.setLayoutManager(mLayoutManager);

après cela onOptionsItemSelected écrit comme:

case R.id.menu_product_change_view:
     isViewWithCatalog = !isViewWithCatalog;
     supportInvalidateOptionsMenu();
     //loading = false;
     mProductListRecyclerView.setLayoutManager(isViewWithCatalog ? new LinearLayoutManager(this) : new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
     mProductListRecyclerView.setAdapter(mAdapter);
     break;

et changer la vue dans onCreateViewHolder comme:

@Override
public ProductRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(isViewWithCatalog ? R.layout.product_row_layout_list : R.layout.product_row_layout_grid, null);
    ProductRowHolder mh = new ProductRowHolder(v);
    return mh;
}

Du début à la fin, vous devez gérer la variable isViewWithCatalog pour afficher la disposition en premier.

34

J'ai résolu ce problème en définissant à nouveau l'adaptateur sur RecyclerView, après avoir changé le gestionnaire de disposition.

listView.setLayoutManager(new LinearLayoutManager(this));
listView.setAdapter(adapter);
8
Alessandro Roaro

Dans ce exemples SDK il y a un exemple complet mais il utilise un fichier de mise en page pour les deux LayoutManagers

Pour conserver la position de défilement lors du changement de disposition, ils ont utilisé cette fonction

public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
    int scrollPosition = 0;

    // If a layout manager has already been set, get current scroll position.
    if (mRecyclerView.getLayoutManager() != null) {
        scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
                .findFirstCompletelyVisibleItemPosition();
    }

    switch (layoutManagerType) {
        case GRID_LAYOUT_MANAGER:
            mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT);
            mCurrentLayoutManagerType = LayoutManagerType.GRID_LAYOUT_MANAGER;
            break;
        case LINEAR_LAYOUT_MANAGER:
            mLayoutManager = new LinearLayoutManager(getActivity());
            mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
            break;
        default:
            mLayoutManager = new LinearLayoutManager(getActivity());
            mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
    }

    mRecyclerView.setLayoutManager(mLayoutManager);
    mRecyclerView.scrollToPosition(scrollPosition);
}
7
Mohammad Yahia

Je pense qu'après le défilement et le retour à la vue grille, le premier élément n'est pas recréé. J'ai résolu ce problème en remplaçant getItemViewType() et en gonflant les fichiers de disposition dans onCreateViewHolder en conséquence.

2
user3377402