libGDX警报对话框

时间:2015-03-19 12:16:37

标签: android libgdx alertdialog

我使用过以下代码:

 AlertDialog.Builder bld;

 if (android.os.Build.VERSION.SDK_INT <= 10) {
     //With default theme looks perfect:
     bld = new AlertDialog.Builder(AndroidLauncher.this);
 } else {
     //With Holo theme appears the double Dialog:
     bld = new AlertDialog.Builder(AndroidLauncher.this, android.R.style.Theme_Holo_Dialog_MinWidth);
 }

 bld.setIcon(R.drawable.ic_launcher);
 bld.setTitle("Exit");
 bld.setMessage("Are you sure you want to exit?");
 bld.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); }
 });
 bld.setPositiveButton("Exit", new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) { finish(); }
 });
 bld.setCancelable(false);
 bld.create().show();

看起来很好,但它说&#34;导入android.app.AlertDialog无法解决&#34;。 它是Android Studio中的标准libGDX项目。

3 个答案:

答案 0 :(得分:11)

在libgdx中,您应该使用scene2d对话框而不是本机Android DialogInterface。下面是如何使用自定义按钮图像和背景图像向libgdx中的舞台添加完全蒙皮的对话框。您只需要替换自己的背景和按钮图像纹理和字体,然后在准备好显示对话框时调用quitGameConfirm()...

import com.badlogic.gdx.scenes.scene2d.ui.Dialog;

public void quitGameConfirm() {

    LabelStyle style = new LabelStyle(_fontChat, Color.WHITE);
    Label label1 = new Label("Are you sure that you want to exit?", style);
    label1.setAlignment(Align.center);
    //style.font.setScale(1, -1);
    style.fontColor = Color.WHITE;

    Skin tileSkin = new Skin();
    Texture tex = new Texture(myButtontexture);
    tex.setFilter(TextureFilter.Linear, TextureFilter.Linear);
    tileSkin.add("white", tex);
    tileSkin.add("default", new BitmapFont());

    TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle();
    textButtonStyle.up = tileSkin.newDrawable("white");
    textButtonStyle.down = tileSkin.newDrawable("white", Color.DARK_GRAY);
    textButtonStyle.checked = tileSkin.newDrawable("white",
            Color.LIGHT_GRAY);
    textButtonStyle.over = tileSkin.newDrawable("white", Color.LIGHT_GRAY);
    textButtonStyle.font = _myTextBitmapFont;
    textButtonStyle.font.setScale(1, -1);
    textButtonStyle.fontColor = Color.WHITE;
    tileSkin.add("default", textButtonStyle);

    TextButton btnYes = new TextButton("Exit", tileSkin);
    TextButton btnNo = new TextButton("Cancel", tileSkin);

    // /////////////////
    Skin skinDialog = new Skin(Gdx.files.internal("data/uiskin.json"));
    final Dialog dialog = new Dialog("", skinDialog) {
        @Override
        public float getPrefWidth() {
            // force dialog width
            // return Gdx.graphics.getWidth() / 2;
            return 700f;
        }

        @Override
        public float getPrefHeight() {
            // force dialog height
            // return Gdx.graphics.getWidth() / 2;
            return 400f;
        }
    };
    dialog.setModal(true);
    dialog.setMovable(false);
    dialog.setResizable(false);

    btnYes.addListener(new InputListener() {
        @Override
        public boolean touchDown(InputEvent event, float x, float y,
                int pointer, int button) {

            // Do whatever here for exit button

            _parent.changeState("StateMenu");
            dialog.hide();
            dialog.cancel();
            dialog.remove();                

            return true;
        }

    });

    btnNo.addListener(new InputListener() {
        @Override
        public boolean touchDown(InputEvent event, float x, float y,
                int pointer, int button) {

            //Do whatever here for cancel

            dialog.cancel();
            dialog.hide();

            return true;
        }

    });

    TextureRegion myTex = new TextureRegion(_dialogBackgroundTextureRegion);
    myTex.flip(false, true);
    myTex.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
    Drawable drawable = new TextureRegionDrawable(myTex);
    dialog.setBackground(drawable);

    float btnSize = 80f;
    Table t = new Table();
    // t.debug();

    dialog.getContentTable().add(label1).padTop(40f);

    t.add(btnYes).width(btnSize).height(btnSize);
    t.add(btnNo).width(btnSize).height(btnSize);

    dialog.getButtonTable().add(t).center().padBottom(80f);
    dialog.show(stage).setPosition(
            (MyGame.VIRTUAL_WIDTH / 2) - (720 / 2),
            (MyGame.VIRTUAL_HEIGHT) - (MyGame.VIRTUAL_HEIGHT - 40));

    dialog.setName("quitDialog");
    stage.addActor(dialog);

}

enter image description here

答案 1 :(得分:4)

问题是你正在尝试创建一个Android小部件,我怀疑你是在Libgdx-core实现中做的。核心实现没有任何Android SDK参考。

那是因为它是继承核心项目的Android项目。因此,核心项目不知道加载到Android实现的任何依赖项。

要解决此问题,您需要在Android项目和Core Project之间创建一个接口。这将允许您调用Android项目中的方法。 必须在核心项目内创建接口,以便两个项目都可以访问它。

例如,您在核心Project中创建了CrossPlatformInterface.java。但首先让我们创建一个回调来从Libgdx线程中的Ui线程获得反馈。 重要的是要记住,Libgdx有一个独立的线程,Android主线程!!! 如果你试图从Libgdx线程运行Android的Widgets,应用程序将会粉碎。

让我们为AlertDialog进行回调。我将在这里建议一个Abstract类,以便只能覆盖你想要的方法,因为有时Alertdialog可以有1,2或3个按钮。

在Core Project中创建AlertDialogCallback.java:

public abstract class AlertDialogCallback{

    public abstract void positiveButtonPressed();
    public void negativeButtonPressed(){}; // This will not be required
    public void cancelled(){}; // This will not be required

}

在Core Project中还创建了CrossPlatformInterface.java:

public interface CrossPlatformInterface{
    public void showAlertDialog(AlertDialogCallback callback);
}

您注意到在showAlertDialog方法中,我们传递回调以在按下按钮时获得反馈!

然后在Android项目中创建一个Class,它将实现CrossPlatformInterface,如:

public ClassInsideAndroidProject implements CrossPlatFormInterface{

   private AndroidLauncher mActivity; // This is the main android activity

   public ClassInsideAndroidProject(AndroidLauncher mActivity){
        this.mActivity = mActivity;
   }
   public void showAlertDialog(final AlertDialogCallback callback){

      mainActivity.runOnUiThread(new Runnable(){

        @Override
        public void run() {

            AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
            builder.setTitle("Test");
            builder.setMessage("Testing");
            builder.setPositiveButton("OKAY", new OnClickListener(){

                @Override
                public void onClick(DialogInterface dialog, int which) {

                    callback.positiveButtonPressed();

                }   
            });
            builder.setNegativeButton(negativeButtonString, new OnClickListener(){

                @Override
                public void onClick(DialogInterface dialog, int which) {

                    callback.negativeButtonPressed();

                }

            });

            AlertDialog dialog = builder.create();
            dialog.show();
        }
    });
   }
}

重要提示

  1. CrossPlatformInterface将在MainActivity(AndroidLauncher)中实例化,如下所示。
  2. 将在android UI线程内创建AlertDialog。因为我们来自Libgdx线程来创建AlertDialog,所以我们需要使用runOnUiThread来确保在ui线程中创建AlertDialog。
  3. 最后如何执行此操作:

    在Android main Activity中实例化CrossPlatform接口,并将Activity传递给在MyGdxGame中传递的Interface实例:

    public class MainActivity extends AndroidApplication {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
                cfg.useGL20 = false;
    
        initialize(new MyGdxGame(new ClassInsideAndroidProject(this)), cfg);
        }
    }
    

    最后,当创建MyGDxGame时,我们得到了crossplatform接口的实例,我们可以调用我们想要的任何函数到android ui线程。

    public class MyGdxGame extends Game {
    
    ClassInsideAndroidProject crossPlatformInterface;
    
    public MyGdxGame(ClassInsideAndroidProject crossPlatformInterface){
         this.crossPlatformInterface = crossPlatformInterface;
    }
    
    @Override
    public void create() {
    
        crossPlatformInterface.showAlertDialog(new AlertDialogCallback(){
    
           @Override
           public void positiveButtonPressed(){
    
           //IMPORTANT TO RUN inside this method the callback from the ui thread because we want everything now to run on libgdx thread! this method ensures that.
              Gdx.app.postRunnable(new Runnable().....) 
    
           }
           @Override
           public void negativeButtonPressed(){
    
           }; // This will not be required
           @Override
           public void cancelled(){
    
            }; // This will not be required
        });
    }
    
    @Override
    public void render() {
        super.render();
    }
    
    public void dispose() {
        super.dispose();
    }
    
    public void pause() {
        super.pause();
    }
    }
    

    我认为这是我第一次打算写的更多。它可能看起来令人生畏,但实际上相当简单。在你完成它之后,一切看起来都比较简单:)。 这项工作的优点是在你创建这个界面后,任何对android小部件的调用都将非常容易和线程安全。

    希望它能给出一幅好照片。

答案 2 :(得分:1)

  

这可行(已测试)。只需传入FragmentActivity或Activity即可   通过你的游戏构造函数。你必须传递一些东西(比如   ClassInsideAndroidProject)。为什么不传递一个非常有用的元素!。

//---------------------------------------------------------------------------
        /**  INSIDE the libgdc core, create a custom NATIVE android dialog
         * :- breaks the rules somewhat for the core,
         *  but if you ONLY using Android, why not use android Native!
         *   @member_var  private final FragmentActivity m_fa; 
         * @constructor public xx_your_app_xx(FragmentActivity m_fa) 
         *{
         *  this.m_fa = m_fa;
         *}
         *  @called_with if(m_fa != null) showCustomDialog(m_fa);
         * @param fa
         */
        public static void showCustomDialog(final FragmentActivity fa) //or Activity 
        {
            fa.runOnUiThread(new Runnable()
            {
    //          boolean[] info;
                @Override
                public void run()
                {
                    LinearLayout ll_Main     = new LinearLayout(fa);
                    LinearLayout ll_Row01    = new LinearLayout(fa);
                    LinearLayout ll_Row02    = new LinearLayout(fa);
                    LinearLayout ll_Row09    = new LinearLayout(fa);
                    LinearLayout ll_Row10    = new LinearLayout(fa);

                    ll_Main.setOrientation(LinearLayout.VERTICAL);
                    ll_Row01.setOrientation(LinearLayout.HORIZONTAL);
                    ll_Row02.setOrientation(LinearLayout.HORIZONTAL);
                    ll_Row09.setOrientation(LinearLayout.HORIZONTAL);
                    ll_Row10.setOrientation(LinearLayout.HORIZONTAL);

                    final CheckBox checkBox  = new CheckBox(fa);
                    final CheckBox cb_debug  = new CheckBox(fa);
                    final EditText et_User   = new EditText(fa);
                    final EditText et_Pass   = new EditText(fa);

                    TextView tv_Check        = new TextView(fa);
                    TextView tv_Debug        = new TextView(fa);
                    TextView tv_User         = new TextView(fa);
                    TextView tv_Pass         = new TextView(fa);

                    tv_Check.setText("rotation lock: ");
                    tv_Debug.setText("debug: ");
                    tv_User.setText("Username: ");
                    tv_Pass.setText("Password: ");

                    ll_Row01.addView(tv_Check);
                    ll_Row01.addView(checkBox);

                    ll_Row02.addView(tv_Debug);
                    ll_Row02.addView(cb_debug);

                    ll_Row09.addView(tv_User);
                    ll_Row09.addView(et_User);

                    ll_Row10.addView(tv_Pass);
                    ll_Row10.addView(et_Pass);

                    ll_Main.addView(ll_Row01);
                    ll_Main.addView(ll_Row02);
    //              ll_Main.addView(ll_Row09);
    //              ll_Main.addView(ll_Row10);

                    AlertDialog.Builder alert = new AlertDialog.Builder(fa);//this.getActivity()
                    alert.setTitle("Camera settings");
                    alert.setView(ll_Main);
                    alert.setCancelable(false);
                    alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() 
                    {
                        @Override
                        public void onClick(DialogInterface dialog, int which) 
                        {
    //                      info1[0] = checkBox.isChecked();
    //                      info1[1] = cb_debug.isChecked();
    //                      String user = et_User.getText().toString();
    //                      String pass = et_Pass.getText().toString();
                            //do something with the data
                            Gdx.app.log("INFO", "**** positiveButtonPressed works here too! ***");
                            Toast.makeText(fa,
                                    "checkBox: " + checkBox.isChecked() +
                                    ", cb_debug: " + cb_debug.isChecked(),
                                    Toast.LENGTH_LONG).show();
                            //IMPORTANT TO RUN inside this {} means everything now  run's on libgdx thread!.
                            Gdx.app.postRunnable( new Runnable() 
                               {
                                    public void run() 
                                    {
                                        //do something with the data
                                        Gdx.app.log("INFO", "**** positiveButtonPressed works here ****");
                                    }//run
                                });//postRunnable
                        }//onClick
                    });//setPositiveButton
                    alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() 
                    {   
                        @Override
                        public void onClick(DialogInterface dialog, int which) 
                        {
                            dialog.dismiss();
                        }//setPositiveButton
                    });//setNegativeButton
                    AlertDialog dialog = alert.create();
                    dialog.show();
                }//run
            });//runOnUiThread
        }//showCustomDialog
    //--------------------------------------------------------------------------------