Android:如何运行由一个按钮控制的环路(开始/暂停)

发布于 2025-02-10 12:39:44 字数 7040 浏览 0 评论 0原文

我正在使用Java(Android)的程序进行程序,希望它在按钮点击时开始并继续提出问题,直到提示用户输入输入为止,一旦收到输入,该程序就应该恢复问题。再次单击按钮时,程序应暂停。

我是OOP的新手,自学。我认为线程将是解决问题的最实用方法。我无法使程序既循环又允许用户输入。尝试使用HandlerThread时,我会在EditText中输入数据的能力。有人可以帮助让这个循环在输入后单击和循环运行吗?

我有一个功能性程序,当按钮循环时可以使用:

主布局以“启动”按钮开头,单击“启动”按钮转到“暂停”,并使一个单独的重复按钮可见(且功能性)。

生成值,提出问题,并通过弹出软键盘并在EditText字段中设置光标来提示用户。

收到答案并单击“输入/完成”键盘按钮后,将根据保存值评估答案。但是我无法让程序循环,或者如果我将其循环循环,则它会完全跳过输入,并继续作为问题而没有时间输入。

如果需要,请引导我使用代码清洁度,我想了解我在做什么。

main.java

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    // Create appropriate objects for buttons, edit text, and text to speech
    TextToSpeech tts;
    EditText txt;
    Button sbtn, rbtn;

    // Array and int to store numbers
    int[] num;
    int added = 0;

    // Boolean to check if questions is running
    public boolean isRunning;

    // Variables for random number range. TODO(Put into switch statement and list to select 1, 10, or 100s)
    static int maxNum = 100;
    static int minNum = 10;

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

        // Initializing buttons and others
        txt = findViewById(R.id.ans);
        sbtn = findViewById(R.id.strButton);
        rbtn = findViewById(R.id.rptButton);
        rbtn.setVisibility(View.INVISIBLE);

        // Initialize text to speech engine
        tts = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status != TextToSpeech.ERROR) {
                    tts.setLanguage(Locale.ENGLISH);
                }
            }
        });

        // Start button click listener
        sbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (!isRunning) {
                    // Show repeat button, hide start and show pause
                    rbtn.setVisibility(View.VISIBLE);
                    sbtn.setText("Pause");

                    process();

                    isRunning = true;

                } else {
                    sbtn.setText("Start");
                    rbtn.setVisibility(View.GONE);

                    isRunning = false;
                }
            }
        });

        // Repeat button click listener
        rbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // Repeat recently generated numbers
                Utilities.speakNums(num[0], num[1], tts);
            }
        });
    }

    public void onPause() {
        if (tts != null) {
            tts.stop();
            tts.shutdown();
        }
        super.onPause();
    }

    // Get input and compare with stored values, announce if user answer is correct or incorrect
    public void submitAns() {
        txt.setOnKeyListener(new View.OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // If the event is a key-down event on the "enter/done" button
                if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
                        (keyCode == KeyEvent.KEYCODE_ENTER)) {
                    // Check to make sure the text field is not empty
                    if (TextUtils.isEmpty(txt.getText().toString())) {
                        Toast.makeText(MainActivity.this, "Enter a Number!", Toast.LENGTH_SHORT).show();
                        return false;
                    }
                    int intValue = Integer.parseInt(txt.getText().toString());

                    if (added == intValue) {
                        Toast.makeText(MainActivity.this, "Correct", Toast.LENGTH_SHORT).show();
                        tts.speak("Correct", TextToSpeech.QUEUE_ADD, null, null);
                    } else {
                        Toast.makeText(MainActivity.this, added + " is the Correct Answer!", Toast.LENGTH_SHORT).show();
                        tts.speak("Incorrect", TextToSpeech.QUEUE_FLUSH, null, null);
                        Utilities.speakAns(added, tts);
                        tts.speak("is the Correct answer", TextToSpeech.QUEUE_ADD, null, null);
                    }
                    txt.setText("");
                    return true;
                }
                return false;
            }
        });
    }
            public void process() {
            num = Utilities.askQuestion(minNum, maxNum, tts);
            added = Utilities.add(num[0], num[1]);
            Utilities.focus(txt, getApplicationContext());
            submitAns();
            }
}

Utilities.java

import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

import java.util.Random;

public class Utilities {

    // Function to generate random numbers in range
    public static int randomGen(int minNum, int maxNum) {
        final Random randNum = new Random();
        return randNum.nextInt(maxNum - minNum) + minNum;
    }
    public static int add(int num1, int num2) {
        return num1 + num2;
    }
    public static int sub(int num1, int num2) {
        return num1 - num2;
    }

    // Speak individual numbers with operator in between speech
    public static void speakNums(int r1, int r2, TextToSpeech tts) {
        String toSpeak = Integer.toString(r1);
        String nexToSpeak = Integer.toString(r2);

        tts.speak(toSpeak, TextToSpeech.QUEUE_ADD, null, null);
        tts.speak("Plus", TextToSpeech.QUEUE_ADD, null, null);
        tts.speak(nexToSpeak, TextToSpeech.QUEUE_ADD, null, null);
    }

    // Speak answer
    public static void speakAns(int a, TextToSpeech tts) {
        String sumSpeak = Integer.toString(a);
        tts.speak(sumSpeak, TextToSpeech.QUEUE_ADD, null, null);
    }

    // Request focus so that keyboard pops up as generate button is tapped
    public static void focus(EditText txt, Context context) {
        txt.requestFocus();
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(txt, InputMethodManager.SHOW_IMPLICIT);
    }

    // Generate question, speak question, and return array of      random numbers for other operations
    public static int[] askQuestion(int minNum, int maxNum, TextToSpeech tts) {
       int r1 = randomGen(minNum, maxNum);
       int r2 = randomGen(minNum, maxNum);
       speakNums(r1, r2, tts);
       return new int[] { r1, r2};
    }
}

I am working on a program in java (android) I would like it to start and continue asking questions, upon button click, until the user is prompted for input, once input is received the program should resume asking the questions. The program should pause when the button is clicked again.

I am new to OOP and self taught. I thought that a thread was going to be the most practical way to solve the issue. I cannot get the program to both loop and allow user input. When trying to use HandlerThread I loose the ability to input data in the EditText. Could someone help with getting this loop to run on start click and loop after input?

I have a functional program that works when the button is cycled:

Main layout begins with "START" button, on click the start button turns to "PAUSE" and a seperate repeat button is made visible (and functional).

The values are generated, the question is asked, and the user is prompted by popping up the soft keyboard and setting the cursor in the EditText field.

Once an answer is received and the "enter/done" keyboard button is clicked, the answer will be evaluated against the saved values. But I cannot get the program to loop, or if I get it to loop it skips input completely and continues to as questions with no time for input.

Please direct me on code cleanliness if needed, I want to learn what I am doing incorrectly.

MAIN.java

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    // Create appropriate objects for buttons, edit text, and text to speech
    TextToSpeech tts;
    EditText txt;
    Button sbtn, rbtn;

    // Array and int to store numbers
    int[] num;
    int added = 0;

    // Boolean to check if questions is running
    public boolean isRunning;

    // Variables for random number range. TODO(Put into switch statement and list to select 1, 10, or 100s)
    static int maxNum = 100;
    static int minNum = 10;

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

        // Initializing buttons and others
        txt = findViewById(R.id.ans);
        sbtn = findViewById(R.id.strButton);
        rbtn = findViewById(R.id.rptButton);
        rbtn.setVisibility(View.INVISIBLE);

        // Initialize text to speech engine
        tts = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status != TextToSpeech.ERROR) {
                    tts.setLanguage(Locale.ENGLISH);
                }
            }
        });

        // Start button click listener
        sbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (!isRunning) {
                    // Show repeat button, hide start and show pause
                    rbtn.setVisibility(View.VISIBLE);
                    sbtn.setText("Pause");

                    process();

                    isRunning = true;

                } else {
                    sbtn.setText("Start");
                    rbtn.setVisibility(View.GONE);

                    isRunning = false;
                }
            }
        });

        // Repeat button click listener
        rbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // Repeat recently generated numbers
                Utilities.speakNums(num[0], num[1], tts);
            }
        });
    }

    public void onPause() {
        if (tts != null) {
            tts.stop();
            tts.shutdown();
        }
        super.onPause();
    }

    // Get input and compare with stored values, announce if user answer is correct or incorrect
    public void submitAns() {
        txt.setOnKeyListener(new View.OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // If the event is a key-down event on the "enter/done" button
                if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
                        (keyCode == KeyEvent.KEYCODE_ENTER)) {
                    // Check to make sure the text field is not empty
                    if (TextUtils.isEmpty(txt.getText().toString())) {
                        Toast.makeText(MainActivity.this, "Enter a Number!", Toast.LENGTH_SHORT).show();
                        return false;
                    }
                    int intValue = Integer.parseInt(txt.getText().toString());

                    if (added == intValue) {
                        Toast.makeText(MainActivity.this, "Correct", Toast.LENGTH_SHORT).show();
                        tts.speak("Correct", TextToSpeech.QUEUE_ADD, null, null);
                    } else {
                        Toast.makeText(MainActivity.this, added + " is the Correct Answer!", Toast.LENGTH_SHORT).show();
                        tts.speak("Incorrect", TextToSpeech.QUEUE_FLUSH, null, null);
                        Utilities.speakAns(added, tts);
                        tts.speak("is the Correct answer", TextToSpeech.QUEUE_ADD, null, null);
                    }
                    txt.setText("");
                    return true;
                }
                return false;
            }
        });
    }
            public void process() {
            num = Utilities.askQuestion(minNum, maxNum, tts);
            added = Utilities.add(num[0], num[1]);
            Utilities.focus(txt, getApplicationContext());
            submitAns();
            }
}

UTILITIES.java

import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

import java.util.Random;

public class Utilities {

    // Function to generate random numbers in range
    public static int randomGen(int minNum, int maxNum) {
        final Random randNum = new Random();
        return randNum.nextInt(maxNum - minNum) + minNum;
    }
    public static int add(int num1, int num2) {
        return num1 + num2;
    }
    public static int sub(int num1, int num2) {
        return num1 - num2;
    }

    // Speak individual numbers with operator in between speech
    public static void speakNums(int r1, int r2, TextToSpeech tts) {
        String toSpeak = Integer.toString(r1);
        String nexToSpeak = Integer.toString(r2);

        tts.speak(toSpeak, TextToSpeech.QUEUE_ADD, null, null);
        tts.speak("Plus", TextToSpeech.QUEUE_ADD, null, null);
        tts.speak(nexToSpeak, TextToSpeech.QUEUE_ADD, null, null);
    }

    // Speak answer
    public static void speakAns(int a, TextToSpeech tts) {
        String sumSpeak = Integer.toString(a);
        tts.speak(sumSpeak, TextToSpeech.QUEUE_ADD, null, null);
    }

    // Request focus so that keyboard pops up as generate button is tapped
    public static void focus(EditText txt, Context context) {
        txt.requestFocus();
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(txt, InputMethodManager.SHOW_IMPLICIT);
    }

    // Generate question, speak question, and return array of      random numbers for other operations
    public static int[] askQuestion(int minNum, int maxNum, TextToSpeech tts) {
       int r1 = randomGen(minNum, maxNum);
       int r2 = randomGen(minNum, maxNum);
       speakNums(r1, r2, tts);
       return new int[] { r1, r2};
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冷︶言冷语的世界 2025-02-17 12:39:44

如果您想进行一系列重复/无限的事件,这些事件涉及用户交互(例如回答问题),则应将其设置为一系列链式事件,而不是尝试使用实际的代码循环或处理程序线程。

如何设置此设置的一个示例是:

  1. 生成一个要显示的问题(例如“什么是12 + 54?”),
  2. 当用户完成答案时,请调用“提交”方法,以检查其答案并显示错误或生成一个新的问题要显示。
  3. 随意重复上述周期。为此,不需要循环或处理程序线。

架构a viewModel 将极大地帮助您,那么活动只能观察到相关状态在视图模型中(例如要显示什么问题)。

这是一个基于您提供的描述和示例代码的简单示例。有一个ViewModel可以处理创建问题,检查答案并前进到一个新问题,以及从ViewModel中观察相关状态的活动。在空白的应用程序项目中尝试一下,以了解其工作原理。

ViewModel

public class MainViewModel extends ViewModel {

    // Error string to observe - to show an error message or toast
    private final MutableLiveData<String> error = new MutableLiveData<>("");
    LiveData<String> getError() {
        return error;
    }

    // Current question to show
    private final MutableLiveData<String> question = new MutableLiveData<>("");
    LiveData<String> getQuestion() {
        return question;
    }

    // Text to show on the start/pause button
    private final MutableLiveData<String> startPauseButton = new MutableLiveData<>("START");
    LiveData<String> getStartPauseButton() {
        return startPauseButton;
    }

    // private internal state, e.g. current question,
    // expected answer, play/pause state
    private int expected = 0;
    private String current_question = "";
    private boolean playing = false;
    private final Random random = new Random();
    private final int minNum = 10;
    private final int maxNum = 100;

    private int getNumber() {
        return random.nextInt(maxNum - minNum) + minNum;
    }

    // Process a user's answer, and either show an error
    // message or generate a new question to show
    void submitAnswer(String ans) {
        try {
            int a = Integer.parseInt(ans);
            if( a == expected ) {
                generateNewQuestion();
                question.postValue(current_question);
            }
            else {
                error.postValue("Incorrect answer, try again");
            }
        }
        catch (NumberFormatException e) {
            error.postValue("Not a number - enter a number");
        }
    }

    private void generateNewQuestion() {
        int a = getNumber();
        int b = getNumber();
        expected = a + b;
        current_question = "What is " + a + " + " + b + "?";
    }

    void clearError() {
        error.postValue("");
    }

    // Called when the user clicks the play/pause button
    void clickStartPause() {
        playing = !playing;
        if( playing ) {
            startPauseButton.postValue("PAUSE");
            question.postValue(current_question);
        }
        else {
            startPauseButton.postValue("START");
            question.postValue("");
        }
    }

    public MainViewModel() {
        generateNewQuestion();
    }
}

活动

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

    TextView question = findViewById(R.id.question);
    EditText answer = findViewById(R.id.answer);
    Button start = findViewById(R.id.start);
    Button submit = findViewById(R.id.submit);

    question.setVisibility(View.GONE);
    answer.setVisibility(View.GONE);
    submit.setVisibility(View.GONE);

    MainViewModel model = new ViewModelProvider(this).get(MainViewModel.class);

    // Observe the current question, and if it is blank
    // hide the question/answer/submit views
    final Observer<String> questionObserver = questionTxt -> {
        if( questionTxt == null || questionTxt.isEmpty() ) {
            question.setVisibility(View.GONE);
            answer.setVisibility(View.GONE);
            submit.setVisibility(View.GONE);
        }
        else {
            question.setVisibility(View.VISIBLE);
            answer.setVisibility(View.VISIBLE);
            submit.setVisibility(View.VISIBLE);
            question.setText(questionTxt);
        }
    };

    // Observe the error state, if it is non-blank show
    // a toast then reset the state (so the toast only shows once)
    final Observer<String> errorObserver = errorText -> {
        if( errorText != null && !errorText.isEmpty() ) {
            Toast.makeText(this, errorText, Toast.LENGTH_LONG).show();
            model.clearError();
        }
    };

    model.getError().observe(this, errorObserver);
    model.getQuestion().observe(this, questionObserver);
    model.getStartPauseButton().observe(this, start::setText);

    submit.setOnClickListener(v -> {
        model.submitAnswer(answer.getText().toString());
        answer.setText("");
    });

    start.setOnClickListener(v -> model.clickStartPause());
}

xml

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/question"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <EditText
        android:id="@+id/answer"
        android:hint="Answer"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/question"
        android:layout_width="0dp"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/answer"/>

    <Button
        android:id="@+id/submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Submit"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/answer"/>

</androidx.constraintlayout.widget.ConstraintLayout>

If you want to have a repeating/infinite series of events that involve user interaction (like answering a question) you should set it up as a series of chained events rather than trying to use an actual code loop or handler thread.

An example of how this could be set up is:

  1. Generate a question to show (e.g. "What is 12 + 54?")
  2. When the user is done answering, call a "submit" method that checks their answer and either shows an error or generates a new question to show.
  3. Repeat the cycle above for as long as you want. No loops or handler threads are needed for this.

In terms of architecture, separating out as much of the question-generation and answer-processing logic into a ViewModel will help you tremendously, then the activity can just observe the relevant state in the view model (like what question to show).

Here is a simple example based on the description and example code you provided. There is a ViewModel that handles creating a question, checking the answer, and advancing to a new question, and an Activity that observes the relevant state from the ViewModel. Try it out in a blank app project to understand how it works.

ViewModel

public class MainViewModel extends ViewModel {

    // Error string to observe - to show an error message or toast
    private final MutableLiveData<String> error = new MutableLiveData<>("");
    LiveData<String> getError() {
        return error;
    }

    // Current question to show
    private final MutableLiveData<String> question = new MutableLiveData<>("");
    LiveData<String> getQuestion() {
        return question;
    }

    // Text to show on the start/pause button
    private final MutableLiveData<String> startPauseButton = new MutableLiveData<>("START");
    LiveData<String> getStartPauseButton() {
        return startPauseButton;
    }

    // private internal state, e.g. current question,
    // expected answer, play/pause state
    private int expected = 0;
    private String current_question = "";
    private boolean playing = false;
    private final Random random = new Random();
    private final int minNum = 10;
    private final int maxNum = 100;

    private int getNumber() {
        return random.nextInt(maxNum - minNum) + minNum;
    }

    // Process a user's answer, and either show an error
    // message or generate a new question to show
    void submitAnswer(String ans) {
        try {
            int a = Integer.parseInt(ans);
            if( a == expected ) {
                generateNewQuestion();
                question.postValue(current_question);
            }
            else {
                error.postValue("Incorrect answer, try again");
            }
        }
        catch (NumberFormatException e) {
            error.postValue("Not a number - enter a number");
        }
    }

    private void generateNewQuestion() {
        int a = getNumber();
        int b = getNumber();
        expected = a + b;
        current_question = "What is " + a + " + " + b + "?";
    }

    void clearError() {
        error.postValue("");
    }

    // Called when the user clicks the play/pause button
    void clickStartPause() {
        playing = !playing;
        if( playing ) {
            startPauseButton.postValue("PAUSE");
            question.postValue(current_question);
        }
        else {
            startPauseButton.postValue("START");
            question.postValue("");
        }
    }

    public MainViewModel() {
        generateNewQuestion();
    }
}

Activity

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

    TextView question = findViewById(R.id.question);
    EditText answer = findViewById(R.id.answer);
    Button start = findViewById(R.id.start);
    Button submit = findViewById(R.id.submit);

    question.setVisibility(View.GONE);
    answer.setVisibility(View.GONE);
    submit.setVisibility(View.GONE);

    MainViewModel model = new ViewModelProvider(this).get(MainViewModel.class);

    // Observe the current question, and if it is blank
    // hide the question/answer/submit views
    final Observer<String> questionObserver = questionTxt -> {
        if( questionTxt == null || questionTxt.isEmpty() ) {
            question.setVisibility(View.GONE);
            answer.setVisibility(View.GONE);
            submit.setVisibility(View.GONE);
        }
        else {
            question.setVisibility(View.VISIBLE);
            answer.setVisibility(View.VISIBLE);
            submit.setVisibility(View.VISIBLE);
            question.setText(questionTxt);
        }
    };

    // Observe the error state, if it is non-blank show
    // a toast then reset the state (so the toast only shows once)
    final Observer<String> errorObserver = errorText -> {
        if( errorText != null && !errorText.isEmpty() ) {
            Toast.makeText(this, errorText, Toast.LENGTH_LONG).show();
            model.clearError();
        }
    };

    model.getError().observe(this, errorObserver);
    model.getQuestion().observe(this, questionObserver);
    model.getStartPauseButton().observe(this, start::setText);

    submit.setOnClickListener(v -> {
        model.submitAnswer(answer.getText().toString());
        answer.setText("");
    });

    start.setOnClickListener(v -> model.clickStartPause());
}

XML

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/question"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <EditText
        android:id="@+id/answer"
        android:hint="Answer"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/question"
        android:layout_width="0dp"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/answer"/>

    <Button
        android:id="@+id/submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Submit"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/answer"/>

</androidx.constraintlayout.widget.ConstraintLayout>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文