android------口算测试APP

得意犹堪夸世俗,诏黄新湿字如鸦。这篇文章主要讲述android------口算测试APP相关的知识,希望能为你提供帮助。
昨天一直在写一个测试口算的简单APP,但不知道怎么回事,算出题目的答案和存入的答案不一样,一直找,也没找到。导致昨天的博客没发,今天早上起来继续找,通过控制台发现题目给出的数字和控制台打印的数不一样,回过头看到界面,发现Textview太小,导致数字溢出。哎!!!!
思想:首先就是需要四个fragment,一个首页,一个出题的,一个胜利,一个失败。打开app,进入首页,点击进入,进入到出题界面,然后答题,如果答题正确个数超过之前的记录,直到答错,回到胜利界面,然后点击返回就回到首页,如果答题正确个数没有超过之前的记录,则失败,回到失败界面,点击返回会到首页。自己的最高记录一直会在首页出现。
首先我们想创建四个fragment(bank),(之前的文章有提过,不再说),然后在res创建一个类型为Navigation的文件夹,在生成的xml文件中将四个fragment按照跳转顺序连接起来,如下
   

android------口算测试APP

文章图片

 
 
  记住,最先来进来的是起始的fragmen,当然也可以改变。
然后我们在绘制各个页面。
TitleFragment:QuestionFragment:
android------口算测试APP

文章图片
android------口算测试APP

文章图片

 
 
 
 
WinFragment:LoseFragment:
 
android------口算测试APP

文章图片
android------口算测试APP

文章图片

 
 

 
界面自己构造,关键是构造想法和各个组件的id。
 
然后在activity_main.xml,将NavHostFragment拖入到ConstraintLayout里
android------口算测试APP

文章图片

 
 
要保存数据,所以要新建一个ViewModel,因为要用LiveData,所以我们要在图像的xml文件里转换成liveData模式。
 
以下为代码:
 
MyViewModel(继承androidViewModel)
package com.example.calculationtest; 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; public class MyViewModel extends AndroidViewModel { private SavedStateHandle handle; private static String KEY_HIGH_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_NAME = "save_shp_data_name"; // SharedPreferences 名字 private static String KEY_CURRENT_SCORE = "key_current_score"; // 当前分数 public boolean win_flag = false; public MyViewModel(@NonNull Application application, SavedStateHandle handle) { super(application); if (!handle.contains(KEY_HIGH_SCORE)) { SharedPreferences preferences = getApplication().getSharedPreferences(SAVE_SHP_DATA_NAME, Context.MODE_PRIVATE); // 第一次访问:初始化 handle.set(KEY_HIGH_SCORE, preferences.getInt(KEY_HIGH_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; }// 获取各个值 public MutableLiveData< Integer> getHighScore() { return handle.getLiveData(KEY_HIGH_SCORE); }public MutableLiveData< Integer> getLeftNumber() { return handle.getLiveData(KEY_LEFT_NUMBER); }public MutableLiveData< Integer> getRightNumber() { return handle.getLiveData(KEY_RIGHT_NUMBER); }public MutableLiveData< String> getOperator() { return handle.getLiveData(KEY_OPERATOR); }public MutableLiveData< Integer> getSaveName() { return handle.getLiveData(SAVE_SHP_DATA_NAME); }public MutableLiveData< Integer> getCurrentScore() { return handle.getLiveData(KEY_CURRENT_SCORE); }public MutableLiveData< Integer> getAnswer() { return handle.getLiveData(KEY_ANSWER); }// 产生式子 public void generator() { int LEVEL = 20, LEVEL2 = 2; int x, y; Random random = new Random(); // 产生随机数 //random.nextInt(LEVEL)产生0-LEVEL-1范围的随机数 x = random.nextInt(LEVEL) + 1; y = random.nextInt(LEVEL) + 1; if (x%2 == 0) { // + getOperator().setValue("+"); getLeftNumber().setValue(x); getRightNumber().setValue(y); getAnswer().setValue(x + y); } else {//- getOperator().setValue("-"); if (x > y) { getLeftNumber().setValue(x); getRightNumber().setValue(y); getAnswer().setValue(x - y); } else { getLeftNumber().setValue(y); getRightNumber().setValue(x); getAnswer().setValue(y - x); } } }//保留最高记录 public void save(){ SharedPreferences preferences = getApplication().getSharedPreferences(SAVE_SHP_DATA_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); // 保存最高记录 editor.putInt(KEY_HIGH_SCORE, getHighScore().getValue()); // 提交 editor.apply(); } // 回答正确 public void answerCorrect(){ // 当前分数+1 getCurrentScore().setValue(getCurrentScore().getValue()+1); // 如果当前的分数大于之前的最高立即,那么改变 if(getCurrentScore().getValue()> getHighScore().getValue()){ getHighScore().setValue(getCurrentScore().getValue()); win_flag = true; } // 回答正确,继续出题 generator(); } // 因为回答错误之间跳转到起始界面,所以这就不再写 }

 
 
 
 
TitleFragment.java
package com.example.calculationtest; import android.os.Bundle; import androidx.databinding.DataBindingUtil; import androidx.fragment.app.Fragment; import androidx.lifecycle.SavedStateViewModelFactory; import androidx.lifecycle.ViewModelProviders; 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.FragmentTitleFragment2Binding; /** * A simple {@link Fragment} subclass. */ public class TitleFragment extends Fragment {public TitleFragment() { // Required empty public constructor }@Override public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) { MyViewModel myViewModel; myViewModel= ViewModelProviders.of(requireActivity(),new SavedStateViewModelFactory(getActivity().getApplication(), this)).get(MyViewModel.class); FragmentTitleFragment2Binding binding; binding = DataBindingUtil.inflate(inflater,R.layout.fragment_title_fragment2, container, false); binding.setData(myViewModel); binding.setLifecycleOwner(requireActivity()); binding.button11.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 转换到问题界面 NavController controller = Navigation.findNavController(v); controller.navigate(R.id.action_titleFragment2_to_questionFragment); } }); return binding.getRoot(); // Inflate the layout for this fragment //return inflater.inflate(R.layout.fragment_title_fragment2, container, false); }}

 
TitleFragment.xml
< ?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=".TitleFragment"> < androidx.constraintlayout.widget.Guideline android:id="@+id/guideline27" 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/guideline28" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.9" /> < androidx.constraintlayout.widget.Guideline android:id="@+id/guideline29" 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/guideline30" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.25" /> < androidx.constraintlayout.widget.Guideline android:id="@+id/guideline31" 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/guideline32" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.85" /> < TextView android:id="@+id/textView16" android:layout_width="0dp" android:layout_height="40dp" android:layout_marginEnd="12dp" android:text="@{@string/best_grade(data.highScore)}" android:textSize="20sp" app:layout_constraintBottom_toTopOf="@+id/guideline29" app:layout_constraintEnd_toStartOf="@+id/guideline28" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.564" tools:text="@string/best_grade" /> < TextView android:id="@+id/textView17" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/app_name" android:textSize="@dimen/big_font" app:layout_constraintBottom_toTopOf="@+id/guideline30" app:layout_constraintEnd_toStartOf="@+id/guideline28" app:layout_constraintStart_toStartOf="@+id/guideline27" app:layout_constraintTop_toTopOf="@+id/guideline29" /> < ImageView android:id="@+id/imageView5" android:layout_width="289dp" android:layout_height="417dp" android:contentDescription="@string/Image_view" android:src="https://www.songbingjia.com/android/@drawable/calculation" app:layout_constraintBottom_toTopOf="@+id/guideline31" app:layout_constraintEnd_toStartOf="@+id/guideline28" app:layout_constraintStart_toStartOf="@+id/guideline27" app:layout_constraintTop_toTopOf="@+id/guideline30" /> < Button android:id="@+id/button11" android:layout_width="0dp" android:layout_height="wrap_content" android:text="@string/button_name" android:textSize="18sp" app:layout_constraintBottom_toTopOf="@+id/guideline32" app:layout_constraintEnd_toStartOf="@+id/guideline28" app:layout_constraintStart_toStartOf="@+id/guideline27" app:layout_constraintTop_toTopOf="@+id/guideline31" /> < /androidx.constraintlayout.widget.ConstraintLayout> < /layout>

 
QuestionFragment.java:
package com.example.calculationtest; import android.os.Bundle; import androidx.databinding.DataBindingUtil; import androidx.fragment.app.Fragment; import androidx.lifecycle.SavedStateViewModelFactory; import androidx.lifecycle.ViewModelProviders; import androidx.navigation.NavController; import androidx.navigation.Navigation; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.example.calculationtest.databinding.FragmentQuestionBinding; /** * A simple {@link Fragment} subclass. */ public class QuestionFragment extends Fragment {public QuestionFragment() { // Required empty public constructor }@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final MyViewModel myViewModel; myViewModel= ViewModelProviders.of(requireActivity(),new SavedStateViewModelFactory(getActivity().getApplication(), this)).get(MyViewModel.class); // 出题 myViewModel.generator(); final FragmentQuestionBinding binding; binding = DataBindingUtil.inflate(inflater,R.layout.fragment_question,container, false); binding.setData(myViewModel); binding.setLifecycleOwner(requireActivity()); 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.buttonc: builder.setLength(0); break; } if(builder.length()==0){ binding.textView10.setText(getString(R.string.Answer)); }else{ binding.textView10.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.buttonc.setOnClickListener(listener); binding.buttonOk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 整型和String不能比较,得转换if(Integer.valueOf(builder.toString()).intValue() == myViewModel.getAnswer().getValue()){ myViewModel.answerCorrect(); builder.setLength(0); binding.textView10.setText(getString(R.string.answer_correct_message)); }else{// 回答错误 // 胜利 NavController controller = Navigation.findNavController(v); if(myViewModel.win_flag){ controller.navigate(R.id.action_questionFragment_to_winFragment1); // 防止以后一直胜利 myViewModel.win_flag = false; // 创造新纪录,保存 myViewModel.save(); }else{ // 失败 controller.navigate(R.id.action_questionFragment_to_loseFragment1); } } } }); return binding.getRoot(); // Inflate the layout for this fragment //return inflater.inflate(R.layout.fragment_question, container, false); }}

QuestionFragment.xml
【android------口算测试APP】
< ?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=".QuestionFragment"> < 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.75" /> < androidx.constraintlayout.widget.Guideline android:id="@+id/guideline9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.85" /> < 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.65" /> < androidx.constraintlayout.widget.Guideline android:id="@+id/guideline7" 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/guideline8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.9" /> < androidx.constraintlayout.widget.Guideline android:id="@+id/guideline10" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.08" /> < 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.2" /> < 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.35" /> < 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.45" /> < 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.55" /> < TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{@string/Grade(data.currentScore)}" android:textSize="18sp" app:layout_constraintBottom_toTopOf="@+id/guideline10" app:layout_constraintEnd_toStartOf="@+id/guideline8" app:layout_constraintStart_toStartOf="@+id/guideline7" app:layout_constraintTop_toTopOf="@+id/guideline10" tools:text="Score:5" /> < TextView android:id="@+id/textView4" android:layout_width="38dp" android:layout_height="53dp" android:text="@{String.valueOf(data.leftNumber)}" android:textSize="30sp" app:layout_constraintBottom_toBottomOf="@+id/textView5" app:layout_constraintEnd_toStartOf="@+id/textView5" app:layout_constraintStart_toStartOf="@+id/guideline7" app:layout_constraintTop_toTopOf="@+id/textView5" app:layout_constraintVertical_bias="0.0" tools:text="85" /> < TextView android:id="@+id/textView7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/euqal" android:textSize="@dimen/big_font" app:layout_constraintBottom_toBottomOf="@+id/textView9" app:layout_constraintEnd_toStartOf="@+id/textView9" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toEndOf="@+id/textView6" app:layout_constraintTop_toTopOf="@+id/textView9" app:layout_constraintVertical_bias="0.0" /> < TextView android:id="@+id/textView5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{data.operator}" android:textSize="@dimen/big_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" app:layout_constraintVertical_bias="0.0" tools:text="+" /> < TextView android:id="@+id/textView6" android:layout_width="37dp" android:layout_height="52dp" android:text="@{String.valueOf(data.rightNumber)}" android:textSize="30sp" 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" app:layout_constraintVertical_bias="0.0" tools:text="75" /> < TextView android:id="@+id/textView9" android:layout_width="16dp" android:layout_height="53dp" android:text="@string/question_mark" android:textSize="@dimen/big_font" app:layout_constraintBottom_toTopOf="@+id/guideline11" app:layout_constraintEnd_toStartOf="@+id/guideline8" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toEndOf="@+id/textView7" app:layout_constraintTop_toTopOf="@+id/guideline11" /> < TextView android:id="@+id/textView10" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Answer" android:textSize="@dimen/big_font" app:layout_constraintBottom_toTopOf="@+id/guideline12" app:layout_constraintEnd_toStartOf="@+id/guideline8" app:layout_constraintStart_toStartOf="@+id/guideline7" app:layout_constraintTop_toTopOf="@+id/guideline12" tools:text="Your Answer:" /> < Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_1" android:textSize="24sp" app:layout_constraintBottom_toTopOf="@+id/guideline14" app:layout_constraintEnd_toStartOf="@+id/button2" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="@+id/guideline7" app:layout_constraintTop_toTopOf="@+id/guideline13" /> < Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_2" android:textSize="24sp" 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/button_3" android:textSize="24sp" app:layout_constraintBottom_toBottomOf="@+id/button2" app:layout_constraintEnd_toStartOf="@+id/guideline8" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toEndOf="@+id/button2" app:layout_constraintTop_toTopOf="@+id/button2" /> < Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button_4" android:textSize="24sp" app:layout_constraintBottom_toTopOf="@+id/guideline15" app:layout_constraintEnd_toStartOf="@+id/button5" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="@+id/guideline7" app:layout_constraintTop_toTopOf="@+id/guideline

    推荐阅读