2011-01-11 13 views
13

Tworzę okno niestandardowy zawierający EditText tak, że mogę dostać dane tekstowe od użytkownika:Dialog Problem: requestFeature() musi być wywołana przed dodaniem zawartości

final EditText newKey = (EditText) findViewById(R.id.dialog_result); 
AlertDialog.Builder keyBuilder = new AlertDialog.Builder(StegDroid.this); 
keyBuilder 
.setCancelable(false) 
.setPositiveButton("Try Again", new DialogInterface.OnClickListener() { 
    public void onClick(DialogInterface dialog, int id) { 
     Log.v("Dialog","New Key: "+newKey.getText().toString()); 
    } 
}) 
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      dialog.cancel(); 
     } 
    }); 
AlertDialog dialog = keyBuilder.create(); 
dialog.setTitle("Decryption Failed"); 
dialog.setContentView(R.layout.decrypt_failed_dialog); 
dialog.show(); 

Jednak zawsze otrzymuję ten wyjątek:

01-11 18:49:00.507: ERROR/AndroidRuntime(3461): android.util.AndroidRuntimeException: requestFeature() must be called before adding content 
01-11 18:49:00.507: ERROR/AndroidRuntime(3461):  at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:181) 
01-11 18:49:00.507: ERROR/AndroidRuntime(3461):  at com.android.internal.app.AlertController.installContent(AlertController.java:199) 
01-11 18:49:00.507: ERROR/AndroidRuntime(3461):  at android.app.AlertDialog.onCreate(AlertDialog.java:251) 

... 

na linii dialog.show(). Co powinienem zrobić, aby się tego pozbyć?

Odpowiedz

34

Musisz ustawić niestandardowy widok przed utworzeniem okna dialogowego. Musisz również użyć setView(View) zamiast setContentView(), jeśli używasz domyślnych przycisków dodatnich i ujemnych dostarczonych przez AlertDialog.

final EditText newKey = (EditText) findViewById(R.id.dialog_result); 
AlertDialog.Builder keyBuilder = new AlertDialog.Builder(StegDroid.this); 
keyBuilder 
.setCancelable(false) 
.setPositiveButton("Try Again", new DialogInterface.OnClickListener() { 
    public void onClick(DialogInterface dialog, int id) { 
     Log.v("Dialog","New Key: "+newKey.getText().toString()); 
    } 
}) 
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      dialog.cancel(); 
     } 
    }); 
keyBuilder.setTitle("Decryption Failed"); 
keyBuilder.setView(getLayoutInflater().inflate(R.layout.decrypt_failed_dialog, null)); 
AlertDialog dialog = keyBuilder.create(); 
dialog.show(); 
+2

Byłoby miło dodać komentarz, aby ktoś inny mógł łatwo dowiedzieć się, co zostało zrobione inaczej, bez konieczności porównywania kodu. – codinguser

+0

Masz rację ... Nie mam teraz czasu. Czy mógłbyś edytować odpowiedź, aby była bardziej precyzyjna? – Cristian

+3

Dzięki! Uratowałeś mi dzień za pomocą "... musisz użyć polecenia setView (View) zamiast setContentView() ..." :) –

4

Upewnij się również, że nie zwracasz już pokazanego okna dialogowego. Na przykład ProgressDialog ma poręczną metodę statyczną show(), która pobiera pewne parametry i zwraca wartość ProgressDialog. Okazuje się, że nie możesz użyć tej metody i zwrócić wynikowego ProgressDialog, ponieważ wtedy, gdy system operacyjny spróbuje go pokazać (i już jest pokazany), wyrzuci ten wyjątek.

Pamiętaj też: powyższe zachowanie występuje na emulatorze Androida, ale w rzeczywistości nie spowodowało ono wyjątku i działało dobrze na moim Droid Incredible w wersji 2.2.

2

Miałem podobny problem. Ale moje okno dialogowe miało być wyświetlane dla IME. Kiedy przełączyłem się na Dialog zamiast AlertDialog i pominięto tworzenie, program pracował dla mnie.

-3

Dokładny sposób, aby rozwiązać ten problem:

requestFeature(int) to metoda Window. Musisz zaimportować tę klasę (android.view.Window).

Musisz uzyskać okno obiektu AlertDialog.Builder. Następnie zadzwoń pod numer requestFeature(int). Parametr wejściowy jest stałą okna.

keyBuilder.getWindow().requestFeature(Window.FEATURE_ACTION_BAR);

4

ja wpadłem na ten temat rok temu i stała się w ten sposób, przy użyciu kodu dziwne. Ponownie aplikacja, nad którą pracuję, ma fragment, który powinien wyświetlać się normalnie na telefonie, ale w dialogu na tablecie. Rozwiązałem to tak:

public class MyDialogFragment extends DialogFragment { 
    private View mLayout; 
    private ViewGroup mContainer; 

    @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     mContainer = container; 
     if (getShowsDialog()) { 
      // one could return null here, or be nice and call super() 
      return super.onCreateView(inflater, container, savedInstanceState); 
     } 
     return getLayout(inflater, container); 
    } 

    private View getLayout(LayoutInflater inflater, ViewGroup container) { 
     mLayout = inflater.inflate(R.layout.my_layout, container, false); 
     return mLayout; 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     return new AlertDialog.Builder(getContext()) 
       .setPositiveButton(R.string.ok, null) 
       .setNegativeButton(R.string.cancel, null) 
       .setNeutralButton(R.string.filter_clear_selection, null) 
       .setView(getLayout(LayoutInflater.from(getContext()), mContainer)) 
       .create() 
      ; 
    } 
} 

To pozwala mi dodać moje fragmentu jak każdy normalny fragment (w układzie), ale również wyświetlić ją jako dialog, gdzie działa autonomicznie.

3

Dla tych, którzy mają ten problem szczególnie podczas korzystania z DialogFragment.

W moim przypadku stało się tak, ponieważ niepoprawnie rozszerzyłem klasę DialogFragment. Zwróciłem widok na onCreateView() i również zwracając niestandardowe okno dialogowe na onCreateDialog().Dokumentacja mówi:

Możesz mieć wygląd interfejsu użytkownika, w którym chcesz kawałek ui pojawiają się okna dialogowego, w niektórych sytuacjach, ale w pełnym ekranie lub wbudowanego fragmentu w innych (być może w zależności od czy urządzenie to duży ekran lub mały ekran). Klasa DialogFragment oferuje tę elastyczność, ponieważ nadal może zachowywać się jako fragment umożliwiający osadzanie się Fragment.

Jednak nie można użyć obiektu AlertDialog.Builder lub innych obiektów dialogowych do zbudować okno dialogowe w tym przypadku. Jeśli chcesz, aby DialogFragment był osadzany w postaci , musisz zdefiniować interfejs okna dialogowego w layoucie, a następnie załadować układ w wywołaniu zwrotnym onCreateView().

Rozwiązano problem, nie tworząc niczego na onCreateDialog() (tylko zwracając implementację nadklasy).

Powiązane problemy