(一)四则运算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设计代码除外。