按钮onClickListener导致运行时错误,而无需按下它

时间:2018-08-02 14:38:51

标签: java android button runtime-error onclicklistener

我正在尝试制作一个应用程序,其中一个循环生成算术表达式并将它们作为线性布局中的单个TextView列出。点击其中一个表达式后,弹出窗口会显示该表达式以及一个供用户输入解决方案的输入字段。下面有一个提交解决方案的按钮。我将按钮定位在XML中。问题是,当我使用onClickListener时,当我点击要弹出的窗口的表达式时,应用程序崩溃。如果我删除整个onClickListener,则窗口出现,但按钮无功能。 这会导致错误:

Button btnDone = (Button) findViewById(R.id.buttonDone);
        btnDone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                answerWindow.dismiss();
            }
        });

这是该函数的其余部分:

    package klosinski.kamil.arithmeticproblems;

import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.ScrollView;
import android.widget.TextView;

import java.util.Random;

public class QuizGenerate extends AppCompatActivity {



   boolean usePlus, useMinus, useMult, useDivide;
   int count, maxValue;
   Equation equation[] = new Equation[20];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_quiz_generate);

        SharedPreferences quizSettings = getSharedPreferences("QuizSettings", MODE_PRIVATE);

        usePlus = quizSettings.getBoolean("usePlus", true);
        useMinus = quizSettings.getBoolean("useMinus", true);
        useMult = quizSettings.getBoolean("useMult", true);
        useDivide = quizSettings.getBoolean("useDivide", true);
        count = quizSettings.getInt("count",0);
        maxValue = quizSettings.getInt("maxValue",0);
        generateQuiz(); //Populate Equation class with generated equations
        displayQuiz(); //Display the equations to the screen
    }

    //Method to display the contents of Equation class to the screen
    public void displayQuiz(){
        ScrollView scrollView = (ScrollView) findViewById(R.id.scrollViewx);
        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        scrollView.addView(linearLayout);
        for(int i = 0; i < count; i++){
            int value1 = equation[i].getValue1();
            int value2 = equation[i].getValue2();
            char operator = equation[i].getOperator();

            String value1Str = Integer.toString(value1);
            String value2Str = Integer.toString(value2);

            TextView textView = new TextView(this);
            textView.setTextSize(getResources().getDimension(R.dimen.equationSize));
            if(operator == '/'){
                operator = '\u00F7';
            }
            textView.setText(value1Str + " " + operator + " " + value2Str + "=");
            textView.setId(i);
            textView.setOnClickListener(displayAnswerForm);
            textView.setClickable(true);

            linearLayout.addView(textView);
        }
        this.setContentView(scrollView);
    }

    // OnClickListener runs after equation is pressed.
    // Displays a popup window with the pressed equation and editText for answer.
    public View.OnClickListener displayAnswerForm = new View.OnClickListener() {
        public void onClick(View v) {

            LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
            View popupView = inflater.inflate(R.layout.popup_window, null);

            // Create the popup window
            int width = LinearLayout.LayoutParams.MATCH_PARENT;  // Width of the popup window
            int height = LinearLayout.LayoutParams.MATCH_PARENT; // Height of the popup window
            final PopupWindow answerWindow = new PopupWindow(popupView, width, height, true);

            int equationTextViewId= v.getId(); // The ID of the text view that was pressed

            // Getting the values and operator to display as equation.
            String value1 = Integer.toString(equation[equationTextViewId].getValue1());
            String value2 = Integer.toString(equation[equationTextViewId].getValue2());
            char operator = equation[equationTextViewId].getOperator();
            // If operator is a '/' (divide) then display it as a divider symbol.
            if(operator == '/'){
                operator = '\u00F7';
            }
            String equationToDisplay = value1+" "+operator+" "+value2+"="; // Complete string with the equation.

            //Display our equation on the popup window.
            ((TextView)answerWindow.getContentView().findViewById(R.id.answerWindowTextView)).setText(equationToDisplay);


            // Display the popup window.
            answerWindow.showAtLocation(v, Gravity.CENTER, 0, 0);


            ////
            ////
            //// setOnClickListener or the function causes a crash.
            ////
            ////
            Button btnDone = (Button) findViewById(R.id.buttonDone);
            btnDone.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    answerWindow.dismiss();
                }
            });


        }

    };


    //Method to populate Equation class with generated equations
    public void generateQuiz(){

        char operator = '+';

        for(int i = 0; i < count; i++){
            switch(getRandomNumber(1, 4)){
                case 1:
                    operator = '+';
                    break;
                case 2:
                    operator = '-';
                    break;
                case 3:
                    operator = '*';
                    break;
                case 4:
                    operator = '/';
                    break;
                default:
                    break;
            }

            equation[i] = new Equation(getRandomNumber(1, maxValue), getRandomNumber(1, maxValue), operator);
        }
    }

    private int getRandomNumber(int min,int max) {
        return (new Random()).nextInt((max - min) + 1) + min;
    }



}
    <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    android:gravity="center"
    android:visibility="visible">

    <TextView
        android:id="@+id/answerWindowTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:text="5 + 2="
        android:textAllCaps="false"
        android:textSize="50sp"
        app:layout_constraintBottom_toTopOf="@+id/editText8"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <EditText
        android:id="@+id/editText8"
        style="@style/Widget.AppCompat.AutoCompleteTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:backgroundTint="@color/colorEditText"
        android:ems="10"
        android:gravity="center"
        android:hint="eg. 28"
        android:inputType="number"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.527"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/answerWindowTextView" />

    <Button
        android:id="@+id/buttonDone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="DONE"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText8" />

</android.support.constraint.ConstraintLayout>

Google已将我引向一些“相关”主题,但没有一个对我有帮助。可能与View有关吗?

关于, 卡米尔(Kamil)

@edit

08-02 15:50:18.731 12741-12741/klosinski.kamil.arithmeticproblems E/AndroidRuntime: FATAL EXCEPTION: main
    Process: klosinski.kamil.arithmeticproblems, PID: 12741
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
        at klosinski.kamil.arithmeticproblems.QuizGenerate$1.onClick(QuizGenerate.java:110)
        at android.view.View.performClick(View.java:5698)
        at android.widget.TextView.performClick(TextView.java:10846)
        at android.view.View$PerformClick.run(View.java:22565)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:158)
        at android.app.ActivityThread.main(ActivityThread.java:7230)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

2 个答案:

答案 0 :(得分:0)

此行at klosinski.kamil.arithmeticproblems.QuizGenerate$1.onClick(QuizGenerate.java:110)告诉您崩溃发生在110行的QuizGenerate.java文件中。

错误java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference表明btnDone为空。

findViewById仅在您要查找的视图属于作用域中的当前上下文时才有效。即,如果您在Activity中调用findViewById,则该视图应属于该Activity,否则它将返回null。如果要在Fragment中调用findViewById,则视图应属于该片段,否则它将返回null。你明白了。

因此,请确保您从正确的位置致电Button btnDone = (Button) findViewById(R.id.buttonDone);

答案 1 :(得分:0)

您不应使用setContentView();像这样。仅在onCreate()中仅调用一次。如果要更改内容,请使用片段或开始其他活动。如果更改内容,则无法再通过findViewById查找视图。