代码之家  ›  专栏  ›  技术社区  ›  JRad the Bad

“setView必须已被调用”-自定义类扩展按钮

  •  3
  • JRad the Bad  · 技术社区  · 11 年前

    所以我有一个12 x 9的“按钮”网格,叫做“瓷砖”。 Tile.java扩展了小部件“Button”。

    不过,我现在遇到了一个问题,我试图让按钮显示一个吐司,该吐司会回忆起按下按钮的ID。

    网格是动态添加的,我希望它保持这种状态。

    以下是GameBoardActivity.java的代码:

    这使12x9网格成为“平铺”,并为每个平铺添加一个侦听器。

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

    下面是上面提到的tileClick方法:

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

    LogCat显示以下内容:

    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)
    

    发生什么事?我在MainActivity.java中有几乎完全相同的代码来显示祝酒词,执行起来毫无问题。 是因为我扩展了Button,它不知道视图已经是什么了吗? 此外,由于某些原因,Eclipse不允许我添加setView()。我确信我在这里遇到了封装问题,但我对它们是什么感到困惑。 提前感谢您的帮助。 JRad公司

    1 回复  |  直到 11 年前
        1
  •  10
  •   NameSpace    11 年前

    将以下代码行更改为以下代码行:

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

    更改为:

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

    从源代码中可以看到,只有当mNextView为null时才会引发该异常。 假设函数“makeText”设置了它,它确实设置了,但您的原始代码没有捕获对它构建的Toast的引用。相反,原始代码创建两个Toast,并尝试“显示”尚未设置视图的Toast。

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