2015-10-15 42 views
5

Mam 4 timePicker w mojej aplikacji. Okno dialogowe timePicker wyświetli się, gdy użytkownik kliknie dwukrotnie na editText. Ale czasami, gdy przypadkowo kliknąłem więcej niż dwa razy, aplikacja się zawiesiła i powiedziała, że ​​fragment już został dodany. Jak mogę to naprawić? Po dwukrotnym kliknięciu przycisku editText chcę wyświetlić okno dialogowe timePicker za pomocą jednego kliknięcia na editText.Jak dodać timePicker za pomocą fragmentu?

public void onClick(View v) { 
     int id = v.getId(); 
     if (id == R.id.editTextTI1) { 
      tp.setFlag(TimePick.FLAG_START_DATE); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 
     if (id == R.id.editTextTO1) { 
      tp.setFlag(TimePick.FLAG_END_DATE); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 
     if (id == R.id.editTextTI2) { 
      tp.setFlag(TimePick.FLAG_START_DATE1); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 
     if (id == R.id.editTextTO2) { 
      tp.setFlag(TimePick.FLAG_END_DATE1); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 
     if (id == R.id.editTextTI3) { 
      tp.setFlag(TimePick.FLAG_START_DATE2); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 
     if (id == R.id.editTextTO3) { 
      tp.setFlag(TimePick.FLAG_END_DATE2); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 
     if (id == R.id.editTextTI4) { 
      tp.setFlag(TimePick.FLAG_START_DATE3); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 
     if (id == R.id.editTextTO4) { 
      tp.setFlag(TimePick.FLAG_END_DATE3); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      tp.show(ft, "TimePicker"); 
     } 

    } 




    public static class TimePick extends android.app.DialogFragment implements TimePickerDialog.OnTimeSetListener { 

     public static final int FLAG_START_DATE = 00; 
     public static final int FLAG_END_DATE = 01; 
     public static final int FLAG_START_DATE1 = 10; 
     public static final int FLAG_END_DATE1 = 11; 
     public static final int FLAG_START_DATE2 = 20; 
     public static final int FLAG_END_DATE2 = 21; 
     public static final int FLAG_START_DATE3 = 30; 
     public static final int FLAG_END_DATE3 = 31; 
     private int flag = 00; 

     @Override 
     public Dialog onCreateDialog(Bundle savedInstanceState) { 

      final Calendar c = Calendar.getInstance(); 
      int hour = c.get(Calendar.HOUR_OF_DAY); 
      int minute = c.get(Calendar.MINUTE); 

      return new TimePickerDialog(getActivity(), this, hour, minute, DateFormat.is24HourFormat(getActivity())); 
     } 

     public void setFlag(int i) { 
      flag = i; 
     } 

     @Override 
     public void onTimeSet(TimePicker view, int hourofDay, int minute) { 

      if (flag == FLAG_START_DATE) { 
       start.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       b = start.getText().toString(); 
      } 
      if (flag == FLAG_END_DATE) { 
       end.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       c = end.getText().toString(); 
      } 
      if (flag == FLAG_START_DATE1) { 
       start1.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       d = start1.getText().toString(); 
      } 
      if (flag == FLAG_END_DATE1) { 
       end1.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       e1 = end1.getText().toString(); 
      } 
      if (flag == FLAG_START_DATE2) { 
       start2.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       f = start2.getText().toString(); 
      } 
      if (flag == FLAG_END_DATE2) { 
       end2.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       g = end2.getText().toString(); 
      } 
      if (flag == FLAG_START_DATE3) { 
       start3.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       h = start3.getText().toString(); 
      } 
      if (flag == FLAG_END_DATE3) { 
       end3.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
       i = end3.getText().toString(); 
      } 

LogCat Błąd

10-15 12:53:17.113 7943-7943/com.example.project.project E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: com.example.project.project, PID: 7943 
    java.lang.IllegalStateException: Fragment already added: TimePick{7c7eb96 #0 TimePicker} 
      at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1219) 
      at android.app.BackStackRecord.run(BackStackRecord.java:715) 
      at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1535) 
      at android.app.FragmentManagerImpl$1.run(FragmentManager.java:482) 
      at android.os.Handler.handleCallback(Handler.java:739) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:148) 

Odpowiedz

2

Twój kod jest na stałe zakodowany i nie jest łatwy do przedłużenia, co może prowadzić do wielu błędów w przyszłości. Należy hermetyzacji ogólną logikę jako max, jak to możliwe, więc w tym przypadku:

public void onClick(View v) { 
    EditText editText = (EditText) v; 
    if (tp==null || !tp.isAdded()){ 
     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     tp = new TimePick(editText); 
     tp.show(ft, "TimePicker"); 
    } 
} 

@Override 
public void onStop() { 
    super.onStop(); 
    if (tp.isAdded()) tp.dismiss(); 
} 

public static class TimePick extends android.app.DialogFragment implements TimePickerDialog.OnTimeSetListener { 

    private EditText editText; 

    public TimePick(EditText editText) { 
     this.editText = editText; 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 

     final Calendar c = Calendar.getInstance(); 
     int hour = c.get(Calendar.HOUR_OF_DAY); 
     int minute = c.get(Calendar.MINUTE); 

     return new TimePickerDialog(getActivity(), this, hour, minute, DateFormat.is24HourFormat(getActivity())); 
    } 

    @Override 
    public void onTimeSet(TimePicker view, int hourofDay, int minute) { 
     editText.setText(Integer.toString(hourofDay) + ":" + Integer.toString(minute)); 
    } 
} 

ten kod nie będzie starał się stworzyć nowy czas kompletacji jeśli jest na ekranie. Możesz przekazać docelowy edittext do fragmentu timePicker. Gdy potrzebujesz wartości z tych editekstów (zmiennych a, b, c, d ...), możesz je przeczytać w razie potrzeby, nie w onTimeSetMethod.

Metoda onStop została zastosowana do obsługi czynności rekreacyjnych. Tutaj po prostu ukrywam aktywny timepicker.

+0

cześć Beloo, dziękuję za poświęcenie czasu na rozwiązanie mojego problemu. Jak przekazać inne zmienne do fragmentu timePicker? – John

+0

Mogłeś to zrobić za pomocą konstruktora, setera. Upewnij się, że naprawdę tego potrzebujesz. Jeśli opisałeś to, czego potrzebujesz, mogę być bardziej szczegółowy – Beloo

+0

możesz zobaczyć obraz po prawej stronie http://i.stack.imgur.com/45hI5.png – John

1

Ty dodajesz ten sam DialogFragment instancji dwukrotnie, aby rozwiązać ten problem, należy sprawdzić, czy TimePicker dodaje się getFragmentManager.findFragmentByTag("TimePicker").

+0

Gdzie mogę sprawdzić? – John

+0

Za każdym razem, gdy wywołujesz 'tp.show (ft," TimePicker ")', '' DialogFragment' jest dodawany jako wyjątek. Sprawdź to przed wywołaniem lub możesz użyć nowej instancji za każdym razem, ponieważ 'DialogFragment' jest usuwany podczas odrzucania. – Neil

+0

IMO dobrze jest użyć nowej instancji okna dialogowego, nie trzeba zaimplementować dużej ilości kodu standardowego, aby zresetować stan i strukturę danych, i, jako jedno z twoich rozważań, lekkie okno dialogowe ma bardzo mały wpływ na przydzielanie pamięci. – Neil