安卓口算测试app


本文为学习类文档,通过学习B站up主longway777的视频,如有侵权,请联系博主进行删除

安卓口算测试app

为了将之前学过的ViewModel,Fragement,本地化,横竖屏设置等结合在一起,做一个安卓口算的app,可以用来给家里的小学生们做练习用,那么开始吧~

创建项目

  1. 创建Fragement分别显示标题,答题,输和赢的界面:在这里插入图片描述
  2. 在资源中创建navigation文件并添加依赖,完成后将fragement导入创建逻辑:在这里插入图片描述
    在这里插入图片描述
  3. 将网上下载的图片存到Drawable中,在使用系统自带的矢量图时需要添加对应的依赖在此不做赘述,并在Gradle中添加需要dataBinding和ViewModelProvider依赖并sync同步:
dependencies {
	...
    implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0'
}

android {
...
    defaultConfig {
	...
        dataBinding.enabled true
    }
...
}

  1. 做界面:
    fragement_title.xml
    在这里插入图片描述
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TitleFragment">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.1" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.9" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/title_message"
        android:textSize="@dimen/big_font"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/guideline2"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.15" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="50dp"
        android:layout_marginEnd="50dp"
        android:contentDescription="@string/title_image_info"
        android:src="@drawable/titleimage"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintEnd_toStartOf="@+id/guideline2"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/title_button_message"
        app:layout_constraintBottom_toBottomOf="@+id/imageView"
        app:layout_constraintEnd_toEndOf="@+id/imageView"
        app:layout_constraintStart_toStartOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.8" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/high_score_message"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.883"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        app:layout_constraintVertical_bias="0.049" />
</androidx.constraintlayout.widget.ConstraintLayout>

fragement_question.xml:在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".QuestionFragment">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.1" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/current_score"
        app:layout_constraintBottom_toTopOf="@+id/guideline3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline3" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.2" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.32" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.4" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.8" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline12"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.7" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline13"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.6" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline14"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.1" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.9" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/huge_font"
        app:layout_constraintBottom_toBottomOf="@+id/textView5"
        app:layout_constraintEnd_toStartOf="@+id/textView5"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/guideline9"
        app:layout_constraintTop_toTopOf="@+id/textView5"
        tools:text="8" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/huge_font"
        app:layout_constraintBottom_toBottomOf="@+id/textView6"
        app:layout_constraintEnd_toStartOf="@+id/textView6"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/textView4"
        app:layout_constraintTop_toTopOf="@+id/textView6"
        tools:text="+" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/huge_font"
        app:layout_constraintBottom_toBottomOf="@+id/textView7"
        app:layout_constraintEnd_toStartOf="@+id/textView7"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/textView5"
        app:layout_constraintTop_toTopOf="@+id/textView7"
        tools:text="9" />

    <TextView
        android:id="@+id/textView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/equal_symbol"
        android:textSize="@dimen/huge_font"
        app:layout_constraintBottom_toBottomOf="@+id/textView8"
        app:layout_constraintEnd_toStartOf="@+id/textView8"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/textView6"
        app:layout_constraintTop_toTopOf="@+id/textView8"
        tools:text="=" />

    <TextView
        android:id="@+id/textView8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/question_mark"
        android:textSize="@dimen/huge_font"
        app:layout_constraintBottom_toTopOf="@+id/guideline4"
        app:layout_constraintEnd_toStartOf="@+id/guideline10"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/textView7"
        app:layout_constraintTop_toTopOf="@+id/guideline4"
        tools:text="\?" />

    <TextView
        android:id="@+id/textView9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/input_indicator"
        android:textSize="@dimen/mid_font"
        app:layout_constraintBottom_toTopOf="@+id/guideline5"
        app:layout_constraintEnd_toStartOf="@+id/guideline10"
        app:layout_constraintStart_toStartOf="@+id/guideline9"
        app:layout_constraintTop_toTopOf="@+id/guideline5" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button1"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toTopOf="@+id/guideline14"
        app:layout_constraintEnd_toStartOf="@+id/button2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/guideline9"
        app:layout_constraintTop_toTopOf="@+id/guideline6" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button2"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/button1"
        app:layout_constraintEnd_toStartOf="@+id/button3"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button1"
        app:layout_constraintTop_toTopOf="@+id/button1" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button3"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/button2"
        app:layout_constraintEnd_toStartOf="@+id/guideline10"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button2"
        app:layout_constraintTop_toTopOf="@+id/button2"
        app:layout_constraintVertical_bias="0.0" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button4"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toTopOf="@+id/guideline13"
        app:layout_constraintEnd_toStartOf="@+id/button5"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/guideline9"
        app:layout_constraintTop_toTopOf="@+id/guideline14" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button5"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/button4"
        app:layout_constraintEnd_toStartOf="@+id/button6"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button4"
        app:layout_constraintTop_toTopOf="@+id/button4" />

    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button6"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/button5"
        app:layout_constraintEnd_toStartOf="@+id/guideline10"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button5"
        app:layout_constraintTop_toTopOf="@+id/button5" />

    <Button
        android:id="@+id/button7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button7"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toTopOf="@+id/guideline12"
        app:layout_constraintEnd_toStartOf="@+id/button8"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/guideline9"
        app:layout_constraintTop_toTopOf="@+id/guideline13" />

    <Button
        android:id="@+id/button8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button8"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/button7"
        app:layout_constraintEnd_toStartOf="@+id/button9"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button7"
        app:layout_constraintTop_toTopOf="@+id/button7" />

    <Button
        android:id="@+id/button9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button9"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/button8"
        app:layout_constraintEnd_toStartOf="@+id/guideline10"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button8"
        app:layout_constraintTop_toTopOf="@+id/button8" />

    <Button
        android:id="@+id/buttonClear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/buttonClear"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toTopOf="@+id/guideline7"
        app:layout_constraintEnd_toStartOf="@+id/button0"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/guideline9"
        app:layout_constraintTop_toTopOf="@+id/guideline12" />

    <Button
        android:id="@+id/button0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button0"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/buttonClear"
        app:layout_constraintEnd_toStartOf="@+id/buttonSubmit"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/buttonClear"
        app:layout_constraintTop_toTopOf="@+id/buttonClear" />

    <Button
        android:id="@+id/buttonSubmit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/buttonSubmit"
        android:textSize="@dimen/button_font"
        app:layout_constraintBottom_toBottomOf="@+id/button0"
        app:layout_constraintEnd_toStartOf="@+id/guideline10"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button0"
        app:layout_constraintTop_toTopOf="@+id/button0" />
</androidx.constraintlayout.widget.ConstraintLayout>

fragment_lose.xml:在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LoseFragment">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.1" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.45" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:contentDescription="@string/lose_image_message"
        android:src="@drawable/ic_sentiment_dissatisfied_black_24dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline11"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline8" />

    <TextView
        android:id="@+id/textView10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/lose_message"
        android:textSize="@dimen/big_font"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline11"
        app:layout_constraintVertical_bias="0.1" />

    <TextView
        android:id="@+id/textView12"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/lose_score_message"
        android:textSize="@dimen/big_font"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline11"
        app:layout_constraintVertical_bias="0.3" />

    <Button
        android:id="@+id/button10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_back_to_title"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView2" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_win.xml:在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WinFragment">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline15"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.1" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline16"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.45" />

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:contentDescription="@string/win_image_messgae"
        android:src="@drawable/ic_sentiment_satisfied_black_24dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline16"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline15" />

    <TextView
        android:id="@+id/textView11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/win_message"
        android:textSize="@dimen/big_font"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView3"
        app:layout_constraintVertical_bias="0.1" />

    <TextView
        android:id="@+id/textView13"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/win_score_message"
        android:textSize="@dimen/big_font"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView3"
        app:layout_constraintVertical_bias="0.3" />

    <Button
        android:id="@+id/button11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_back_to_title"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView3" />
</androidx.constraintlayout.widget.ConstraintLayout>
  1. 将fragement链接到activity中:在这里插入图片描述
  2. ViewModel类中做数据的操作:
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.SavedStateHandle;

import java.util.Random;

@SuppressWarnings("ConstantConditions")
public class MyViewModel extends AndroidViewModel {
    private SavedStateHandle handle;
    private static String KEY_HIGE_SCORE = "key_high_score";
    private static String KEY_LEFT_NUMBER = "key_left_number";
    private static String KEY_RIGHT_NUMBER = "key_right_number";
    private static String KEY_OPERATOR = "key_operator";
    private static String KEY_ANSWER = "key_answer";
    private static String SAVE_SHP_DATA_MANE = "save_shp_data_name";
    private static String KEY_CURRENT_SCORE = "key_current_score";
    boolean win_flag = false;

    public MyViewModel(@NonNull Application application, SavedStateHandle handle) { //使用了savedstatehandle
        super(application);
        //管理的数据有:最高纪录存放之sharedpreferences,题目数字及运算符和答案,当前得分。
        if (!handle.contains(KEY_HIGE_SCORE)){
            SharedPreferences sharedPreferences = getApplication().getSharedPreferences(SAVE_SHP_DATA_MANE, Context.MODE_PRIVATE);
            handle.set(KEY_HIGE_SCORE,sharedPreferences.getInt(KEY_HIGE_SCORE,0));
            handle.set(KEY_LEFT_NUMBER,0);
            handle.set(KEY_RIGHT_NUMBER,0);
            handle.set(KEY_OPERATOR,"+");
            handle.set(KEY_ANSWER,0);
            handle.set(KEY_CURRENT_SCORE,0);
        }
        this.handle = handle;
    }
    MutableLiveData<Integer>getLeftNumber(){
        return handle.getLiveData(KEY_LEFT_NUMBER);
    }
    MutableLiveData<Integer>getRightNumber(){
        return handle.getLiveData(KEY_RIGHT_NUMBER);
    }
    MutableLiveData<String>getOperator(){
        return handle.getLiveData(KEY_OPERATOR);
    }
    MutableLiveData<Integer>getHignScore(){
        return handle.getLiveData(KEY_HIGE_SCORE);
    }
    MutableLiveData<Integer>getCurrentScore(){
        return handle.getLiveData(KEY_CURRENT_SCORE);
    }
    MutableLiveData<Integer>getAnswer(){
        return handle.getLiveData(KEY_ANSWER);
    }

    //创建题目
    void generator(){
        int LEVEL_NUMBER = 21;
        Random random = new Random();
        int x,y;
        x = random.nextInt(LEVEL_NUMBER) + 1; //出现的随机数为0到LEVEL_NUMBER-1;为防止负数出现,需要加1
        y = random.nextInt(LEVEL_NUMBER) + 1;
        if (x%2 == 0){  //对2取余为0,使得加减法各占一半
            getOperator().setValue("+");
            //做处理防止超出学生难度范围,做大数作为来当加法的结果
            if (x > y){  //x若为大数,x做结果,y做"+"前面的数,差值做“+”后面的数
                getAnswer().setValue(x);
                getLeftNumber().setValue(y);
                getRightNumber().setValue(x - y);
            }else {
                getAnswer().setValue(y);
                getLeftNumber().setValue(x);
                getRightNumber().setValue(y - x);
            }
        }else {
            getOperator().setValue("-");
            if (x > y){
                getAnswer().setValue(x - y);
                getLeftNumber().setValue(x);
                getRightNumber().setValue(y);
            }else {
                getAnswer().setValue(y - x);
                getLeftNumber().setValue(y);
                getRightNumber().setValue(x);
            }
        }
    }

    //保存
    void save() {
        SharedPreferences sharedPreferences = getApplication().getSharedPreferences(SAVE_SHP_DATA_MANE,Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putInt(KEY_HIGE_SCORE,getHignScore().getValue());
        editor.apply();
    }

    //根据答题情况区别对待
    void answerCorrect(){
        getCurrentScore().setValue(getCurrentScore().getValue() + 1);
        if (getCurrentScore().getValue() > getHignScore().getValue()){
            getHignScore().setValue(getCurrentScore().getValue());//刷新最高分
            win_flag = true;
        }
        generator();
    }
}
  1. 对界面数据绑定,转换databinding layout并绑定数据
    (1) 标题界面的数据绑定——右上角的最高纪录:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <variable
            name="data"
            type="com.example.calculationtest.MyViewModel" />
    </data>
...

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/high_score_message(data.hignScore)}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.883"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/imageView"
            app:layout_constraintVertical_bias="0.049"
            tools:text="@string/high_score_message" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

(2) 答题界面的数据绑定——当前得分、出题数字与运算符:

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <variable
            name="data"
            type="com.example.calculationtest.MyViewModel" />
    </data>
...
        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/current_score(data.currentScore)}"
            app:layout_constraintBottom_toTopOf="@+id/guideline3"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline3"
            tools:text="Score:3" />
...

        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/huge_font"
            android:text="@{String.valueOf(data.leftNumber)}"
            app:layout_constraintBottom_toBottomOf="@+id/textView5"
            app:layout_constraintEnd_toStartOf="@+id/textView5"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="@+id/guideline9"
            app:layout_constraintTop_toTopOf="@+id/textView5"
            tools:text="8" />

        <TextView
            android:id="@+id/textView5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/huge_font"
            android:text="@{data.operator}"
            app:layout_constraintBottom_toBottomOf="@+id/textView6"
            app:layout_constraintEnd_toStartOf="@+id/textView6"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/textView4"
            app:layout_constraintTop_toTopOf="@+id/textView6"
            tools:text="+" />

        <TextView
            android:id="@+id/textView6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/huge_font"
            android:text="@{String.valueOf(data.rightNumber)}"
            app:layout_constraintBottom_toBottomOf="@+id/textView7"
            app:layout_constraintEnd_toStartOf="@+id/textView7"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/textView5"
            app:layout_constraintTop_toTopOf="@+id/textView7"
            tools:text="9" />
...
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

(3) 挑战成功创造新纪录的界面——新纪录高分:

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <variable
            name="data"
            type="com.example.calculationtest.MyViewModel" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".WinFragment">
...

        <TextView
            android:id="@+id/textView13"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/win_score_message(data.hignScore)}"
            android:textSize="@dimen/big_font"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView3"
            app:layout_constraintVertical_bias="0.3"
            tools:text="New Record:" />
...
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

(4) 挑战失败没有创造新纪录显示本次得分:

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <variable
            name="data"
            type="com.example.calculationtest.MyViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".LoseFragment">
...

        <TextView
            android:id="@+id/textView12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/lose_score_message(data.currentScore)}"
            android:textSize="@dimen/big_font"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline11"
            app:layout_constraintVertical_bias="0.3"
            tools:text="Your Score" />
...
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
  1. 编写Fragement中的代码(每个Fragement中都需要写绑定):
    标题fragement:
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.calculationtest.databinding.FragmentTitleBinding;
...
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container,
                             Bundle savedInstanceState) {
        MyViewModel myViewModel;
        myViewModel = new ViewModelProvider(requireActivity(), new SavedStateViewModelFactory(requireActivity()
                .getApplication(), this)).get(MyViewModel.class); //新版大长式子恶心人 TvT ~~~
        FragmentTitleBinding binding;
        binding = DataBindingUtil.inflate(inflater,R.layout.fragment_title,container,false);
        binding.setData(myViewModel);
        binding.setLifecycleOwner(requireActivity());
        binding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NavController controller = Navigation.findNavController(v);
                controller.navigate(R.id.action_titleFragment_to_questionFragment);
            }
        });
        return binding.getRoot();  //返回值为View类型
    }
}

答题界面:

import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.calculationtest.databinding.FragmentQuestionBinding;
...
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final MyViewModel myViewModel;
        myViewModel = new ViewModelProvider(requireActivity(), new SavedStateViewModelFactory(requireActivity()
                .getApplication(), this)).get(MyViewModel.class);
        myViewModel.generator();
        myViewModel.getCurrentScore().setValue(0);
        final FragmentQuestionBinding binding;
        binding = DataBindingUtil.inflate(inflater,R.layout.fragment_question,container,false);
        binding.setData(myViewModel);
        binding.setLifecycleOwner(requireActivity());
        //借用stringbuilder来处理用户输入的数据
        final StringBuilder builder = new StringBuilder();
        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switch (v.getId()){
                    case R.id.button0:
                        builder.append(0);
                        break;
                    case R.id.button1:
                        builder.append(1);
                        break;
                    case R.id.button2:
                        builder.append(2);
                        break;
                    case R.id.button3:
                        builder.append(3);
                        break;
                    case R.id.button4:
                        builder.append(4);
                        break;
                    case R.id.button5:
                        builder.append(5);
                        break;
                    case R.id.button6:
                        builder.append(6);
                        break;
                    case R.id.button7:
                        builder.append(7);
                        break;
                    case R.id.button8:
                        builder.append(8);
                        break;
                    case R.id.button9:
                        builder.append(9);
                        break;
                    case R.id.buttonClear:
                        builder.setLength(0);
                        //或者builder =  new StringBuilder();
                        break;
                }
            if (builder.length() == 0){
                binding.textView9.setText(R.string.input_indicator);
            }else {
                binding.textView9.setText(builder.toString());
            }
            }
        };

        binding.button0.setOnClickListener(listener);
        binding.button1.setOnClickListener(listener);
        binding.button2.setOnClickListener(listener);
        binding.button3.setOnClickListener(listener);
        binding.button4.setOnClickListener(listener);
        binding.button5.setOnClickListener(listener);
        binding.button6.setOnClickListener(listener);
        binding.button7.setOnClickListener(listener);
        binding.button8.setOnClickListener(listener);
        binding.button9.setOnClickListener(listener);
        binding.buttonClear.setOnClickListener(listener);

        binding.buttonSubmit.setOnClickListener(new View.OnClickListener() {
            @SuppressWarnings("ConstantConditions")
            @Override
            public void onClick(View v) {
              if (builder.length() == 0) {
                    builder.append("-1"); //当前加减法算式中不可能有负数答案,因此设为-1,来作为不输入直接确定的错误答案
                }
                if (Integer.valueOf(builder.toString()).intValue() == myViewModel.getAnswer().getValue()){ //转换为简单int型作比较,如果什么都不输入会返回空值,需要在此之前做拦截
                    myViewModel.answerCorrect();
                    builder.setLength(0);
                    binding.textView9.setText(R.string.answer_correct_message);
                    //builder.append(getString(R.string.answer_correct_message));
                }else {
                    NavController controller = Navigation.findNavController(v);
                    if (myViewModel.win_flag){
                        controller.navigate(R.id.action_questionFragment_to_winFragment);
                        myViewModel.win_flag = false;
                        myViewModel.save();
                    }else {
                        controller.navigate(R.id.action_questionFragment_to_loseFragment);
                    }
                }
            }
        });
        return binding.getRoot();
    }
}

创造新纪录界面:

import android.os.Bundle;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.calculationtest.databinding.FragmentWinBinding;
...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        MyViewModel myViewModel = new ViewModelProvider(requireActivity(),new SavedStateViewModelFactory(requireActivity()
                .getApplication(),this)).get(MyViewModel.class);
        FragmentWinBinding binding;
        binding = DataBindingUtil.inflate(inflater,R.layout.fragment_win, container, false);
        binding.setData(myViewModel);
        binding.setLifecycleOwner(requireActivity());

        binding.button11.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(v).navigate(R.id.action_winFragment_to_titleFragment);
            }
        });
        return binding.getRoot();
    }
}

挑战失败当前得分界面:

import android.os.Bundle;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.calculationtest.databinding.FragmentLoseBinding;
...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        MyViewModel myViewModel = new ViewModelProvider(requireActivity(),new SavedStateViewModelFactory(requireActivity()
                .getApplication(),this)).get(MyViewModel.class);
        final FragmentLoseBinding binding;
        binding = DataBindingUtil.inflate(inflater,R.layout.fragment_lose, container, false);
        binding.setData(myViewModel);
        binding.setLifecycleOwner(requireActivity());

        binding.button10.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(v).navigate(R.id.action_loseFragment_to_titleFragment);
            }
        });
        return binding.getRoot();
    }
}
  1. 完善ActionBar实现误操作提示——界面人性化返回:在MainActivity中填写代码
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;
import android.content.DialogInterface;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    NavController controller;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //左上角的返回按键
        controller = Navigation.findNavController(this,R.id.fragment);
        NavigationUI.setupActionBarWithNavController(this,controller);
    }

    @Override //响应返回按键实现询问是否返回?
    public boolean onSupportNavigateUp() {
        if (controller.getCurrentDestination().getId() == R.id.questionFragment){  //答题界面实现询问返回
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(getString(R.string.quit_dialog_title));
            builder.setPositiveButton(R.string.dialog_positive_message, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    controller.navigateUp();
                }
            });
            builder.setNegativeButton(R.string.dialog_negative_message, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                }
            });
            AlertDialog dialog = builder.create(); //创建对话框并显示
            dialog.show();
        }else if (controller.getCurrentDestination().getId() == R.id.titleFragment) {  //标题界面实现退出程序
            finish();
        }
        else {  //其他界面(输赢界面)实现跳转到标题界面
            controller.navigate(R.id.titleFragment);
        }
        return super.onSupportNavigateUp();
    }

    @Override  //设备自带返回按键做处理,继承上面的即可
    public void onBackPressed() {
        onSupportNavigateUp();
        //super.onBackPressed();
    }
}
  1. String.xml实现汉化:此处也附上当前使用的dimens
    dimens.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="huge_font">60sp</dimen>
    <dimen name="big_font">40sp</dimen>
    <dimen name="mid_font">30sp</dimen>
    <dimen name="button_font">20sp</dimen>
</resources>

strings.xml

<resources>
    <string name="app_name">CalculationTest</string>
    <!-- TODO: Remove or change this placeholder text -->
    <string name="hello_blank_fragment" translatable="false">Hello blank fragment</string>
    <string name="title_message">Calculation Test</string>
    <string name="title_image_info" translatable="false">title_image</string>
    <string name="title_button_message">Enter</string>
    <string name="high_score_message">High Score: %d</string>
    <string name="button0" translatable="false">0</string>
    <string name="button1" translatable="false">1</string>
    <string name="button2" translatable="false">2</string>
    <string name="button3" translatable="false">3</string>
    <string name="button4" translatable="false">4</string>
    <string name="button5" translatable="false">5</string>
    <string name="button6" translatable="false">6</string>
    <string name="button7" translatable="false">7</string>
    <string name="button8" translatable="false">8</string>
    <string name="button9" translatable="false">9</string>
    <string name="buttonClear">C</string>
    <string name="buttonSubmit">OK</string>
    <string name="equal_symbol" translatable="false">=</string>
    <string name="question_mark" translatable="false">\?</string>
    <string name="current_score">Score:%d</string>
    <string name="input_indicator">Your answer</string>
    <string name="lose_image_message" translatable="false">lose image</string>
    <string name="win_image_messgae" translatable="false">win message</string>
    <string name="lose_message">You Lose!</string>
    <string name="win_message">You Win!!!</string>
    <string name="lose_score_message">Your Score:%d</string>
    <string name="win_score_message">New Record:%d</string>
    <string name="button_back_to_title">Back</string>
    <string name="answer_correct_message">Correct!Go on!</string>
    <string name="quit_dialog_title">Are you sure to quit?</string>
    <string name="dialog_positive_message">OK</string>
    <string name="dialog_negative_message">Cancle</string>
    
</resources>

在string页面点击右上角的open editor,寻找中文并选择,在多出来的文本框中填写与英文对应的中文,阿拉伯数字与运算符可以设置为唯一:
openeditor
中文
string.xml(zh-rCN)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">口算测试</string>
    <string name="answer_correct_message">回答正确!请继续!</string>
    <string name="buttonClear">清除</string>
    <string name="buttonSubmit">确定</string>
    <string name="button_back_to_title">返回</string>
    <string name="current_score">得分:%d</string>
    <string name="dialog_negative_message">取消</string>
    <string name="dialog_positive_message">确定</string>
    <string name="high_score_message">最高记录:%d</string>
    <string name="input_indicator">请开始答题</string>
    <string name="lose_message">挑战失败!</string>
    <string name="lose_score_message">你的得分:%d</string>
    <string name="quit_dialog_title">确定退出吗?</string>
    <string name="title_button_message">开始挑战</string>
    <string name="title_message">口算测试</string>
    <string name="win_message">挑战成功!!!</string>
    <string name="win_score_message">新纪录:%d</string>
</resources>
  1. fragement名称更改:在导航图中的图形化界面中选中对应的fragement的label进行更改,也可以创建资源进行系统化管理
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav"
    app:startDestination="@id/titleFragment">

    <fragment
        android:id="@+id/titleFragment"
        android:name="com.example.calculationtest.TitleFragment"
        android:label="@string/title_nav_message"
        tools:layout="@layout/fragment_title" >
        <action
            android:id="@+id/action_titleFragment_to_questionFragment"
            app:destination="@id/questionFragment" />
    </fragment>
    <fragment
        android:id="@+id/questionFragment"
        android:name="com.example.calculationtest.QuestionFragment"
        android:label="@string/question_nav_message"
        tools:layout="@layout/fragment_question" >
        <action
            android:id="@+id/action_questionFragment_to_winFragment"
            app:destination="@id/winFragment" />
        <action
            android:id="@+id/action_questionFragment_to_loseFragment"
            app:destination="@id/loseFragment" />
    </fragment>
    <fragment
        android:id="@+id/winFragment"
        android:name="com.example.calculationtest.WinFragment"
        android:label="@string/win_nav_message"
        tools:layout="@layout/fragment_win" >
        <action
            android:id="@+id/action_winFragment_to_titleFragment"
            app:destination="@id/titleFragment" />
    </fragment>
    <fragment
        android:id="@+id/loseFragment"
        android:name="com.example.calculationtest.LoseFragment"
        android:label="@string/lose_nav_message"
        tools:layout="@layout/fragment_lose" >
        <action
            android:id="@+id/action_loseFragment_to_titleFragment"
            app:destination="@id/titleFragment" />
    </fragment>
</navigation>

运行程序

各个界面测试如下:
标题界面:
在这里插入图片描述
答题界面:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
挑战成功界面:
在这里插入图片描述
挑战失败界面:
在这里插入图片描述

横屏处理

当前如果横屏的话:在这里插入图片描述
界面全部被打乱,不是我们想要的结果,因此需要设置横屏布局(如果强制不允许横屏处理需要在AndroidManifest.xml配置文件中设置相对应的Activity就可以):

<application
...
android:screenOrientation="portrait"
...
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

对每一个页面做单独的横板副本(根据需求做即可,此处不做代码的粘贴):
创建横屏副本

结束

目前还有一个小bug的问题就是在横竖屏切换的时候,问答界面中的算式会因为重新构建界面而刷新界面,因此界面上的式子也会因此而变动。

发布了18 篇原创文章 · 获赞 1 · 访问量 330

猜你喜欢

转载自blog.csdn.net/qq_40509784/article/details/105389016
今日推荐