Frage

So I've got a 12 x 9 grid of "buttons" called "tiles". Tile.java extends the widget "Button".

I've got an issue right now though, where I'm trying to get the button to display a toast that recalls the ID of the button pushed.

The grid is added dynamically and I want it to stay that way.

Here's the code from GameBoardActivity.java:

This makes the 12x9 grid of "tiles" and adds a listener for each.

    public void gridRowButtons(int iterations){
    final Tile[] gridSpaces = new Tile[12];
    LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
    for (int i = 0; i < 12; i++) {
        String idString = String.valueOf(aToI[iterations]) + String.valueOf(i + 1);
        final int id = getResources().getIdentifier(idString, "id", getPackageName());
        gridSpaces[i] = new Tile(getApplicationContext());
        gridSpaces[i].setText("");
        gridSpaces[i].setHeight(40);
        gridSpaces[i].setWidth(40);
        gridSpaces[i].setLayoutParams(buttonParams);
        gridSpaces[i].setId(id);
        OnClickListener showID = new OnClickListener(){
            public void onClick(View view){                 
                TextView text = (TextView) findViewById(R.id.tileIDText);
                String tileID = getApplicationContext().getResources().getResourceEntryName(id);
                text.setText(tileID);
                Tile clickedTile = (Tile) findViewById(id);
                clickedTile.tileClick(0, tileID);
            }
        };
        gridSpaces[i].setOnClickListener(showID);
    }
    LinearLayout buttonRow = new LinearLayout(getApplicationContext());
    buttonRow.setOrientation(LinearLayout.HORIZONTAL);
    buttonRow.setLayoutParams(buttonParams);
    LinearLayout boardSpace = (LinearLayout) this.findViewById(R.id.boardLayout);
    for (int i = 0; i < gridSpaces.length; i++) {
        buttonRow.addView(gridSpaces[i]);
    }
    boardSpace.addView(buttonRow);
}

And here's the tileClick method mentioned above:

    public void tileClick(int action, String tileID) {
    switch(action) {
        case 1 :
            //action 1
        case 2 :
            //action 2
        default :
            Context context = getContext();
            Toast toast = new Toast(context);
            Toast.makeText(context, tileID, Toast.LENGTH_SHORT);
            toast.show();
    }
}

The LogCat shows the following:

02-22 20:45:14.623: E/AndroidRuntime(7868): FATAL EXCEPTION: main
02-22 20:45:14.623: E/AndroidRuntime(7868): java.lang.RuntimeException: setView must have been called
02-22 20:45:14.623: E/AndroidRuntime(7868):     at android.widget.Toast.show(Toast.java:103)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at com.jneal.ecquire.Tile.tileClick(Tile.java:51)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at com.jneal.ecquire.GameBoardActivity$1.onClick(GameBoardActivity.java:55)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at android.view.View.performClick(View.java:3627)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at android.view.View$PerformClick.run(View.java:14329)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at android.os.Handler.handleCallback(Handler.java:605)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at android.os.Handler.dispatchMessage(Handler.java:92)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at android.os.Looper.loop(Looper.java:137)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at android.app.ActivityThread.main(ActivityThread.java:4511)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at java.lang.reflect.Method.invokeNative(Native Method)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at java.lang.reflect.Method.invoke(Method.java:511)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:976)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:743)
02-22 20:45:14.623: E/AndroidRuntime(7868):     at dalvik.system.NativeStart.main(Native Method)

What's going on? I've got virtually the exact same code for displaying a toast in my MainActivity.java and that executes with no problem. Is it because I've extended Button and it doesn't know what the view is already? Also, Eclipse won't let me add setView() for some reason. I'm sure I've got encapsulation issues here but I'm confused as to what they are. Thanks for your help in advance. JRad

War es hilfreich?

Lösung

Change the lines of code below, to the one's that follow:

        Toast toast = new Toast(context);
        Toast.makeText(context, tileID, Toast.LENGTH_SHORT);
        toast.show();

Change to this:

    Toast toast = Toast.makeText(context, tileID, Toast.LENGTH_SHORT);
    toast.show();       

As you can see from the source code, that exception is thrown only when mNextView is null. The function "makeText" is suppose to set it, and it does, but your original code does not capture the reference to the Toast it builds. Instead, your original code creates two Toasts, and attempts to "show" the one which has not yet had its view set.

public void show() {
    if (mNextView == null) {
        throw new RuntimeException("setView must have been called");
    }

....

public static Toast makeText(Context context, CharSequence text, int duration) {
    Toast result = new Toast(context);

    LayoutInflater inflate = (LayoutInflater)
            context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
    TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
    tv.setText(text);

    result.mNextView = v;
    result.mDuration = duration;

    return result;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top