创建对话框

时间:2018-05-26 17:54:16

标签: java android dialog alertdialog android-windowmanager

我正在尝试从非活动类创建一个对话框。

这是我的代码

  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 - >然后调用显示的对话框。

3 个答案:

答案 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_ALERTTYPE_APPLICATION_OVERLAY,如果您的应用未向用户显示紧急通知,则不建议使用此对话框。

  

<强>解决方案

如果您有可用的活动背景,那么您可以显示来自任何类的对话,例如servicebroadcast 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文档:

https://developer.android.com/guide/topics/ui/dialogs