2015-03-19 200 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 
    //--------------------------------------------------------------------------------