Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libGDX Alert Dialog

I have used code below:

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

It seems fine, but it says "import android.app.AlertDialog cannot resolve". It is a standard libGDX project in Android Studio.

like image 396
plaidshirt Avatar asked Mar 19 '15 12:03

plaidshirt


1 Answers

The problem is that you are trying to create an Android widget which I suspect you are doing it in the Libgdx-core implementation. The core implementation does not have any references to Android SDK.

That is because it is the Android project which inherits the core project. As a result the core project is not aware of any dependencies loaded to the Android implementation.

To overcome this you need to create an interface between Android project and Core Project. That will allow you to call methods inside the Android Project. The interface must be created inside the core Project in order for both projects to have access to it.

For example you create CrossPlatformInterface.java inside core Project. But first let's create a callback to get feedback from the Ui Thread inside the Libgdx Thread. It is important to remember that Libgdx has a seperate thread that Android main thread!!! If you try to run Widgets of Android from Libgdx threads the Application will crush.

Let's make the callback for the AlertDialog. I will suggest an Abstract class here in order to be able to override only the methods you want because sometimes Alertdialog can have 1,2 or 3 buttons.

In Core Project create 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

}

In Core Project also create CrossPlatformInterface.java:

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

You notice that in the showAlertDialog method we pass the callback to get feedback when buttons are pressed!

Then you create a Class inside Android project that will implement the CrossPlatformInterface like:

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

Important notes

  1. The CrossPlatformInterface will be instantiated inside the MainActivity (AndroidLauncher) as you will see below.
  2. The AlertDialog will be created inside the android UI thread. Because we are coming from the Libgdx thread to create the AlertDialog we need to use runOnUiThread to ensure the AlertDialog is created in ui thread.

Finally how to execute this:

Instantiate CrossPlatform interface inside Android main Activity and pass the Activity to the Interface instance which is passed inside the 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);
    }
}

Finally when the MyGDxGame is created we get the instance of the crossplatform interface and we can the call any functions we want to the android ui thread.

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

I think it was much more writing I first intended. It might look daunting but actually is fairly simple. Well after you've done it everything looks simpler :). The advantage of this effort is after you make this interface any call to android widget will be very easy and thread safe.

Hope it gives a good picture.

like image 107
z3n105 Avatar answered Nov 11 '22 13:11

z3n105