(一)四则运算APP版

这这个Demo的目的就是强化一下本周学习的Android的Jetpack里的新内容,接下来我将通过这个Demo来展示我所学到的新知识。

先列出新学到的知识:ViewModel,Navigation,MutableLiveData,ViewModelSaveState,SharedPreferences,AndroidViewModel,DataBinding

设计思路:

UI设计思路:

一共四个页面:首页,习题页,成功页,失败页

将这四个页面通过Navigation连接起来形成一条逻辑关系。

接下来就是对每个页面进行设计。

首页:一个TextView和一个ImageView还有一个Button,顶部还有一个最高分Textview,通过button来进入出题页面

<?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.calculation.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/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/CalName"
android:textSize="@dimen/huge_size"
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.106" /> <ImageView
android:id="@+id/imageView"
android:layout_width="320dp"
android:layout_height="349dp"
android:contentDescription="@string/title_image"
android:src="@drawable/size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="w,1:1"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintHorizontal_bias="0.56"
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"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.862" /> <TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/higer_score(data.highScore)}"
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="parent"
app:layout_constraintVertical_bias="0.036"
tools:text="High Score:%d" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

出题页面:顶部一个textview代表目前的得分情况,中间是一个算式,下面是你的答案,接下来是4行3列,12个按钮代表你的操作。

<?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.calculation.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/guideline3"
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/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.33" /> <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/guideline10"
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/guideline11"
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/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/guideline7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.8" /> <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_toStartOf="@+id/guideline9"
app:layout_constraintHorizontal_bias="0.537"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:layout_constraintTop_toTopOf="@+id/guideline3"
app:layout_constraintVertical_bias="0.473"
tools:text="Score:0" /> <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.1" /> <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.9" /> <TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/huge_size"
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/guideline8"
app:layout_constraintTop_toTopOf="@+id/textView5"
tools:text="1" /> <TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/huge_size"
android:text="@{String.valueOf(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_size"
android:text="@{String.valueOf(data.rigthNumber)}"
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="2" /> <TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="="
android:textSize="@dimen/huge_size"
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/Cal_Answer"
android:textSize="@dimen/huge_size"
app:layout_constraintBottom_toTopOf="@+id/guideline4"
app:layout_constraintEnd_toStartOf="@+id/guideline9"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/textView7"
app:layout_constraintTop_toTopOf="@+id/guideline4" /> <TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Your Answer:"
android:textSize="@dimen/mid_size"
app:layout_constraintBottom_toTopOf="@+id/guideline5"
app:layout_constraintEnd_toStartOf="@+id/guideline9"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:layout_constraintTop_toTopOf="@+id/guideline5" /> <Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toTopOf="@+id/guideline10"
app:layout_constraintEnd_toStartOf="@+id/button2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:layout_constraintTop_toTopOf="@+id/guideline6" /> <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2"
android:textSize="@dimen/button_size"
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="3"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toBottomOf="@+id/button2"
app:layout_constraintEnd_toStartOf="@+id/guideline9"
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="4"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toTopOf="@+id/guideline11"
app:layout_constraintEnd_toStartOf="@+id/button5"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:layout_constraintTop_toTopOf="@+id/guideline10" /> <Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5"
android:textSize="@dimen/button_size"
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="6"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toBottomOf="@+id/button5"
app:layout_constraintEnd_toStartOf="@+id/guideline9"
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="7"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toTopOf="@+id/guideline12"
app:layout_constraintEnd_toStartOf="@+id/button8"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:layout_constraintTop_toTopOf="@+id/guideline11" /> <Button
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="8"
android:textSize="@dimen/button_size"
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="9"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toBottomOf="@+id/button8"
app:layout_constraintEnd_toStartOf="@+id/guideline9"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/button8"
app:layout_constraintTop_toTopOf="@+id/button8" /> <Button
android:id="@+id/clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clear"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toTopOf="@+id/guideline7"
app:layout_constraintEnd_toStartOf="@+id/button0"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:layout_constraintTop_toTopOf="@+id/guideline12" /> <Button
android:id="@+id/button0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toBottomOf="@+id/clear"
app:layout_constraintEnd_toStartOf="@+id/submit"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/clear"
app:layout_constraintTop_toTopOf="@+id/clear" /> <Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"
android:textSize="@dimen/button_size"
app:layout_constraintBottom_toBottomOf="@+id/button0"
app:layout_constraintEnd_toStartOf="@+id/guideline9"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/button0"
app:layout_constraintTop_toTopOf="@+id/button0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

成功页面:一个Imageview笑脸,两个Textview还有一个Button来返回首页

<?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.calculation.MyViewModel" />
</data> <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WinFragment"> <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.1" /> <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.35" /> <ImageView
android:id="@+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@string/image_win"
android:src="@drawable/ic_sentiment_satisfied_black_24dp"
app:layout_constraintBottom_toTopOf="@+id/guideline14"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline13" /> <TextView
android:id="@+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="恭喜你!创下新纪录"
android:textSize="@dimen/bige_size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline14"
app:layout_constraintVertical_bias="0.1" /> <TextView
android:id="@+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/New_Score(data.highScore)}"
android:textSize="@dimen/bige_size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView2"
app:layout_constraintVertical_bias="0.3"
tools:text="你的成绩是:%d" /> <Button
android:id="@+id/button10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline14"
app:layout_constraintVertical_bias="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

失败页面:一个Imageview哭脸,两个Textview还有一个Button来返回首页

<?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.calculation.MyViewModel" />
</data> <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoseFragment"> <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.35" /> <ImageView
android:id="@+id/imageView3"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/ic_sentiment_dissatisfied_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/textView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/New_Score(data.currentScore)}"
android:textSize="@dimen/bige_size"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline16"
app:layout_constraintVertical_bias="0.3"
tools:text="你的成绩是:%d" /> <Button
android:id="@+id/button11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline16"
app:layout_constraintVertical_bias="0.5" /> <TextView
android:id="@+id/textView14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="挑战失败!"
android:textSize="@dimen/bige_size"
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" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

程序设计:

首先是设计我们的MyViewModel里的数据,有最高分,目前得分,左操作数,右操作数,操作符,答案

通过SharedPreferences来保存数据,livedata可以随时的刷新数据,故用它来显示数据。

package com.example.calculation;

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 androidx.lifecycle.ViewModel; 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";
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 shp=getApplication().getSharedPreferences(SAVE_SHP_DATA_NAME, Context.MODE_PRIVATE);
handle.set(KEY_HIGH_SCORE,shp.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> getLeftNumber(){
return handle.getLiveData(KEY_LEFT_NUMBER);
}
public MutableLiveData<Integer> getRigthNumber(){
return handle.getLiveData(KEY_RIGHT_NUMBER);
}
public MutableLiveData<String> getOperator(){
return handle.getLiveData(KEY_OPERATOR);
}
public MutableLiveData<Integer> getHighScore(){
return handle.getLiveData(KEY_HIGH_SCORE);
}
public MutableLiveData<Integer> getCurrentScore(){
return handle.getLiveData(KEY_CURRENT_SCORE);
}
public MutableLiveData<Integer> getAnswer(){
return handle.getLiveData(KEY_ANSWER);
} public void setCurrentScore(){
handle.set(KEY_CURRENT_SCORE,0);
} void generator(){
int level=100;
Random random=new Random();
int a=random.nextInt(level)+1;
int b=random.nextInt(level)+1;
if(a%4==0){
getOperator().setValue("+");
if(a>b){
getAnswer().setValue(a);
getLeftNumber().setValue(b);
getRigthNumber().setValue(a-b);
}else{
getOperator().setValue("+");
getAnswer().setValue(b);
getLeftNumber().setValue(a);
getRigthNumber().setValue(b-a);
}
}
else if(a%4==1){
getOperator().setValue("-");
if(a>b){
getAnswer().setValue(a-b);
getLeftNumber().setValue(a);
getRigthNumber().setValue(b);
}else{
getOperator().setValue("-");
getAnswer().setValue(b-a);
getLeftNumber().setValue(b);
getRigthNumber().setValue(a);
}
}
else if(a%4==2){
getOperator().setValue("*");
getLeftNumber().setValue(a);
getRigthNumber().setValue(b);
getAnswer().setValue(a*b);
}
else if(a%4==3){
getOperator().setValue("/");
while(a%b!=0){
a=random.nextInt(level)+1;
b=random.nextInt(level)+1;
}
getLeftNumber().setValue(a);
getRigthNumber().setValue(b);
getAnswer().setValue(a/b);
}
}
void save(){
SharedPreferences shp=getApplication().getSharedPreferences(SAVE_SHP_DATA_NAME,Context.MODE_PRIVATE);
SharedPreferences.Editor editor=shp.edit();
editor.putInt(KEY_HIGH_SCORE,getHighScore().getValue());
editor.apply();
}
void answerCurrent(){
getCurrentScore().setValue(getCurrentScore().getValue()+1);
if(getCurrentScore().getValue()>getHighScore().getValue()){
getHighScore().setValue(getCurrentScore().getValue());
win_flag=true;
}
generator();
}
}

TieleFragment的设计:设计一个按钮的绑定事件,进行跳转到出题页面

package com.example.calculation;

import android.app.AppComponentFactory;
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.os.Bundle; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.NavController;
import androidx.navigation.Navigation; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import com.example.calculation.databinding.FragmentTitleBinding; /**
* A simple {@link Fragment} subclass.
*/
public class TitleFragment extends Fragment{ public TitleFragment() {
// Required empty public constructor
} @Override
public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) { FragmentTitleBinding binding;
binding= DataBindingUtil.inflate(inflater,R.layout.fragment_title,container,false);
MyViewModel myViewModel = ViewModelProviders.of(requireActivity(), new SavedStateViewModelFactory(requireActivity().getApplication(),requireActivity())).get(MyViewModel.class);
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();
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_title, container, false);
} }

QuestionFragment的设计:通过按钮点击来获取用户的答案,然后从数据里获取当前的viewmodel,判断结果是否相同,之后进行相应的操作。

里面有代码注释

package com.example.calculation;

import android.os.Bundle;

import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.NavController;
import androidx.navigation.Navigation; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast; import com.example.calculation.databinding.FragmentQuestionBinding; /**
* A simple {@link Fragment} subclass.
*/
public class QuestionFragment extends Fragment { public QuestionFragment() {
// Required empty public constructor
} @Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
final MyViewModel myViewModel;
myViewModel= ViewModelProviders.of(requireActivity(),new SavedStateViewModelFactory(requireActivity().getApplication(),requireActivity())).get(MyViewModel.class);
//获取运算表达式
myViewModel.generator();
//设置初始得分为0
myViewModel.setCurrentScore();
//获取页面的控制binding
final FragmentQuestionBinding binding;
binding= DataBindingUtil.inflate(inflater,R.layout.fragment_question,container,false);
//设置数据与生命周期
binding.setData(myViewModel);
binding.setLifecycleOwner(requireActivity());
//builder用来保存用户输入的数据
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.clear:
//清楚代表用户的输入长度未0
builder.setLength(0);
break;
}
if(builder.length()==0){
binding.textView9.setText("请输入你的答案:");
}else{
//显示到UI页面上
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.clear.setOnClickListener(listener);
//提交按钮的设计
binding.submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(builder.length()!=0) {
//当答案相同时
if (Integer.valueOf(builder.toString()).intValue() == myViewModel.getAnswer().getValue()) {
myViewModel.answerCurrent();
builder.setLength(0);
binding.textView9.setText("回答正确! 请继续!");
} 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);
}
}
}else{
Toast.makeText(v.getContext(), "请输入答案", Toast.LENGTH_SHORT).show();
}
}
});
return binding.getRoot();
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_question, container, false);
}
}
WinFragment的设计:设置它的返回按钮,与LoseFragment一样
package com.example.calculation;

import android.os.Bundle;

import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateHandle;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.NavController;
import androidx.navigation.Navigation; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import com.example.calculation.databinding.FragmentWinBinding; /**
* A simple {@link Fragment} subclass.
*/
public class WinFragment extends Fragment { public WinFragment() {
// Required empty public constructor
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
MyViewModel myViewModel;
myViewModel= ViewModelProviders.of(requireActivity(), new SavedStateViewModelFactory(requireActivity().getApplication(),requireActivity())).get(MyViewModel.class);
FragmentWinBinding binding;
binding= DataBindingUtil.inflate(inflater,R.layout.fragment_win,container,false);
binding.setData(myViewModel);
binding.setLifecycleOwner(requireActivity());
binding.button10.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NavController controller= Navigation.findNavController(v);
controller.navigate(R.id.action_winFragment_to_titleFragment);
}
});
return binding.getRoot();
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_win, container, false);
}
}
package com.example.calculation;

import android.os.Bundle;

import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.NavController;
import androidx.navigation.Navigation; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import com.example.calculation.databinding.FragmentLoseBinding; /**
* A simple {@link Fragment} subclass.
*/
public class LoseFragment extends Fragment { public LoseFragment() {
// Required empty public constructor
} @Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
MyViewModel myViewModel;
myViewModel= ViewModelProviders.of(requireActivity(),new SavedStateViewModelFactory(requireActivity().getApplication(),requireActivity())).get(MyViewModel.class);
FragmentLoseBinding binding;
binding= DataBindingUtil.inflate(inflater,R.layout.fragment_lose,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_loseFragment_to_titleFragment);
}
});
return binding.getRoot();
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_lose, container, false);
}
}

MainActivity的设计:用来设置左上角的返回与手机左下方左三角的返回

package com.example.calculation;

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.app.Dialog;
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("你确定要退出吗?");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
controller.navigateUp();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
});
AlertDialog dialog=builder.create();
dialog.show();
}else{
controller.navigate(R.id.titleFragment);
}
return super.onSupportNavigateUp();
}
//设置手机的左三角的返回操作
@Override
public void onBackPressed() {
onSupportNavigateUp();
}
}
整个项目到此完结。。。
花费时间:
2020/3/29:上午10:00-11:10,休息10分钟,11:30-12:30,
2020/3/29:下午15:00-15:45,吃东西喝水10分钟,16:00-19:00,吃饭30分钟。
2020/3/29:晚上19:30-20:45,完成。
共花费:420分钟,代码量:450行,UI设计代码除外。

四则运算APP版的更多相关文章

  1. 结对编程项目——四则运算vs版

    结对编程项目--四则运算vs版 1)小伙伴信息:        学号:130201238 赵莹        博客地址:点我进入 小伙伴的博客 2)实现的功能: 实现带有用户界面的四则运算:将原只能在 ...

  2. 四则运算app工程的进展

    深入分析五个四则运算app: 1.ALM-Addition 缺点:版本是英文版,不利于孩子们弄懂.  用选择题的方法来选择正确的答案,固然有运气答对的成分,不利于统计真实的水平. 优点:有图标统计答题 ...

  3. 四则运算GUI版

    小学四则运算界面版 李永豪 201421123117 郑靖涛 201421123114 coding 地址:https://git.coding.net/ras/work2.git 一.题目描述 我们 ...

  4. 家居环境监測系统设计(PC上位机版)(手机APP版待定)

    下面是我的毕业设计:家居环境监測系统设计(PC上位机临时版.手机app版待定).本系统採用STC12C5A60S2单片机.结合传感器.分别对空气湿度.空气温度.气压.海拔.进水温度.出水温度.光照强度 ...

  5. 《软件工程》小组团队项目-小学生四则运算APP(First Sprint)

    <软件工程>团队项目我们小组选择了小学生四则运算APP,在上学期原有的项目基础上进行更新升级.(自我感觉我们团队上学期的小学生四则运算APP是较为成功且实用的,不过这学期学习到了新的知识, ...

  6. 小学四则运算APP 最后阶段

    团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 这次发布的是我们APP的最终版本!图片背景有根据用户需求改变!还增加了草稿纸运算的画布功能! 运行结果如下: package com.ex ...

  7. 小学四则运算APP 第三阶段冲刺-第一天

    团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第三次冲刺阶段时间:12.12~12.19 本次发布的是音乐播放功能,可以根据用户需求一边播放音乐一边做题,也拥有暂停播放音乐的功能,增强 ...

  8. 小学四则运算APP 第二阶段冲刺-第五天

    团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第二次冲刺阶段时间:11.29~12.09 本次发布的是判断题代码,已经实现部分功能,,但是美中不足的是判断错误 panduanset.j ...

  9. 小学四则运算APP 第二次冲刺 第四天

    团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第二次冲刺阶段时间:11.29~12.09 本次发布的是合并后的选择题功能界面的设置: ChoiceSet.java: package c ...

随机推荐

  1. selenium&appium中的三种等待方式---基于python

    我们在实际使用selenium或者appium时,等待下个等待定位的元素出现,特别是web端加载的过程,都需要用到等待,而等待方式的设置是保证脚本稳定有效运行的一个非常重要的手段,在selenium中 ...

  2. selenium之浏览器、元素、鼠标等操作总结

    1    控制浏览器 Selenium 主要提供的是操作页面上各种元素的方法,但它也提供了操作浏览器本身的方法,比如浏览器的大小以及浏览器后退.前进按钮等. 1.1  控制浏览器窗口大小 在不同的浏览 ...

  3. Tian Tian 菾菾 导游 陪同

    自画像系列是梵高的代表作之一,他是一位自学成才的画家,下笔完全自由,主观提取了当时印象派画家学到的技巧,在这幅画中,我们可以看到,颜色在画中的堆叠,色彩与笔在画中表现的形态,都表现出,梵高在他作画中内 ...

  4. linux下查找文件及查找包含指定内容的文件常用命令

    whereis <程序名称> 查找软件的安装路径-b 只查找二进制文件-m 只查找帮助文件-s 只查找源代码-u 排除指定类型文件-f 只显示文件名-B <目录> 在指定目录下 ...

  5. scrapy post payload的坑及相关知识的补充【POST传参方式的说明及scrapy和requests实现】

    一.问题及解决: 在用scrapy发送post请求时,把发送方式弄错了. 本来应该是 application/x-www-form-urlencoded  弄成了application/json. 但 ...

  6. 浅析TCP/IP协议

    浅析TCP/IP协议 0x00 什么是TCP/IP协议? ​ 想一想人与人之间交流需要什么?我们是不是要掌握一种我们都能体会到对方意思的语言.那么计算机与网络设备之间进行通信,是不是不同设备之间是不是 ...

  7. JS基础入门篇(十八)—日期对象

    1.日期对象 日期对象: 通过new Date()就能创建一个日期对象,这个对象中有当前系统时间的所有详细信息. 以下代码可以获取当前时间: <script> var t = new Da ...

  8. Let’s Encrypt https证书安装

    我的博客: https://www.seyana.life/post/15 现在已经有很多的免费ssl证书提供商,国内的也有, 不过国内政策要求还要把key给他们, 我们还是用Let's Encryp ...

  9. Java 8 Optional 良心指南,建议收藏

    想学习,永远都不晚,尤其是针对 Java 8 里面的好东西,Optional 就是其中之一,该类提供了一种用于表示可选值而非空引用的类级别解决方案.作为一名 Java 程序员,我真的是烦透了 Null ...

  10. 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型

    本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...