1

I am trying to implement a dynamic list update to FragmentStatePagerAdapter. I have a list of few fragments which have radio buttons, edit text, and different other fragments having just a single view.

Now the logic revolves around radio button fragment, so lets suppose you have a list having 10 elements and the list item showing the radio button is 6, and there are 2 options for the user to select on the radio button fragment. If user selects 1st option then 8th item should be shown and 7th should be skipped and if 2nd option is selected then 7th should be shown and then 9th.

I have added a view pager, and have an associated FragmentStatePagerAdapter associated with it. Now I was able to populate the list based on the option but when I refresh list in the adapter, it does not hops from 6th to 8th and still shows 7th.

Can someone help me around it on how can I implement the hopping mechanism on FragmentStatePagerAdapter?

Adapter

import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.view.ViewGroup;

import java.util.List;

public class OrderDetailsAdapter extends FragmentPagerAdapter {

    private final Logger log = LoggerFactory.getLogger(OrderDetailsAdapter.class);
    private List<IndexedFragments> adapterList;
    private FragmentManager fragmentManager;

    public OrderDetailsAdapter(FragmentManager fragmentManager, List<IndexedFragments> adapterList) {
        super(fragmentManager);
        this.fragmentManager = fragmentManager;
        this.adapterList = adapterList;
    }

    @Override
    public Fragment getItem(int position) {
        final IndexedFragments indexedFragment = adapterList.get(position);
        return indexedFragment.getFragment();
    }

    @Override
    public int getCount() {
        if (adapterList.isEmpty()) {
            return 0;
        } else {
            return adapterList.size();
        }
    }

    @Override
    public int getItemPosition(@NonNull Object object) {
        return POSITION_NONE;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        log.debug("Destroying fragment position {}", position);
    }

    public void updateList(List<IndexedFragments> indexedFragments) {
        adapterList.clear();
        log.debug("Fragment List OrderDetailsAdapter after clearing {} on {}", adapterList.size(), adapterList);
        adapterList.addAll(indexedFragments);
        log.debug("Fragment List OrderDetailsAdapter after adding indexed fragments {} on {}", adapterList.size(), adapterList);
        notifyDataSetChanged();
    }
}

Model Class

import android.support.v4.app.Fragment;

import java.io.Serializable;

public class IndexedFragments implements Serializable {

    private final static long serialVersionUID = -304520750038118996L;
    private Integer index;
    private Fragment fragment;
    private boolean isSkippedRequested = false;

    public Integer getIndex() {
        return index;
    }

    public void setIndex(Integer index) {
        this.index = index;
    }

    public Fragment getFragment() {
        return fragment;
    }

    public void setFragment(Fragment fragment) {
        this.fragment = fragment;
    }

    public boolean isSkippedRequested() {
        return isSkippedRequested;
    }

    public void setSkippedRequested(boolean skippedRequested) {
        isSkippedRequested = skippedRequested;
    }
}

FormsActivity

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import javax.inject.Inject;

import dagger.Binds;
import dagger.Module;
import dagger.Subcomponent;
import dagger.android.ActivityKey;
import dagger.android.AndroidInjection;
import dagger.android.AndroidInjector;
import dagger.multibindings.IntoMap;


public class FormsActivity extends AppCompatActivity implements FragmentNavigationListener {

    private static String CHECK_BOX = "checkbox";
    private static String RADIO_BUTTON = "radio";
    private static String TEXT_INPUT = "text";
    private static String NUMERIC_INPUT = "numeric";
    private static String VIDEO_VIEW = "video";
    private static String IMAGE_VIEW = "image";
    private final Logger log = LoggerFactory.getLogger(FormsActivity.class);
    public LinkedHashMap<String, String> stringLinkedHashMap;
    @Inject
    protected BaseRetrofit restRequests;
    @Inject
    protected AppUtils appUtils;
    private FormData formData;
    private ViewPager viewPager;
    private ProgressBar progressBar;
    private Button submitButton;
    private Toolbar toolbar;
    private List<Frmdtl> formDataList;
    private List<IndexedFragments> fragmentList;

    private Context context;

    private OrderDetailsAdapter orderDetailsAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_forms);
        context = this;
        Intent intent = getIntent();
        if (intent != null) {
            formData = (FormData) intent.getSerializableExtra(AppConstants.FORMS_ACTIVITY);
        }
        restRequests.setContext(this);
        initializeViews();
        populateFragments(formData);
    }

    @Override
    public void onBackPressed() {
        showAlertDialog();
    }

    private void initializeViews() {
        submitButton = findViewById(R.id.submit_button);
        toolbar = findViewById(R.id.toolbar_main_activity);
        setSupportActionBar(toolbar);
        progressBar = findViewById(R.id.progress_bar_layout);
    }

    private void showAlertDialog() {
        Dialog dialog = new AlertDialogFragment().createWarningDialog(context, getString(R.string.warning),
                getString(R.string.saved_form_data_lost),
                R.string.ok,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        appUtils.getFormAnswersList().clear();
                        finish();
                    }
                });
        dialog.setCanceledOnTouchOutside(true);
        dialog.show();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void populateFragments(FormData formData) {
        formDataList = formData.getOrderDetails().getFrmdtl();
        fragmentList = new ArrayList<>();
        for (Frmdtl frmdtl : formDataList) {
            Fragment fragment = null;
            if (frmdtl.getFieldType().equalsIgnoreCase(TEXT_INPUT)) {
                fragment = createTextFieldFragment(frmdtl, null);
            } else if (frmdtl.getFieldType().equalsIgnoreCase(NUMERIC_INPUT)) {
                fragment = createTextFieldFragment(frmdtl, NUMERIC_TYPE);
            } else if (frmdtl.getFieldType().equalsIgnoreCase(CHECK_BOX)) {
                fragment = createCheckBoxFragment(frmdtl);
            } else if (frmdtl.getFieldType().equalsIgnoreCase(RADIO_BUTTON)) {
                fragment = createRadioButtonFragment(frmdtl);
            } else if (frmdtl.getFieldType().equalsIgnoreCase(VIDEO_VIEW)) {
                fragment = createVideoViewFragment(frmdtl);
            } else if (frmdtl.getFieldType().equalsIgnoreCase(IMAGE_VIEW)) {
                fragment = createImageViewFragment(frmdtl);
            }

            if (fragment != null) {
                IndexedFragments indexedFragments = new IndexedFragments();
                indexedFragments.setFragment(fragment);
                indexedFragments.setIndex(frmdtl.getIndex());
                fragmentList.add(indexedFragments);
            }
        }
        viewPager = findViewById(R.id.fragment_view_pager);
        orderDetailsAdapter = new OrderDetailsAdapter(getSupportFragmentManager(), fragmentList);
        viewPager.setAdapter(orderDetailsAdapter);
        viewPager.setOffscreenPageLimit(0);
    }

    private Fragment createTextFieldFragment(Frmdtl formData, String inputType) {
        FormEditTextFragment formEditTextFragment = new FormEditTextFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable(FORM_DATA, formData);
        bundle.putString(INPUT_TYPE, inputType);
        formEditTextFragment.setArguments(bundle);
        log.debug("Form Data Id for text {}", formData.getId());
        return formEditTextFragment;
    }

    private Fragment createCheckBoxFragment(Frmdtl formData) {
        FormCheckBoxFragment formCheckBoxFragment = new FormCheckBoxFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable(FORM_DATA, formData);
        formCheckBoxFragment.setArguments(bundle);
        log.debug("Form Data Id for check {}", formData.getId());
        return formCheckBoxFragment;
    }

    private Fragment createRadioButtonFragment(Frmdtl frmdtl) {
        FormRadioButtonFragment formRadioButtonFragment = new FormRadioButtonFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable(FORM_DATA, frmdtl);
        bundle.putSerializable(ORDER_DETAILS, formData.getOrderDetails());
        formRadioButtonFragment.setArguments(bundle);
        log.debug("Form Data Id for radio {}", frmdtl.getId());
        return formRadioButtonFragment;
    }

    private Fragment createVideoViewFragment(Frmdtl formData) {
        FormVideoFragment formVideoFragment = new FormVideoFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable(FORM_DATA, formData);
        formVideoFragment.setArguments(bundle);
        log.debug("Form Data Id for video {}", formData.getId());
        return formVideoFragment;
    }

    private Fragment createImageViewFragment(Frmdtl formData) {
        FormImageFragment formImageFragment = new FormImageFragment();
        Bundle bundle = new Bundle();
        bundle.putSerializable(FORM_DATA, formData);
        formImageFragment.setArguments(bundle);
        log.debug("Form Data Id for image {}", formData.getId());
        return formImageFragment;
    }

    private void navigateBetweenFragments(int navigation, List<String> stringList, Integer currentIndex) {
        if (navigation == NEXT_NAVIGATION) {

            if (stringList != null && !stringList.isEmpty() && currentIndex != null) {
                processLogicBasedFragments(stringList, currentIndex);
                viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
                return;
            }

            if (viewPager.getCurrentItem() == fragmentList.size() - 1) {
                log.debug("FormData list size {}", formDataList.size());
                log.debug("Moving to {} form", viewPager.getCurrentItem() + 1);
                submitButton.setVisibility(View.VISIBLE);
                submitButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        progressBar.setVisibility(View.VISIBLE);
                        attemptFormUpload();
                    }
                });
            } else {
                viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
            }
        }
        if (navigation == PREVIOUS_NAVIGATION) {
            viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
        }
    }

    private void processLogicBasedFragments(List<String> stringList, Integer currentIndex) {

        List<IndexedFragments> indexedFragmentsList = new ArrayList<>();

        for (int i = 0; i < fragmentList.size(); i++) {
            Integer index = fragmentList.get(i).getIndex();
            if (index.compareTo(currentIndex) <= 0) {
                indexedFragmentsList.add(fragmentList.get(i));
            }
        }

        for (int i = 0; i < fragmentList.size(); i++) {
            IndexedFragments indexedFragments = fragmentList.get(i);
            if (stringList.contains(String.valueOf(indexedFragments.getIndex()))) {
                indexedFragmentsList.add(indexedFragments);
            } else if (!stringList.contains(String.valueOf(indexedFragments.getIndex()))
                    && fragmentList.get(i).getIndex().compareTo(currentIndex) > 0) {
                indexedFragments.setSkippedRequested(true);
                indexedFragmentsList.add(indexedFragments);
            }
        }

        fragmentList.clear();
        log.debug("Fragment List Forms Activity after clearing {} on {}", fragmentList.size(), fragmentList);
        fragmentList.addAll(indexedFragmentsList);
        log.debug("Fragment List Forms Activity after adding indexed fragments {} on {}", fragmentList.size(), fragmentList);

        orderDetailsAdapter.updateList(indexedFragmentsList);
    }

    private void attemptFormUpload() {
        try {
            if (appUtils.isNetworkConnected(context)) {
                uploadForm();
            } else {
                preserveFormDataForFutureUpload();
                Toast.makeText(context, R.string.no_connection, Toast.LENGTH_LONG).show();
                progressBar.setVisibility(GONE);
                finish();
            }
        } catch (IOException e) {
            log.error("Error in attempting to upload form {}", e.fillInStackTrace());
        }
    }

    private void uploadForm() throws UnsupportedEncodingException {
        restRequests.uploadForm(formData.getOrderDetails().getId(),
                String.valueOf(formData.getOrderDetails().getFormId()),
                formData.getOrderDetails().getLatitude(),
                formData.getOrderDetails().getLongitude(),
                appUtils.getFormAnswersList(), new RestRequestListener() {
                    @Override
                    public void onSuccessResponse(String response) {
                        appUtils.getFormAnswersList().clear();
                        progressBar.setVisibility(GONE);
                        finish();
                    }

                    @Override
                    public void onErrorResponse(Throwable t) {
                        appUtils.getFormAnswersList().clear();
                        progressBar.setVisibility(GONE);
                        finish();
                    }
                });
    }

    private void preserveFormDataForFutureUpload() throws IOException {
        OfflineSubmittedOrder offlineSubmittedOrder = new OfflineSubmittedOrder();
        List<FormAnswers> formAnswers = new ArrayList<>(appUtils.getFormAnswersList());
        offlineSubmittedOrder.setFormAnswersList(formAnswers);
        offlineSubmittedOrder.setOrderDetail(formData.getOrderDetails());
        appUtils.getFormAnswersList().clear();
        appUtils.getOfflineSubmittedOrders().add(offlineSubmittedOrder);
        appUtils.writeObject(getApplicationContext(), FORM_ANSWER_LIST_CACHE, appUtils.getOfflineSubmittedOrders());
        appUtils.setSubmissionPending(true);
    }

    @Override
    public void onFragmentNavigationTriggered(int navigation, List<String> stringList, Integer currentIndex) {
        navigateBetweenFragments(navigation, stringList, currentIndex);
    }

    @Subcomponent
    public interface FormsActivitySubcomponent extends AndroidInjector<FormsActivity> {

        @SuppressWarnings({"InnerClassTooDeeplyNested", "ClassNameSameAsAncestorName"})
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<FormsActivity> {
        }
    }

    @SuppressWarnings("InterfaceNeverImplemented")
    @Module(subcomponents = FormsActivity.FormsActivitySubcomponent.class)
    public interface FormsActivityModule {

        @Binds
        @IntoMap
        @ActivityKey(FormsActivity.class)
        AndroidInjector.Factory<? extends Activity>
        bindFormsActivityInjectorFactory(FormsActivity.FormsActivitySubcomponent.Builder builder);
    }
}
Shiv Anand
  • 81
  • 1
  • 2
  • 10

0 Answers0