Maintain scroll position in an ExpandableViewList

31 Views Asked by At

Please forgive me for my bad English. I'm new to Android and I have a problem maintaining the scroll position in an ExpandableViewList when making a selection. My application displays an ExpandableList with clickable objects, allowing these objects to be added to a basket. When I click on a product to add it to the basket, the ExpandableViewList is refreshed and as a result I lose the scroll position. The scroll goes back to position parent 0 child 0. I can't find a solution to maintain the position.

This my view activity

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flux_stock_listing);
        expandableListFluxStock = findViewById(R.id.expandableListOfFluxStock);
        expandablePanierChargement = findViewById(R.id.expandableListChargement);
        actionWasteLoading = findViewById(R.id.actionWasteLoading);
        getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragment_flux_listing_bottom, barcodeScanner.getFragmentClass(), savedInstanceState)
            .commit();
        checkAuthorizedUser();
        loadDataFromStore();
        initPanierChargement();
        initFluxStockList();
        if (savedInstanceState == null) {
            synchronizeFromSiteSelectionActivity();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        barcodeScanner.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        barcodeScanner.onPause();
    }

  protected void initFluxStockList() {
        expandableListFluxStock.setTag(TO_UPDATE);
        expandableListFluxStock.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            if (TO_UPDATE.equals(expandableListFluxStock.getTag())) {
                fluxStockListAdapter = new ExpandableFluxStockListAdapter(this, storageZones, fluxByStorageZone, storageEntriesAExpedier);
                expandableListFluxStock.setAdapter(fluxStockListAdapter);
                expandableListFluxStock.setTag(UPDATED);
            }
        });
        expandableListFluxStock.setOnChildClickListener((parent, view, storageZonePosition, stockPosition, id) -> {
            StorageEntry storageEntry = requireNonNull(fluxByStorageZone.get(storageZones.get(storageZonePosition)))
                .get(stockPosition);
            startChargement(view, storageEntry);
            return false;
        });
    }

    public void initPanierChargement() {
        panierChargementView = findViewById(R.id.panier_chargement);
        if (storageEntriesAExpedier.isEmpty()) {
            panierChargementView.setVisibility(GONE);
        } else {
            panierChargementView.setVisibility(VISIBLE);
        }
    }

    private void startChargement(View view, StorageEntry storageEntry) {
        if (EN_STOCK.equals(storageEntry.getStatutType())) {
            if (isHorsPanier(storageEntry)) {
                fillFluxStockAjouteLeftView(view);
                ajouterAuPanierChargement(storageEntry);
            } else {
                supprimerDuPanierChargement(view, storageEntry);
            }
        }
    }

    public void ajouterAuPanierChargement(StorageEntry storageEntry) {
        databaseService.savePanierChargementItem(storageEntry);
        storageEntriesAExpedier = databaseService.findPanierChargement();
        mettreAJourPanierChargement();
        if (isPanierGone()) {
            panierChargementView.setVisibility(VISIBLE);
        }
        expandableListFluxStock.setTag(TO_UPDATE);
    }


    private void mettreAJourPanierChargement() {
        wasteNames.clear();
        descriptionsByWasteName.clear();
        panierChargementAdapter = new ExpandablePanierChargementAdapter(this, rendrePanierChargement(storageEntriesAExpedier));
        expandablePanierChargement.setAdapter(panierChargementAdapter);
    }

This is my Adapter

    public ExpandableFluxStockListAdapter(Context context, List<String> listDataHeader,
                                          Map<String, List<StorageEntry>> listChildData,
                                          List<SimpleStorageEntry> storageEntriesAExpedier) {
        this.context = context;
        this.storageZones = listDataHeader;
        this.fluxByStorageZone = listChildData;
        this.storageEntriesAExpedier = storageEntriesAExpedier;
    }

    /**
     * Return the zoneStorage view
     */
    @Override
    public View getGroupView(int storageZonePosition, boolean isExpanded, View convertView, ViewGroup parent) {
        convertView = createOrRecycleStorageZoneView(convertView);

        fillStorageZoneView(storageZonePosition, convertView, (ExpandableListView) parent);

        return convertView;
    }

    private void fillStorageZoneView(int storageZonePosition, View convertView, ExpandableListView parent) {
        TextView storageZoneView = (TextView) convertView.findViewById(R.id.storageZoneItem);
        String storageZoneName = (String) getGroup(storageZonePosition);
        storageZoneView.setText(storageZoneName);

        //On affiche l'accordéon des zoneStorages déplié par défaut
        parent.expandGroup(storageZonePosition);
    }

    /**
     * Return the fluxStock view
     */
    @Override
    public View getChildView(int storageZonePosition, final int fluxStockPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        return getChildView(storageZonePosition, fluxStockPosition, convertView);
    }

    public View getChildView(int storageZonePosition, final int fluxStockPosition, View convertView) {
        convertView = createOrRecycleFluxStockView(convertView);

        final StorageEntry storageEntry = (StorageEntry) getChild(storageZonePosition, fluxStockPosition);

        fillFluxStockIconLeftView(convertView, storageEntry);

        fillFluxStockNameCenterView(convertView, storageEntry);

        fillFluxStockNameRightView(convertView, storageEntry);

        return convertView;
    }

    private void fillFluxStockIconLeftView(View convertView, StorageEntry storageEntry) {
        int iconId;
        int bgColor;
        int textColor;
        List<String> storageEntryAExpedierIds = storageEntriesAExpedier.stream()
            .map(SimpleStorageEntry::getId)
            .collect(toList());

        if (EN_STOCK.equals(storageEntry.getStatutType()) && !storageEntryAExpedierIds.contains(storageEntry.getDemandId())) {
            iconId = R.drawable.ic_action_flux_stock_en_stock;
            bgColor = R.color.demand_enlevement;
            textColor = R.color.text_standard;
        } else {
            iconId = R.drawable.ic_action_flux_stock_charge;
            bgColor = R.color.tennaxia_blue;
            textColor = R.color.text_white;
        }

        ImageView fluxStockIcon = convertView.findViewById(R.id.fluxStockIcon);
        fluxStockIcon.setImageDrawable(context.getResources().getDrawable(iconId));

        LinearLayout leftLayout = convertView.findViewById(R.id.fluxStockLeftIconView);
        leftLayout.setBackgroundColor(context.getResources().getColor(bgColor));

        TextView demandTypeLabelView = (TextView) convertView.findViewById(R.id.fluxStockTypeLabel);
        demandTypeLabelView.setTextColor(getColor(context, textColor));
        if (storageEntryAExpedierIds.contains(storageEntry.getDemandId())) {
            demandTypeLabelView.setText(CHARGE.getLabel());
        } else {
            demandTypeLabelView.setText(storageEntry.getStatutType().getLabel());
        }
    }

    private void fillFluxStockNameCenterView(View convertView, StorageEntry storageEntry) {
        int textColor;
        textColor = R.color.text_standard;

        TextView fluxStockDescription = convertView.findViewById(R.id.fluxStockDescription);
        fluxStockDescription.setText(generateDescription(storageEntry));
        fluxStockDescription.setTextColor(getColor(context, textColor));
    }

    private void fillFluxStockNameRightView(View convertView, StorageEntry storageEntry) {
        TextView demandFluxNumber = convertView.findViewById(R.id.fluxStockFluxNumber);
        demandFluxNumber.setText(generateFluxNumber(storageEntry));
    }

    private Spanned generateDescription(StorageEntry storageEntry) {
        return fromHtml(new FluxStockDescription(context.getResources(), storageEntry).htmlShort(), FROM_HTML_MODE_LEGACY, null, null);
    }

    private Spanned generateFluxNumber(StorageEntry storageEntry) {
        return fromHtml(new FluxStockDescription(context.getResources(), storageEntry).htmlFluxNumber(), FROM_HTML_MODE_LEGACY, null, null);
    }

    @Override
    public Object getChild(int storageZonePosition, int fluxStockPosition) {
        return fluxByStorageZone
            .get(this.storageZones.get(storageZonePosition))
            .get(fluxStockPosition);
    }

    @Override
    public long getChildId(int storageZonePosition, int fluxStockPosition) {
        return fluxStockPosition;
    }

    @Override
    public int getChildrenCount(int storageZonePosition) {
        return fluxByStorageZone.get(storageZones.get(storageZonePosition)).size();
    }

    @Override
    public Object getGroup(int storageZonePosition) {
        return storageZones.get(storageZonePosition);
    }

    @Override
    public int getGroupCount() {
        return storageZones.size();
    }

    @Override
    public long getGroupId(int storageZonePosition) {
        return storageZonePosition;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public boolean isChildSelectable(int storageZonePosition, int fluxStockPosition) {
        return true;
    }

    private View createOrRecycleFluxStockView(View convertView) {
        if (convertView == null) {
            convertView = createView(R.layout.list_flux_stock);
        }
        return convertView;
    }

    private View createOrRecycleStorageZoneView(View convertView) {
        if (convertView == null) {
            convertView = createView(R.layout.list_storage_zone);
        }
        return convertView;
    }

    private View createView(int ressource) {
        LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        return layoutInflater.inflate(ressource, null);
    }

And my xml view

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <ExpandableListView
        android:id="@+id/expandableListOfFluxStock"
        android:layout_weight="1"
        android:layout_height="0dp"
        android:layout_width="match_parent"
        android:cacheColorHint="#00000000"
        android:groupIndicator="@null"/>

    <LinearLayout
        android:id="@+id/panier_chargement"
        android:layout_width="match_parent"
        android:layout_height="300sp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/titre_panier"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/text_white"
            android:background="@color/tennaxia_blue"
            android:text="@string/titre_panier_chargement"
            android:padding="10sp"
            android:textStyle="bold"
            android:textSize="17sp"/>

        <ExpandableListView
            android:id="@+id/expandableListChargement"
            android:layout_weight="1"
            android:layout_height="0dp"
            android:layout_width="match_parent"
            android:cacheColorHint="#00000000"
            android:groupIndicator="@null"
            android:divider="@null"/>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:paddingBottom="5sp"
            android:paddingTop="5sp">

            <Button
                android:id="@+id/actionWasteLoading"
                android:layout_width="150sp"
                android:layout_height="40sp"
                android:text="@string/button_next_step"
                android:textColor="@color/text_white"
                android:background="@color/tennaxia_blue"
                android:onClick="getWasteLoading"/>

        </LinearLayout>

    </LinearLayout>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_flux_listing_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

I found a lot of information on listView but almost none on ExpandableView

expandablelist view scrolling position => used only from listView

I am looking for ExpandableListView Auto Scroll to particular position => used with RecycleView, not possible for me.

0

There are 0 best solutions below