Question

Ok, bear with me because I haven't worked with custom Dialogs (or Android programming at all really) that much, and I'm sure I've made a stupid beginner mistake.

So I have a simple dice rolling app that I'm trying to incorporate into my existing app, but I want to do it as essentially a popup. The solution I found thus far was to extend a dialog class and use the xml from the app as a custom layout. This actually displays the expected output, but doesn't allow me to interact with it (i.e. it shows dice on screen but I can't roll them!).

The java class I'm calling is this:

import java.io.IOException;
import java.util.Random;
import com.zeldar.scanner.R;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class RollDice extends Activity implements SensorEventListener {
    private final int rollAnimations = 50;
    private final int delayTime = 15;
    private Resources res;
    private final int[] diceImages = new int[] { R.drawable.d1, R.drawable.d2, R.drawable.d3, R.drawable.d4, R.drawable.d5, R.drawable.d6 };
    private Drawable dice[] = new Drawable[6];
    private final Random randomGen = new Random();
    @SuppressWarnings("unused")
    private int diceSum;
    private int roll[] = new int[] { 6, 6 };
    private ImageView die1;
    private ImageView die2;
    private LinearLayout diceContainer;
    private SensorManager sensorMgr; 
    private Handler animationHandler;
    private long lastUpdate = -1;
    private float x, y, z;
    private float last_x, last_y, last_z;
    private boolean paused = false;
    private static final int UPDATE_DELAY = 50;
    private static final int SHAKE_THRESHOLD = 400;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        paused = false;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dice);
        setTitle(getString(R.string.app_name));
        res = getResources();
        for (int i = 0; i < 6; i++) {
            dice[i] = res.getDrawable(diceImages[i]);
        }
        diceContainer = (LinearLayout) findViewById(R.id.diceContainer);
        diceContainer.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    rollDice();
                } catch (Exception e) {};
            }
        });
        die1 = (ImageView) findViewById(R.id.die1);
        die2 = (ImageView) findViewById(R.id.die2);
        animationHandler = new Handler() {
            public void handleMessage(Message msg) {
                die1.setImageDrawable(dice[roll[0]]);
                die2.setImageDrawable(dice[roll[1]]);
            }
        };
        sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
        boolean accelSupported = sensorMgr.registerListener(this,
                sensorMgr.getDefaultSensor(SensorManager.SENSOR_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
        if (!accelSupported) sensorMgr.unregisterListener(this); //no accelerometer on the device
        rollDice();
    }

    private void rollDice() {
        if (paused) return;
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < rollAnimations; i++) {
                    doRoll();
                }
            }
        }).start();
        MediaPlayer mp = MediaPlayer.create(this, R.raw.roll);
        try {
            mp.prepare();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mp.start();
    }

    private void doRoll() { // only does a single roll
        roll[0] = randomGen.nextInt(6);
        roll[1] = randomGen.nextInt(6);
        diceSum = roll[0] + roll[1] + 2; // 2 is added because the values of the rolls start with 0 not 1
        synchronized (getLayoutInflater()) {
            animationHandler.sendEmptyMessage(0);
        }
        try { // delay to alloy for smooth animation
            Thread.sleep(delayTime);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void onResume() {
        super.onResume();
        paused = false;
    }

    public void onPause() {
        super.onPause();
        paused = true;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        Sensor mySensor = event.sensor;
        if (mySensor.getType() == SensorManager.SENSOR_ACCELEROMETER) {
            long curTime = System.currentTimeMillis();
            if ((curTime - lastUpdate) > UPDATE_DELAY) {
                long diffTime = (curTime - lastUpdate);
                lastUpdate = curTime;
                x = event.values[SensorManager.DATA_X];
                y = event.values[SensorManager.DATA_Y];
                z = event.values[SensorManager.DATA_Z];
                float speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000;
                if (speed > SHAKE_THRESHOLD) { //the screen was shaked
                    rollDice();
                }
                last_x = x;
                last_y = y;
                last_z = z;
            }
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        return; //this method isn't used
    }
}

And this is the layout xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/diceContainer"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp" >

    <ImageView
        android:id="@+id/die1" 
        android:src="@drawable/d6"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginBottom="15dp"
        android:contentDescription="@string/content_dice" />

    <ImageView
        android:id="@+id/die2"
        android:src="@drawable/d6"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:contentDescription="@string/content_dice" />

</LinearLayout>

Finally, the call I'm using to create the dialog:

private Dialog rollDice;

rollDice = new Dialog(ScanActivity.this);
rollDice.setContentView(R.layout.dice);
rollDice.setTitle("Roll Dice");
rollDice.setCancelable(true);
rollDice.show();

To clarify: the most confusing part is that I'm not getting an error, either on compile or run time, it just pops up the window and won't let me do anything with it (except dismiss)!

Was it helpful?

Solution

I would suggest using an activity with a dialog theme if you are wanting something like a dialog. This will allow it to "pop-up" like a dialog but give you more flexibility and easier to manipulate, IMHO. Create a separate activity to open up and add this to your manifest for the activity

<activity android:theme="@android:style/Theme.Dialog">

Themes

There may be a better way to do this but I think this might work well for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top