2014-12-28 15 views
5

Tôi hiểu câu hỏi này đã được hỏi nhiều lần ở đây nhưng sau khi dành 1,5 giờ đọc và cố gắng phân loại vấn đề của tôi, tôi không thể.AndroidRuntimeException: requestFeature() phải được gọi trước khi thêm nội dung vào DialogFragment

tuyên bố Vấn đề:

Khi gọi setStyle phương pháp trong DialogFragment tôi nhận được lỗi RuntimeException ghi trong tiêu đề.

Đây là mã ban đầu của tôi, mà không ném ngoại lệ này:

public class MapDialogFragment extends DialogFragment 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     view = inflater.inflate(R.layout.maps_dialog, container, false); 
     return view; 
    } 
} 

Bây giờ, tôi đã chỉ cần thêm ImmersiveMode suốt ứng dụng của tôi. Như một số bạn có thể biết, chế độ chìm sẽ bị mất khi hiển thị Hộp thoại, vì vậy người ta phải ghi đè các đoạn này và đặt cờ thích hợp để chế độ được giữ. Tôi đã thực hiện thành công điều này - nó hoạt động. Nhưng, tôi phải bình luận ra dòng: setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo);, vì vậy tôi đang mất phong cách của hộp thoại của tôi và đây là vấn đề.

Có một cái nhìn sâu hơn về các phương pháp setStyle trong DialogFragment, tôi có thể không thực sự xem làm thế nào requestFeature() đang được viện dẫn:

public void setStyle(int style, int theme) { 
     mStyle = style; 
     if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { 
      mTheme = com.android.internal.R.style.Theme_DeviceDefault_Dialog_NoFrame; 
     } 
     if (theme != 0) { 
      mTheme = theme; 
     } 
    } 

Cuối cùng, đây là lớp DialogFragment của tôi, nơi các ngoại lệ đang xảy ra. Lưu ý getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); và cũng là clearFlag, đó là cần thiết để có ImmersiveMode làm việc (hy vọng điều này sẽ có ích cho một ai đó):

public class MapDialogFragmentv2 extends DialogFragment { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     //I have also tried the code here, before the super.OnCreate but to no avail 
     //setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo); 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public Dialog onCreateDialog(final Bundle savedInstanceState) { 
     MyDialog mDialog = new MyDialog(getActivity()); 

     mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 

     view = getActivity().getLayoutInflater().inflate(R.layout.maps_dialog, null); 

     //Line below throws exception. Needs to be commented out 
     setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo); 
     mDialog.setContentView(view); 

     return mDialog; 
    } 

    public class MyDialog extends Dialog { 
     public MyDialog(Context context) { 
      super(context); 
      getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); 
      getWindow().getDecorView().setSystemUiVisibility(MainActivity.getImmersiveModeFlags()); 
     } 

     @Override 
     public void show() { 
      getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); 
      super.show(); 
     } 
    } 
} 

Tôi cũng đã cố gắng sử dụng một kết hợp của onCreate, onCreateViewonCreateDialog nhưng nó didn' t làm việc. Tôi cũng đọc ở đây tại Stackoverflow ai đó bình luận rằng nó không phải là một ý tưởng tốt để có onCreateView và onCreateDialog cùng một lúc.

Và cũng đã cố gắng bổ sung thêm phong cách để bố trí xml của tôi chính nó, nhưng cũng không làm việc:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/lib/com.google.android.gms.plus" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="@android:color/transparent" 
    style="@android:style/Theme.Holo.Dialog" > 

Cảm ơn bạn

+0

Bạn đã cố gắng gọi setStyle() bên trong onCreate() mà là sau khi super.onCreate (savedInstanceState)? –

+0

@ dev.bmax có, tôi đã làm. Trong thực tế, đó là mã rất ban đầu. –

+0

'MapDialogFragmentv2' của bạn là một lớp lồng nhau bên trong' Hoạt động'? –

Trả lời

5

Vấn đề là bạn nghiền nát cùng nhau quá nhiều thứ khác nhau và bạn không tôn trọng vòng đời của mỗi lớp.

Trước tiên, bạn cần dừng các lớp lồng nhau như bạn. Đây là một phần nguồn gốc của lỗi. Nếu bạn thực sự muốn/phải lồng một số Fragment hoặc Dialog thì điều quan trọng là bạn khai báo số lồng nhau là Fragments, Dialogs. Nếu bạn không khai báo chúng là tĩnh, bạn có thể gây ra rò rỉ bộ nhớ và các vấn đề như của bạn. Nhưng điều tốt nhất bạn có thể làm là chỉ giới hạn bản thân với một lớp cho mỗi tệp trừ khi bạn có lý do thực sự để lồng ghép nó. Điều này cũng có thêm lợi ích của việc cải thiện khả năng đọc và bảo trì mã của bạn.

Nhưng nguyên nhân chính gây ra lỗi của bạn là bạn hoàn toàn bỏ qua vòng đời của Dialog.Khá nhiều tất cả các mã sau đây phải ở trong phương pháp chu kỳ đúng đắn của Dialog:

mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 

view = getActivity().getLayoutInflater().inflate(R.layout.maps_dialog, null); 

//Line below throws exception. Needs to be commented out 
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo); 
mDialog.setContentView(view); 

Vì vậy, để khắc phục lỗi của bạn, bạn cần phải làm 3 điều:

  1. Hoặc tuyên bố MapDialogFragmentv2MyDialog tĩnh như sau:

    public class MainActivity extends Activity { 
    
        ... 
    
        public static class MapDialogFragmentv2 extends Fragment { 
    
         ... 
    
         public static class MyDialog extends Dialog { 
          ... 
         } 
        } 
    } 
    

Hoặc thậm chí di chuyển chúng tốt hơn vào các tệp của riêng chúng.

  1. Move mã từ onCreateDialog() trong MapDialogFragmentv2 trong các phương pháp vòng đời đúng trong MyDialog. Sau đó nó sẽ giống như thế này:

    public static class MyDialog extends Dialog { 
    
        private final LayoutInflater mInflater; 
    
        public MyDialog(Context context) { 
         super(context); 
    
         mInflater = LayoutInflater.from(context); 
        } 
    
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
    
         getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); 
         getWindow().getDecorView().setSystemUiVisibility(MainActivity.getImmersiveModeFlags()); 
    
         View view = mInflater.inflate(R.layout.maps_dialog, null); 
         setContentView(view); 
        } 
    
        @Override 
        public void show() { 
         getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); 
         super.show(); 
        } 
    } 
    
  2. Thêm setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo); với phương pháp onCreate() của MapDialogFragmentv2 của bạn sau khi super.onCreate() gọi.

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
    
        setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo); 
    } 
    

bạn MapDialogFragmentv2 nên sau đó chỉ cần nhìn như thế này:

public static class MapDialogFragmentv2 extends DialogFragment { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo); 
    } 

    @Override 
    public Dialog onCreateDialog(final Bundle savedInstanceState) { 
     return new MyDialog(getActivity()); 
    } 
} 

Tôi đã thử nghiệm tất cả mọi thứ trên Nexus của tôi 5 chạy Android 5.0.1 (Lollipop) và nó hoạt động .

+0

Điều đó thực sự tạo ra rất nhiều ý nghĩa. Tôi đang cố gắng làm việc này, nhưng vẫn không có may mắn. Tôi kết thúc bằng một hộp thoại không phải là toàn màn hình và không có kiểu được áp dụng cho nó. Tôi tin rằng tôi đã làm theo tất cả những gì bạn nói với tôi, nhưng việc thực hiện của tôi phức tạp hơn nhiều so với những gì tôi đã trình bày ở đây - vì vậy tôi sẽ tiếp tục cố gắng. Trong trường hợp nó hoạt động theo gợi ý của bạn, tôi sẽ đặt nó là đúng. –

0

tôi đã giải quyết được vấn đề không có một Dialog toàn màn hình trong MapDialogFragmentv2:

@Override 
    public void onStart() { 
     super.onStart(); 

     Dialog dialog = getDialog(); 
     if (dialog != null) { 
      int width = ViewGroup.LayoutParams.MATCH_PARENT; 
      int height = ViewGroup.LayoutParams.MATCH_PARENT; 
      dialog.getWindow().setLayout(width, height); 
     } 
    } 

Bây giờ điều duy nhất còn thiếu là các phương pháp setStyle() không hoạt động. Kiểu không được đặt. Nhưng nó không ném ngoại lệ ban đầu được đề cập trong bài đăng này.

0

Ok,

nó gần như đang hoạt động ngay bây giờ, vì vậy tôi sẽ đánh dấu câu trả lời của Xaver là chính xác khi nó dẫn tôi đến đúng cách.

tôi đã phải thay đổi lớp MyDialog tới:

MyDialog công cộng (bối cảnh Bối cảnh, int theme) {
siêu (bối cảnh, chủ đề);
mInflater = LayoutInflater.from (ngữ cảnh);

}

Bằng cách đó tôi quản lý để giữ Theme. Nhưng đối với một số lý do các nút của tôi không theo Chủ đề. Tất cả chúng đều trở về mặc định.Tôi đang cố thiết lập phong cách theo chương trình, nhưng không thành công cho đến bây giờ

buttonGuess.setBackgroundColor (android.R.attr.borderlessButtonStyle); buttonOk.setBackgroundColor (android.R.style.Widget_Holo_Button);

Tuy nhiên, bây giờ nó hoạt động như tôi muốn.

Cảm ơn tất cả mọi người

0

tôi giải quyết điều này bằng cách loại bỏ mã này.

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
                 Bundle savedInstanceState) { 
    return inflater.inflate(R.layout.fragment_choose_image, container, false); 
} 

} 
Các vấn đề liên quan