我正在尝试从非活动类创建一个对话框。
这是我的代码
public static void ShowDialogBox(final Context con, final Listener list) {
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(con);
dlgAlert.setMessage("TEXT");
dlgAlert.setTitle("TEXT");
dlgAlert.setPositiveButton("TEXT"),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
dlgAlert.setCancelable(false);
dlgAlert.create().show(); // THIS LINE GIVES ME AN ERROR
}
这是我得到的错误
android.view.WindowManager $ BadTokenException:at android.view.ViewRootImpl.setView(ViewRootImpl.java:574)at android.view.WindowManagerGlobal.addView (WindowManagerGlobal.java:282)at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
在android.app.Dialog.show(Dialog.java:298)at 包裹名称和类别 包裹名称和类别 包裹名称和类别 包裹名称和类别 包名和CLASS.onBackPressed (Class.java:95)在android.app.Activity.onKeyUp (Activity.java:2465)在android.view.KeyEvent.dispatch上 (KeyEvent.java:2646)在android.app.Activity.dispatchKeyEvent (Activity.java:2716)at android.support.v7.internal.view.WindowCallbackWrapper.dispatchKeyEvent (WindowCallbackWrapper.java:50)at android.support.v7.app.AppCompatDelegateImplBase $ AppCompatWindowCallbackBase.dispatchKeyEvent (AppCompatDelegateImplBase.java:224)at com.android.internal.policy.impl.PhoneWindow $ DecorView.dispatchKeyEvent (PhoneWindow.java:2280)at android.view.ViewRootImpl $ ViewPostImeInputStage.processKeyEvent (ViewRootImpl.java:4038)at android.view.ViewRootImpl $ ViewPostImeInputStage.onProcess (ViewRootImpl.java:4000)at android.view.ViewRootImpl $ InputStage.deliver(ViewRootImpl.java:3562) 在android.view.ViewRootImpl $ InputStage.onDeliverToNext (ViewRootImpl.java:3615)at android.view.ViewRootImpl $ InputStage.forward(ViewRootImpl.java:3581) 在android.view.ViewRootImpl $ AsyncInputStage.forward (ViewRootImpl.java:3698)at android.view.ViewRootImpl $ InputStage.apply(ViewRootImpl.java:3589)
在android.view.ViewRootImpl $ AsyncInputStage.apply (ViewRootImpl.java:3755)at android.view.ViewRootImpl $ InputStage.deliver(ViewRootImpl.java:3562) 在android.view.ViewRootImpl $ InputStage.onDeliverToNext (ViewRootImpl.java:3615)at android.view.ViewRootImpl $ InputStage.forward(ViewRootImpl.java:3581) 在android.view.ViewRootImpl $ InputStage.apply(ViewRootImpl.java:3589) 在android.view.ViewRootImpl $ InputStage.deliver (ViewRootImpl.java:3562)at android.view.ViewRootImpl $ InputStage.onDeliverToNext (ViewRootImpl.java:3615)at android.view.ViewRootImpl $ InputStage.forward(ViewRootImpl.java:3581) 在android.view.ViewRootImpl $ AsyncInputStage.forward (ViewRootImpl.java:3731)at android.view.ViewRootImpl $ ImeInputStage.onFinishedInputEvent (ViewRootImpl.java:3892)at android.view.inputmethod.InputMethodManager $ PendingEvent.run (InputMethodManager.java:2208)at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback (InputMethodManager.java:1849)at android.view.inputmethod.InputMethodManager.finishedInputEvent (InputMethodManager.java:1840)at android.view.inputmethod.InputMethodManager $ ImeInputEventSender.onInputEventFinished (InputMethodManager.java:2185)at android.view.InputEventSender.dispatchInputEventFinished (InputEventSender.java:141)at android.os.MessageQueue.nativePollOnce(Native Method)at android.os.MessageQueue.next(MessageQueue.java:143)at android.os.Looper.loop(Looper.java:122)at android.app.ActivityThread.main(ActivityThread.java:5254)at java.lang.reflect.Method.invoke(Native Method)at java.lang.reflect.Method.invoke(Method.java:372)at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:902)at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:697)
以下是用户的情景
活动A - >打开活动B - >用户按活动B中的返回按钮 - >按下后退按钮,监听器被发送到活动A - >然后调用显示的对话框。
答案 0 :(得分:1)
我通常更喜欢使用DialogFragment
代替您尝试的内容以减少重复。以下是DialogFragment
示例,其中包含我称为R.layout.fragment_alert_dialog
的自定义布局:
public class AlertDialogFragment extends DialogFragment {
private static final String ARG_TITLE = "title";
private static final String ARG_MESSAGE = "message";
private String title;
private String message;
boolean endSuccess = false;
private AlertFinishedDialogListener mListener;
public AlertDialogFragment() {
}
public static AlertDialogFragment newInstance(String title, String message) {
AlertDialogFragment fragment = new AlertDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
args.putString(ARG_MESSAGE, message);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
title = getArguments().getString(ARG_TITLE);
message = getArguments().getString(ARG_MESSAGE);
}
}
@Override
public Dialog onCreateDialog(Bundle saveIntsanceState){
final Context context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View rootView = inflater.inflate(R.layout.fragment_alert_dialog, null, false);
final TextView titleView = (TextView)rootView.findViewById(R.id.tvTitle);
final TextView messView = (TextView)rootView.findViewById(R.id.tvMessage);
titleView.setText(title);
messView.setText(message);
builder.setView(rootView)
// .setTitle(title)
.setPositiveButton(R.string.ok_button_dialog_title, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
endSuccess = true;
if(mListener == null) mListener = (AlertFinishedDialogListener) context;
mListener.onAlertFinishedDialog();
}
});
return builder.create();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
if(mListener == null) mListener = (AlertFinishedDialogListener) context;
}
catch (Exception ex){
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface AlertFinishedDialogListener {
void onAlertFinishedDialog();
}
}
它包含Listener
,以防您在DialogFragment
完成时需要通知。
首先,您需要实现回调:
implements AlertDialogFragment.AlertFinishedDialogListener{
为了拨打AlertDialogFragment
,您可以通过Activity
(如有必要,还Fragment
)拨打此电话。
private void startAlertDialogFragment(String title, String mess){
AlertDialogFragment alert = AlertDialogFragment.newInstance(title, mess);
alert.show(getFragmentManager(), "alertDialogFragment132");
}
@Override
public void onAlertFinishedDialog() {
Log.e(TAG, "onAlertFinishedDialog");
}
答案 1 :(得分:1)
<强>问题强>
您可以仅显示来自活动上下文的对话框。除了TYPE_SYSTEM_ALERT或TYPE_APPLICATION_OVERLAY,如果您的应用未向用户显示紧急通知,则不建议使用此对话框。
<强>解决方案强>
如果您有可用的活动背景,那么您可以显示来自任何类的对话,例如service
,broadcast receiver
,甚至是您想象的任何课程。
这是我的解决方法,可以显示任何类的对话,就像我说的那样。
这是一个片段,用于显示来自任何课程的对话框。 (可以 更简单!)
import android.app.Dialog;
import android.content.DialogInterface;
public class SampleClass {
void anyMethod() {
Dialog dialog = ApplicationContext.getInstance().showDialog("title", "yourMessage", "Cancel", "Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO: handle button 1 clicked
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO: handle button 2 clicked
}
});
}
}
现在你将实现这项工作。
<强> 1。创建应用程序类,您将在android清单应用程序标记中注册
<application
android:name=".ApplicationContext"
...
>
...
</application>
<强> 2。在此应用程序类中,您将保存实时活动对象。这将对显示对话框更有用。
ApplicationContext.java
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.DialogInterface;
public class ApplicationContext extends Application {
private static ApplicationContext mInstance;
private Activity liveActivity;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
@Override
public void onTerminate() {
super.onTerminate();
mInstance = null;
}
public static synchronized ApplicationContext getInstance() {
return mInstance;
}
public Activity getLiveActivity() {
return liveActivity;
}
public void setLiveActivity(Activity liveActivity) {
this.liveActivity = liveActivity;
}
/*
* Show Dialog with Title, Message, Button1, Button2 with Button1 and Button2 Listener
*/
public AlertDialog showDialog(String title, String msg,
String btn1, String btn2,
DialogInterface.OnClickListener listener1,
DialogInterface.OnClickListener listener2) {
if (liveActivity == null) return null;
AlertDialog.Builder builder = new AlertDialog.Builder(liveActivity)
.setTitle(title)
.setMessage(msg)
.setCancelable(false)
.setPositiveButton(btn1, listener1);
if (btn2 != null)
builder.setNegativeButton(btn2, listener2);
AlertDialog alert = builder.create();
alert.show();
return alert;
}
}
再多一步
第3。您将通过此基本活动类扩展您的所有活动(如果您已有基础活动,则可以编辑基本活动。)
import android.support.v7.app.AppCompatActivity;
public class BaseActivity extends AppCompatActivity {
@Override
protected void onResume() {
super.onResume();
ApplicationContext.getInstance().setLiveActivity(this);
}
@Override
protected void onPause() {
super.onPause();
ApplicationContext.getInstance().setLiveActivity(null);
}
}
你走了!!!
答案 2 :(得分:1)
您尝试在单独的课程中构建pandas
时遇到的问题是您正在通过AlertDialog
AlertDialog
Context
。您收到错误是因为Activity
需要AlertDialog
中具有布局的WindowManager
而不是Activity
。这是因为Context
扩展了Activit
......而不是相反。
为了使您的代码有效,您需要提供对Context
的{{1}}访问权限。因此,将代码更改为以下内容:
AlertDialog.Builder
现在,您可以通过Activity
拨打public class TestDialog {
private static final String TAG = TestDialog.class.getSimpleName();
Activity mActivity;
public TestDialog(Activity activity){
mActivity = activity;
}
public void showDialog(){
AlertDialog.Builder b = new AlertDialog.Builder(mActivity);
b.setTitle("Title");
b.setMessage("message");
b.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.e(TAG, "showDialog : onClick");
}
});
b.create().show();
}
}
,在这种情况下可以这样说AlertDialog
:
Activity
我没有从MainActivity
尝试此操作,因此我不知道这是否适用于TestDialog testDialog = new TestDialog(MainActivity.this);
testDialog.showDialog();
,或者您是否会继续遇到某些设备的问题。出于这些原因,我(和Google!)仍然强烈建议您使用Fragment
,因为它是专为此方案设计的。请查看Google文档: