0

This is an easy question perhaps but I have been researching since yesterday and can not found the solution so I decided to put it here.

My app uses nav drawer and one of the menu is statistics,, let's jump to the code

  public class StatisticsFragment extends Fragment implements
        OnItemSelectedListener {

    protected static final String tag = "Statistic Fragment";
    private NDIcsSpinner spinDate;
    private FragmentActivity context;
    private SimpleDateFormat defaultDateFormat;
    protected String startDate, endDate;
    private CheckBox cbCompare;
//  private boolean isConfigChanged = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(null);
        // setRetainInstance(true);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);

        Clog.d(tag, "[onSaveInstanceState]");
        outState.putString("startDate", startDate);
        outState.putString("endDate", endDate);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        Clog.d(tag, "[onCreateView]");
        View v = inflater
                .inflate(R.layout.statistic_fragment, container, false);
        if (savedInstanceState != null) {
            Clog.d(tag, "[onCreateView] savedInstanceState is not null and configuration has changed");
            startDate = savedInstanceState.getString("startDate");
            endDate = savedInstanceState.getString("endDate");
//          isConfigChanged = true;
        } 

        spinDate = (NDIcsSpinner) v.findViewById(R.id.sta_date);
        cbCompare = (CheckBox) v.findViewById(R.id.sta_check_compare);

        // define default date format
        defaultDateFormat = new SimpleDateFormat("MMMM d, yyyy");

        context = getActivity();
        ArrayAdapter<String> dateAdapter = new ArrayAdapter<String>(context,
                com.actionbarsherlock.R.layout.sherlock_spinner_item,
                getResources().getStringArray(R.array.date_array));
        dateAdapter
                .setDropDownViewResource(com.actionbarsherlock.R.layout.sherlock_spinner_dropdown_item);
        spinDate.setAdapter(dateAdapter);
        spinDate.setOnItemSelectedListener(this);

        // compare to previous period checkbox

        cbCompare.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) {
                Clog.d(tag, "[cbcompare] onCheckedChanged");
                updateFragments();

            }
        });

        if (getChildFragmentManager().findFragmentById(R.id.staper_frame) == null) {
            Clog.d(tag, "[onCreateView] fragment is null");
            Fragment fragment = new StaperFragment();

            fragment.setArguments(getAllArguments());
            FragmentTransaction transaction = getChildFragmentManager()
                    .beginTransaction();

            Fragment f2 = new StadiffFragment();
            f2.setArguments(getAllArguments());
            transaction.add(R.id.staper_frame, fragment);
            transaction.add(R.id.stadiff_frame, f2);
            transaction.commit();
        }

        return v;

    }

    private Bundle getAllArguments() {
        Bundle args = new Bundle();
        args.putString("startDate", startDate);
        args.putString("endDate", endDate);
        args.putBoolean("isCompare", cbCompare.isChecked());
        return args;
    }

    protected void showDialogStartEndDate() {
        Clog.d(tag, "[showDialogStartnEndDate]");
        // show first dialog
        Toast.makeText(getActivity(), "Start", Toast.LENGTH_SHORT).show();
        CalendarDatePickerDialog cd = new CalendarDatePickerDialog();
        cd.setTargetFragment(StatisticsFragment.this, 100);

        cd.setOnCancelListener(new OnDateCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                Clog.d(tag, "[setOnCancelListener] onCancel");
                updateFirstField();

            }
        });
        cd.setOnDateSetListener(new OnDateSetListener() {

            // Using start to create a temporary startDate to consequence on
            // back pressed in second picker

            private String start;

            @Override
            public void onDateSet(CalendarDatePickerDialog dialog, int year,
                    int monthOfYear, int dayOfMonth) {

                Calendar calendar = Calendar.getInstance();
                calendar.set(year, monthOfYear, dayOfMonth);
                start = defaultDateFormat.format(calendar.getTime());

                Toast.makeText(getActivity(), "End", Toast.LENGTH_SHORT).show();
                CalendarDatePickerDialog cd2 = CalendarDatePickerDialog
                        .newInstance(null, year, monthOfYear, dayOfMonth);

                cd2.setTargetFragment(StatisticsFragment.this, 100);

                cd2.setOnCancelListener(new OnDateCancelListener() {

                    @Override
                    public void onCancel(DialogInterface dialog) {
                        // Clog.d(tag, "[setOnCancelListener] onCancel");
                        updateFirstField();
                    }
                });
                cd2.setOnDateSetListener(new OnDateSetListener() {

                    @Override
                    public void onDateSet(CalendarDatePickerDialog dialog,
                            int year, int monthOfYear, int dayOfMonth) {
                        Calendar calendar2 = Calendar.getInstance();
                        calendar2.set(year, monthOfYear, dayOfMonth);

                        endDate = defaultDateFormat.format(calendar2.getTime());
                        startDate = start;

                        updateFirstField();
                    }

                });
                cd2.show(getFragmentManager(), "endDate");

            }

        });

        cd.show(getFragmentManager(), "startDate");

    }

    /**
     * This is for updating the textview in spinner with the latest start and
     * end date
     */

    private void updateFirstField() {
        String finalString = startDate + " - " + endDate;
        TextView getText = (TextView) spinDate.getChildAt(0);
        getText.setText(finalString);
        Clog.d(tag,
                "[updateFirstField] spinDate position : "
                        + spinDate.getSelectedItemPosition());
        // cbCompare.setChecked(false);
        updateFragments();
    }

    /**
     * Update start and end date with respective days
     * 
     * @param i
     * @return
     */

    private void updateTextDate(int i) {

        Calendar cal = Calendar.getInstance();
        endDate = defaultDateFormat.format(cal.getTime());

        cal.add(Calendar.DAY_OF_MONTH, -i);

        // get date string
        startDate = defaultDateFormat.format(cal.getTime());

        // update

        updateFirstField();

    }

    private void updateFragments() {
        Clog.d(tag, "[updateFragments]");
        Fragment staperFragment = new StaperFragment();
        staperFragment.setArguments(getAllArguments());
        Fragment f2 = new StadiffFragment();
        f2.setArguments(getAllArguments());

        FragmentTransaction trans = getChildFragmentManager()
                .beginTransaction();
        trans.replace(R.id.stadiff_frame, f2);
        trans.replace(R.id.staper_frame, staperFragment);
        trans.commit();

    }

    @Override
    public void onItemSelected(IcsAdapterView<?> parent, View view,
            int position, long id) {
//      if (!isConfigChanged) {
            Clog.d(tag, "[onCreateView] spinDate onItemSelected ");
            switch (position) {
            case 0:
                updateTextDate(6);
                break;
            case 1:
                updateTextDate(29);
                break;
            case 2:
                updateTextDate(119);
                break;
            case 3:
                showDialogStartEndDate();
                break;
            default:
                break;
            }
//      } else {
//          isConfigChanged = false;
//          updateFirstField();
//      }

    }

    @Override
    public void onNothingSelected(IcsAdapterView<?> parent) {
        // TODO Auto-generated method stub

    }

So, in the layout I have spinner, 1 checkbox and 2 frame layouts, the problem is when the orientation changed, the spinner got selected twice.

First Time    
01-03 08:40:18.061: D/Statistic Fragment(5007): [onCreateView] spinDate onItemSelected 
    01-03 08:40:18.061: D/Statistic Fragment(5007): [updateFirstField] spinDate position : 0
    01-03 08:40:18.061: D/Statistic Fragment(5007): [updateFragments]

On Configuration Changed
    01-03 08:40:22.253: D/Statistic Fragment(5007): [onSaveInstanceState]
    01-03 08:40:22.313: D/Statistic Fragment(5007): [onCreateView]
    01-03 08:40:22.317: D/Statistic Fragment(5007): [onCreateView] savedInstanceState is not null and configuration has changed
    01-03 08:40:22.561: D/Statistic Fragment(5007): [onCreateView] spinDate onItemSelected 
    01-03 08:40:22.561: D/Statistic Fragment(5007): [updateFirstField] spinDate position : 0
     01-03 08:40:22.561: D/Statistic Fragment(5007): [updateFragments]

I set position of spinner to 1

    01-03 08:40:38.209: D/Statistic Fragment(5007): [onCreateView] spinDate onItemSelected 
    01-03 08:40:38.209: D/Statistic Fragment(5007): [updateFirstField] spinDate position : 1
    01-03 08:40:38.209: D/Statistic Fragment(5007): [updateFragments]

On Configuration Changed again and see onItemSelected twice!

    01-03 08:40:42.937: D/Statistic Fragment(5007): [onSaveInstanceState]
    01-03 08:40:42.957: D/Statistic Fragment(5007): [onCreateView]
    01-03 08:40:42.961: D/Statistic Fragment(5007): [onCreateView] savedInstanceState is not null and configuration has changed
    01-03 08:40:43.449: D/Statistic Fragment(5007): [onCreateView] spinDate onItemSelected 
    01-03 08:40:43.449: D/Statistic Fragment(5007): [updateFirstField] spinDate position : 1
    01-03 08:40:43.449: D/Statistic Fragment(5007): [updateFragments]
    01-03 08:40:43.449: D/Statistic Fragment(5007): [onCreateView] spinDate onItemSelected 
    01-03 08:40:43.453: D/Statistic Fragment(5007): [updateFirstField] spinDate position : 1
    01-03 08:40:43.453: D/Statistic Fragment(5007): [updateFragments]

I don't understand why onItemSelected is called twice when the position of spinner is not 0. I have to show dialog on selected item case 3, so when the orientation changed the dialog would show up again, how to prevent spinner got selected on orientation changed?

Huteri
  • 158
  • 2
  • 12
  • There are two ways, one is through the Manifest and the other one by using a Bundle. – Skynet Jan 03 '14 at 04:01
  • So, what do you mean by using a bundle? – Huteri Jan 03 '14 at 04:09
  • http://stackoverflow.com/questions/151777/saving-activity-state-in-android – Skynet Jan 03 '14 at 04:11
  • I have known about that, if you see my code, I'm using saveInstanceState to save startDate and endDate. The problem is the spinner got selected on orientation changed. How do I prevent that? I believe android save the position of selected item in my spinner, and when the orientation changed, my spinner got selected automatically. – Huteri Jan 03 '14 at 04:18
  • If saved instance state is not null, refresh the Spinner? Easy? – Skynet Jan 03 '14 at 04:19
  • http://stackoverflow.com/questions/11072576/set-selected-item-of-spinner-programmatically – Skynet Jan 03 '14 at 04:20
  • Yeah, I have tried by using setSelection(), but it does not solve the problem, the dialogs keep popping up on orientation changed. – Huteri Jan 03 '14 at 04:56
  • The other way around this would be to put a flag, if the dialog has been shown previously, dont show it again. – Skynet Jan 03 '14 at 05:10
  • I have tried with flag, and I realized it's getting odder now. If the spinner selected in position 0, it was only called once on configuration changed, but twice otherwise. see my updated question. – Huteri Jan 03 '14 at 08:49

1 Answers1

0

Alright, this can be a little bit tricky, and thanks to +AlexFlynn from android developer community in google plus and Astral Projection who was helping me.

The solution is to make use of onTouchListener, so we set up a flag like came-to-user, and set it as true in onTouchListener, and set up a condition in OnSelectionListener to check whether came-to-user is true, if it's not, then ignores the selection

Huteri
  • 158
  • 2
  • 12