毕设博客(十三) —— 口算测试APP

1、创建四个Fragment:Title,Question,Win,Lose

2、在res下创建一个导航图表nav,用连线表示出四个页面之间的逻辑关系:

3、给title页面添加一个图标,并且在gradle中添加dataBinding 和依赖:

buildFeatures{
    dataBinding = true;
}
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

4、开始做Title页面:

<string name="title_message">Calculation Test</string>
<string name="title_image_info">title image</string>
<string name="title_button_message">Enter</string>
<string name="high_score_message">High Score:%d</string>

5、做Question页面: 

<string name="button0">0</string>
<string name="button1">1</string>
<string name="button2">2</string>
<string name="button3">3</string>
<string name="button4">4</string>
<string name="button5">5</string>
<string name="button6">6</string>
<string name="button7">7</string>
<string name="button8">8</string>
<string name="button9">9</string>
<string name="button_clear">C</string>
<string name="button_submit">OK</string>
<string name="equal_symbol">=</string>
<string name="question_mark">\?</string>
<string name="current_score">Score:%d</string>
<string name="input_indicator">Your Answer:</string>

6、做win和lose页面:

<string name="lose_image_message">lose image</string>
<string name="win_image_message">win image</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>

7、需要创建一个ViewModel:

...

    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";
    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;
    }
    MutableLiveData<Integer>getLeftNumber(){
        return handle.getLiveData(KEY_LEFT_NUMBER);
    }
    MutableLiveData<Integer>getRightNumber(){
        return handle.getLiveData(KEY_RIGHT_NUMBER);
    }
    MutableLiveData<Integer>getOperator(){
        return handle.getLiveData(KEY_OPERATOR);
    }
    MutableLiveData<Integer>getHighScore(){
        return  handle.getLiveData(KEY_HIGH_SCORE);
    }
    MutableLiveData<Integer>getCurrentScore(){
        return handle.getLiveData(KEY_CURRENT_SCORE);
    }
    MutableLiveData<Integer>getAnswer(){
        return handle.getLiveData(KEY_ANSWER);
    }
    void generator(){
        int LEVEL = 20;
        Random random = new Random();
        int x,y;
        x = random.nextInt(LEVEL) + 1;
        y = random.nextInt(LEVEL) + 1;
        if (x % 2 == 0){
            getOperator().setValue(Integer.valueOf("+"));
            if (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(Integer.valueOf("-"));
            if (x > y){
                getAnswer().setValue(x - y);
                getLeftNumber().setValue(x);
                getRightNumber().setValue(y);
            }
            else {
                getAnswer().setValue(y - x);
                getLeftNumber().setValue(y);
                getRightNumber().setValue(x);
            }
        }
    }
    @SuppressWarnings("ConstantConditions")
    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();
    }
    @SuppressWarnings("ConstantConditions")
    void answerCorrect(){
        getCurrentScore().setValue(getCurrentScore().getValue() + 1);
        if (getCurrentScore().getValue() > getHighScore().getValue()){
            getHighScore().setValue(getCurrentScore().getValue());
            win_flag = true;
        }
        generator();
    }
}

8、做数据绑定: 

fragment_title:

<?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:text="@{@string/high_score_message(data.highScore)}"
           ...
</layout>

fragment_question:

<?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:text="@{@string/current_score(data.currentScore)}"
            ... />
        ...
        <TextView
            ...
            android:text="@{String.valueOf(data.leftNumber)}"
            .../>
        <TextView
            ...
            android:text="@{data.operator}"
            ... />
        <TextView
            ...
            android:text="@{String.valueOf(data.rightNumber)}"
            ... />
       ...
</layout>

fragment_win:

<?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:text="@{@string/win_score_message(data.highScore)}"
            ... />
    ...
</layout>

fragment_lose:

<?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:text="@{@string/lose_score_message(data.currentScore)}"
            ... />
    ...
</layout>

9、写fragment里面的代码:

TitleFragment:

...
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        MyViewModel myViewModel;
        myViewModel = new ViewModelProvider(requireActivity(),new SavedStateViewModelFactory(requireActivity().getApplication(),this)).get(MyViewModel.class);
        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 view) {
                NavController controller = Navigation.findNavController(view);
                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:

...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final MyViewModel myViewModel;
        myViewModel = new ViewModelProvider(requireActivity(),new SavedStateViewModelFactory(requireActivity().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() {
            @SuppressLint("NonConstantResourceId")
            @Override
            public void onClick(View view) {
                switch (view.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.button_clear:
                        builder.setLength(0);break;
                }
                if (builder.length() == 0){
                    binding.textView9.setText(getString(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 view) {
                if(builder.length() == 0){//没有输入的情况下
                    Toast.makeText(getActivity(), getString(R.string.input_null_message), Toast.LENGTH_SHORT).show();
                    return;
                }
                else if (Integer.valueOf(builder.toString()).intValue() == myViewModel.getAnswer().getValue()){
                    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(view);
                    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();
    }
}

WinFragment:

...
    @Override
    public View onCreateView(@NonNull 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 view) {
                NavController controller = Navigation.findNavController(view);
                controller.navigate(R.id.action_winFragment_to_titleFragment);
            }
        });
        return binding.getRoot();
    }
}

 LoseFragment:

...
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        MyViewModel myViewModel = new ViewModelProvider(requireActivity(),new SavedStateViewModelFactory(requireActivity().getApplication(),this)).get(MyViewModel.class);
        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 view) {
                NavController controller = Navigation.findNavController(view);
                controller.navigate(R.id.action_loseFragment_to_titleFragment);
            }
        });
        return binding.getRoot();
    }
}

10、MainActivity:

package com.example.calculationtest;
import ...

public class MainActivity extends AppCompatActivity {
    NavController controller;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //controller = findNavController(this,R.id.fragment);
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
        controller = navHostFragment.getNavController();
        NavigationUI.setupActionBarWithNavController(this,controller);
    }

    @Override
    public boolean onSupportNavigateUp() {
        if (Objects.requireNonNull(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, (dialogInterface, i) -> controller.navigateUp());
            builder.setNegativeButton(R.string.dialog_negative_message, (dialogInterface, i) -> {

            });
            AlertDialog dialog = builder.create();
            dialog.show();
        }else {
            controller.navigate(R.id.titleFragment);
        }
        return super.onNavigateUp();
    }

    @Override
    public void onBackPressed() {
        onSupportNavigateUp();
    }
}

11、MyViewModel:

package com.example.calculationtest;
import ...
public class MyViewModel extends AndroidViewModel {
    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 CURRENT_SCORE = "current_score";
    boolean win_flag = false;
    // private  String current = getApplication().getResources().getString(R.string.KEY_CURRENT_SCORE);
    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(CURRENT_SCORE, 0);
/*
            handle.set(application.getString(R.string.KEY_CURRENT_SCORE),0 );
*/
        }
        this.handle = handle;
    }
    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>getHighScore(){
        return handle.getLiveData(KEY_HIGH_SCORE);
    }
    public MutableLiveData<Integer>getCurrentScore(){
        return handle.getLiveData(CURRENT_SCORE);
    }
    public MutableLiveData<Integer>getAnswer(){
        return handle.getLiveData(KEY_ANSWER);
    }
    void generator(){
        int LEVEL = 20;
        Random random = new Random();
        int x,y;
        x = random.nextInt(LEVEL) + 1;
        y = random.nextInt(LEVEL) + 1;
        if(x%2 == 0 ){
            getOperator().setValue("+");
            if(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 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 answerCorrect() {
        getCurrentScore().setValue(getCurrentScore().getValue() + 1);
        if (getCurrentScore().getValue() > getHighScore().getValue()) {
            getHighScore().setValue(getCurrentScore().getValue());
            win_flag = true;
        }
        generator();
    }
}

12、对一些需要汉化的资源进行汉化:

最终运行结果:

简易口算测试APP

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值