【问题标题】:Android Button initialized but not workingAndroid Button 已初始化但无法正常工作
【发布时间】:2017-02-25 18:00:53
【问题描述】:

我在 3 X 3 网格中有九个按钮,用于井字游戏应用程序。这是 board_layout.xml 中前三个按钮的代码 -

<TableLayout
    android:id="@+id/tableLayout1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="20sp" >

    <TableRow
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center" >

        <Button
            android:id="@+id/cellOne"
            android:layout_width="90sp"
            android:layout_height="98sp"
            android:text=""
            android:textSize="70sp"
            />

        <Button
            android:id="@+id/cellTwo"
            android:layout_width="90sp"
            android:layout_height="98sp"
            android:text=""
            android:textSize="70sp"
            />

        <Button
            android:id="@+id/cellThree"
            android:layout_width="90sp"
            android:layout_height="98sp"
            android:text=""
            android:textSize="70sp"
            />

    </TableRow>

<!and so on for other 6>

现在在我的 MainActivity.java 中,我有一个函数 setboard(),可以在此屏幕上设置此布局并按如下方式初始化按钮:

private String p1name = "P1";
private String p2name = "P2";

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

public void setName(View view) {
            //Function called upon click on some button
            // Other code irrelevant to the question
            setBoard();
    }

}

public void setBoard() {
    ////////////
    LayoutInflater inflater = this.getLayoutInflater();
    View boardView = inflater.inflate(R.layout.board_layout, null);
    ////////////

    boardCells = new Button[3][3];
    boardCells[0][0] = (Button) boardView.findViewById(R.id.cellOne);
    boardCells[0][1] = (Button) boardView.findViewById(R.id.cellTwo);
    boardCells[0][2] = (Button) boardView.findViewById(R.id.cellThree);
    // Code for other 6 buttons

    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++) {
            boardCells[i][j].setOnClickListener(new MyClickListener(i, j));
            boardCells[i][j].setText("");
            boardCells[i][j].setEnabled(false);
        }

    setContentView(R.layout.board_layout);

    TextView tv1 = (TextView) findViewById(R.id.p1Name_board);
    tv1.setText(p1name + ":");

    tv1 = (TextView) findViewById(R.id.p2Name_board);
    tv1.setText(p2name + ":");

    turnDisp = (TextView) findViewById(R.id.turnDispString);
    turnDisp.setText("Turn of " + p1name);
}

下面是 MyClickListener 类的代码(MainActivity 类的内部类):

class MyClickListener implements View.OnClickListener {
    int x;
    int y;


    public MyClickListener(int x, int y) {
        this.x = x;
        this.y = y;
        //This Log.d works fine
        Log.d("TAG1", Float.toString(x) + " " + Float.toString(y));
    }


    public void onClick(View view) {
        //This Log.d doesn't work
        Log.d("TAG2", Float.toString(this.x) + " Hi ");

        //This Toast also doesn't work
        Toast.makeText(getApplicationContext(), "Pressed", Toast.LENGTH_LONG).show();

        //Plus Other code irrelevant to the question
    }

现在的问题是在设置按钮时调用的构造函数中的 Log.d 工作正常并打印到 Logcat 但单击按钮时 onClick 函数不起作用。 onClick 函数既不显示 Log.d 也不显示 toast。

任何帮助将不胜感激。

【问题讨论】:

  • 数组索引为零,顺便说一句
  • inflate() 电话的其余部分是什么?您是否将板直接充气到现有布局中?如果没有,您在哪里将充气板添加到现有布局中?你确定你设置监听器的Views 实际上是屏幕上的板吗?
  • @cricket_007 我知道这只是为了方便。而且我不太了解 Java,所以请详细说明 Override。
  • 关于迈克所说的,View boardView = inflater.inflate。那行不完整....boardView 稍后在该代码中如何使用?你是如何显示这些按钮的?
  • 我们需要查看整个 setBoard() 方法以及调用它的整个方法,我假设它是一个 onCreate(),不要遗漏部分内容,您可能会遗漏一些东西

标签: java android android-layout


【解决方案1】:

简答:

您的视图不在层次结构中

长答案/解决方案(解决问题的正确方法):

您看到此问题是因为启用 onClickListeners 的视图实际上并未附加到视图层次结构。

这可以通过在你这里使用的充气器中永远不使用 null 来轻松避免:

inflater.inflate(R.layout.board_layout, null);

无论如何,它都会跳过充气器中有用的代码块,并且已经提供了等待附加到您需要的位置(即在适配器中)的规定:

inflater.inflate(R.layout.board_layout, parent, false);

当您将 null 作为第二个参数传递时,膨胀的视图不会附加到层次结构,除非您手动这样做。

但是,在您的情况下,无需膨胀布局。你在一个活动中,所以setContentView() 膨胀并替换了布局(但永远不要onCreate 之后调用)。

只需更改onCreate() 中使用的布局,然后删除inflater.inflate 并直接在上下文中调用findViewById

LayoutInflater inflater = this.getLayoutInflater(); View boardView = inflater.inflate(R.layout.board_layout, null);

boardCells[0][0] = (Button) findViewById(R.id.cellOne);

同时删除对 setContentView 的第二次调用:

setContentView(R.layout.board_layout);

第二次调用是在屏幕上添加一个新的膨胀集(不使用你附加监听器的那些)

这里还有一些其他的小错误。 Java 总是使用从零开始的数组(所以元素是 [0],[1],[2]... 而不是 [1],[2]...)。您在分配电路板时浪费了内存 - 您的布局中有一个 3x3 网格,但有一个 4x4 数组

boardCells = new Button[4][4];
boardCells[1][1] = (Button) boardView.findViewById(R.id.cellOne);

for (int i = 1; i <= 3; i++)
    for (int j = 1; j <= 3; j++)

当您使用上面的循环时,您只使用了数组中的一些项目(下面的 x)。零是空的浪费元素

0 | 0 | 0 | 0
- - - - - - -
0 | x | x | x
- - - - - - -
0 | x | x | x
- - - - - - -
0 | x | x | x

另一个注释(只是为了节省您的精力)。每当您将任何内容与字符串连接时,它都会为您转换为字符串(原语自动,对象通过其 toString 方法自动),因此对于记录以下内容都是相等的:

Log.d("TAG1", Float.toString(x) + " " + Float.toString(y));
Log.d("TAG1", new Float(x) + " " + new Float(y));
Log.d("TAG1", x + " " + y);

短解决方案(hack)

当且仅当您不理解我刚刚解释的内容。然后你可以通过改变来修复它

setContentView(R.layout.board_layout);

setContentView(boardView);

【讨论】:

  • 我知道您的第一点是为了确保与我编写的其他代码的兼容性,这就是我故意浪费内存的原因。谢谢你的第二点。但这绝不会回答我的问题。
  • 我根据建议编辑了代码,我只是坦率地说。无论如何,这也是困扰我的地方,我认为代码是正确的,但不知何故 onClick() 函数不起作用。
  • 如果我删除该代码,应用程序会在单击调用 setName() 的按钮时崩溃。原因:java.lang.NullPointerException: Attempt to read from null array at com.example.user.tictactoe_basic.MainActivity.setBoard(MainActivity.java:84) - 此行与 boardCells[0][0] = (按钮) findViewById(R.id.cellOne);
  • 我不明白你最后的评论。我还在我的答案底部添加了一个简短的 hacky 方法来修复您的代码。你说你是安卓新手。我建议你看看这本书(顺便说一下这里是另一个用户写的)commonsware.com/Android
  • 我的意思是,在执行您建议的操作时,应用程序崩溃了,并且我在 android 监视器上收到了上述错误。最初不存在充气代码,但由于之前出现错误,我从这里添加了该代码 - stackoverflow.com/questions/16192378/…
【解决方案2】:

你不应该使用那个代码,

boardCells[i][j].setOnClickListener(new MyClickListener(i, j));

我想,bug从这里开始。

你可以,

boardCells[i][j].setOnClickListener(new OnClickListener(....
Log.d("Testing","Clicked : " + i + "-" + j);
...)

【讨论】:

  • 那里没有错。你的回答只是调试应该做的一个步骤
猜你喜欢
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-14
  • 1970-01-01
  • 2010-12-30
  • 2017-03-15
相关资源
最近更新 更多