2015-03-19 155 views
6

我用代码:libGDX警告对话框

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(); 

这似乎很好,但它说:“进口android.app.AlertDialog无法解析”。 它是Android Studio中的标准libGDX项目。

回答

10

在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

+0

这就是我要做的。但说实话,这是一场噩梦!只要看看代码。为弹出式输入所有内容是否公平? – Arash 2015-03-19 18:03:16

+0

这是非常复杂的,有很多的依赖关系,进口,即无法解决。有没有更简单的解决方案? – plaidshirt 2015-03-19 23:09:02

+0

您可以将所有皮肤存储在json文件中。只需找到一些教程。代码会少得多。 ;) – Aleksandrs 2015-03-20 04:34:40

3

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

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

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

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

让我们对AlertDialog进行回调。我会在这里建议一个Abstract类,以便能够仅覆盖所需的方法,因为有时Alertdialog可以有1,2或3个按钮。

核心项目创建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 

} 

核心项目还创造CrossPlatformInterface.java:

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

你注意到在showAlertDialog方法我们通过回调以获取反馈时按钮被按下!

然后创建Android项目内部的类将实现像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. AlertDialog将在android UI线程内部创建。因为我们来自Libgdx线程来创建AlertDialog,我们需要使用runOnUiThread来确保AlertDialog是在ui线程中创建的。

最后如何执行这样的:

的Android主活动内部

实例化跨平台接口并通过活动到它的MyGdxGame内部传递的接口实例:

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 widget的调用非常简单和线程安全。

希望它能给出一个好的照片。

+0

看起来不错,但是当我尝试将ClassInsideAndroidProject类粘贴到AndroidLauncher时出现错误。 – plaidshirt 2015-03-20 20:18:03

+0

有一个接口可以与libgdx项目的android端进行交流,这是一个很好的基础知识,但是您确定要为简单的警报对话做所有事情吗?我在上面给出了一个完全独立于单个方法的工作示例,并且每个人都说这是太多的代码...? – DroidStunter 2015-03-21 12:58:27

+3

同样,scene2d有它自己的一套小部件,我会极力阻止在libgdx项目中使用本机警报对话框。伟大的教学和接口的地方,但它是没有意义的,做一个警报对话框。 – DroidStunter 2015-03-21 13:06:33

1

这工作(测试)。只需通过游戏构造函数传递FragmentActivity或活动 即可。你必须传递一些东西(如 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 
    //--------------------------------------------------------------------------------