文章目录
一、功能需求
- 包含单选、多选和判断题题型
- 每次考完立刻判分,给出评语
二、标准化测试
(一)运行效果
(二)涉及知识点
- 线性布局(LinearLayout)
- 帧式布局(FrameLayout)
- 标签(TextView)
- 按钮(Button)
- 单选按钮(RadioButton)
- 复选框(CheckBox)
(三)实现步骤
1、创建安卓应用【StandardTest】
2、将背景图片拷贝到drawable目录
3、主布局资源文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:orientation="vertical"
android:padding="15dp"
tools:context="net.hw.standard_test.MainActivity">
<TextView
android:id="@+id/tv_stem"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2.5"
android:textSize="20sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="#aaaaaa" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4">
<LinearLayout
android:id="@+id/ll_single_choice"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible">
<RadioGroup
android:id="@+id/rg_single_choice"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RadioButton
android:id="@+id/rb_single_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<RadioButton
android:id="@+id/rb_single_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<RadioButton
android:id="@+id/rb_single_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<RadioButton
android:id="@+id/rb_single_d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
</RadioGroup>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_multiple_choice"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible">
<CheckBox
android:id="@+id/cb_multiple_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<CheckBox
android:id="@+id/cb_multiple_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<CheckBox
android:id="@+id/cb_multiple_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
<CheckBox
android:id="@+id/cb_multiple_d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_judgement"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible">
<RadioGroup
android:id="@+id/rg_judgement"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RadioButton
android:id="@+id/rb_judgement_t"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/judgement_t"
android:textSize="20sp" />
<RadioButton
android:id="@+id/rb_judgement_f"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/judgement_f"
android:textSize="20sp" />
</RadioGroup>
</LinearLayout>
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="#aaaaaa" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btn_previous"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:onClick="doPrevious"
android:text="@string/previous"
android:textSize="20sp" />
<Button
android:id="@+id/btn_next"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:onClick="doNext"
android:text="@string/next"
android:textSize="20sp" />
<Button
android:id="@+id/btnSubmit"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:onClick="doSubmit"
android:text="@string/submit"
android:textSize="20sp" />
<Button
android:id="@+id/btn_exit"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:onClick="doExit"
android:text="@string/exit"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
4、字符串资源文件strings.xml
<string name="judgement_t">正确</string>
<string name="judgement_f">错误</string>
<string name="previous">上一题</string>
<string name="next">下一题</string>
<string name="submit">提交</string>
<string name="exit">退出</string>
5、创建试题实体类 - Question
package net.hw.standard_test;
/**
* 功能:试题实体类
* 作者:华卫
* 日期:2020年10月20日
*/
public class Question {
/**
* 编号
*/
private int id;
/**
* 题干
*/
private String stem;
/**
* A选项
*/
private String a;
/**
* B选项
*/
private String b;
/**
* C选项
*/
private String c;
/**
* D选项
*/
private String d;
/**
* 题型
* 1 - 单选题
* 2 - 多选题
* 3 - 判断题
*/
private int type;
/**
* 答案
*/
private String answer;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStem() {
return stem;
}
public void setStem(String stem) {
this.stem = stem;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
@Override
public String toString() {
return "Question{" +
"id=" + id +
", stem='" + stem + '\'' +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
", type=" + type +
", answer='" + answer + '\'' +
'}';
}
}
6、主界面类MainActivity
package net.hw.standard_test;
import android.app.AlertDialog;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private LinearLayout llSingleChoice;
private LinearLayout llMultipleChoice;
private LinearLayout llJudgement;
private TextView tvStem;
private RadioGroup rgSingleChoice;
private RadioButton rbSingleA;
private RadioButton rbSingleB;
private RadioButton rbSingleC;
private RadioButton rbSingleD;
private RadioGroup rgJudgement;
private RadioButton rbJudgementT;
private RadioButton rbJudgementF;
private CheckBox cbMultipleA;
private CheckBox cbMultipleB;
private CheckBox cbMultipleC;
private CheckBox cbMultipleD;
private ArrayList<Question> questions;
private int questionIndex;
private String[] answers;
private String answer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 利用布局资源文件设置用户界面
setContentView(R.layout.activity_main);
// 通过资源标识符获得控件实例
llSingleChoice = findViewById(R.id.ll_single_choice);
llMultipleChoice = findViewById(R.id.ll_multiple_choice);
llJudgement = findViewById(R.id.ll_judgement);
tvStem = findViewById(R.id.tv_stem);
rgSingleChoice = findViewById(R.id.rg_single_choice);
rbSingleA = findViewById(R.id.rb_single_a);
rbSingleB = findViewById(R.id.rb_single_b);
rbSingleC = findViewById(R.id.rb_single_c);
rbSingleD = findViewById(R.id.rb_single_d);
rgJudgement = findViewById(R.id.rg_judgement);
rbJudgementT = findViewById(R.id.rb_judgement_t);
rbJudgementF = findViewById(R.id.rb_judgement_f);
cbMultipleA = findViewById(R.id.cb_multiple_a);
cbMultipleB = findViewById(R.id.cb_multiple_b);
cbMultipleC = findViewById(R.id.cb_multiple_c);
cbMultipleD = findViewById(R.id.cb_multiple_d);
// 初始化试题库
questions = getQuestions();
// 实例化答案数组
answers = new String[questions.size()];
// 取出第1题
Question question = questions.get(questionIndex);
// 根据题型设置界面
setInterfaceByType(question);
}
/**
* 获取试题列表
*
* @return 试题列表
*/
private ArrayList<Question> getQuestions() {
ArrayList<Question> questions = new ArrayList<>();
// 创建第1题
Question question = new Question();
question.setId(1);
question.setStem("驾驶机动车在道路上违反道路交通安全法的行为,属于什么行为?");
question.setA("违章行为");
question.setB("违法行为");
question.setC("过失行为");
question.setD("违规行为");
question.setType(1);
question.setAnswer("B");
// 将第1题添加到试题库
questions.add(question);
// 创建第2题
question = new Question();
question.setId(2);
question.setStem("交通信号包括交通信号灯、交通标志、交通标线和交通警察的指挥。");
question.setA("正确");
question.setB("错误");
question.setC("");
question.setD("");
question.setType(3);
question.setAnswer("A");
// 将第2题添加到试题库
questions.add(question);
// 创建第3题
question = new Question();
question.setId(3);
question.setStem("机动车驾驶人违法驾驶造成重大交通事故构成犯罪的,依法追究什么责任?");
question.setA("刑事责任");
question.setB("民事责任");
question.setC("经济责任");
question.setD("直接责任");
question.setType(1);
question.setAnswer("A");
// 将第3题添加到试题库
questions.add(question);
// 创建第4题
question = new Question();
question.setId(4);
question.setStem("钱某驾驶大型卧铺客车,乘载45人(核载40人),保持40公里/小时以上的车速行至八宿县境内连续下坡急转弯路段处,翻下100米深的山崖,造成17人死亡、20人受伤。钱某的主要违法行为是什么?");
question.setA("驾驶时接听手持电话");
question.setB("超速行驶");
question.setC("客车超员");
question.setD("疲劳驾驶");
question.setType(2);
question.setAnswer("BC");
// 将第4题添加到试题库
questions.add(question);
// 创建第5题
question = new Question();
question.setId(5);
question.setStem("邹某驾驶大型卧铺客车(核载35人,实载47人),行至京港澳高速公路938公里时,因乘车人携带的大量危险化学品在车厢内突然发生爆燃,造成41人死亡,6人受伤。此事故中的主要违法行为是什么?");
question.setA("客车超员");
question.setB("乘车人携带易燃易爆危险物品");
question.setC("超速行驶");
question.setD("不按规定停车");
question.setType(2);
question.setAnswer("AB");
// 将第5题添加到试题库
questions.add(question);
return questions;
}
/**
* 根据题型设置界面
*
* @param question
*/
private void setInterfaceByType(Question question) {
// 判断题型,选择界面
switch (question.getType()) {
case 1:
llSingleChoice.setVisibility(View.VISIBLE);
llMultipleChoice.setVisibility(View.INVISIBLE);
llJudgement.setVisibility(View.INVISIBLE);
tvStem.setText("[单选] " + question.getId() + ". " + question.getStem());
tvStem.setTextColor(Color.RED);
rbSingleA.setText(question.getA());
rbSingleB.setText(question.getB());
rbSingleC.setText(question.getC());
rbSingleD.setText(question.getD());
// 清空控件选中状态
rbSingleA.setChecked(false);
rbSingleB.setChecked(false);
rbSingleC.setChecked(false);
rbSingleD.setChecked(false);
rgSingleChoice.check(-1);
answer = answers[questionIndex];
if (answer != null) {
// 根据用户答案来设定单选按钮状态
switch (answer) {
case "A":
rbSingleA.setChecked(true);
break;
case "B":
rbSingleB.setChecked(true);
break;
case "C":
rbSingleC.setChecked(true);
break;
case "D":
rbSingleD.setChecked(true);
break;
}
}
break;
case 2:
llMultipleChoice.setVisibility(View.VISIBLE);
llSingleChoice.setVisibility(View.INVISIBLE);
llJudgement.setVisibility(View.INVISIBLE);
tvStem.setText("[多选] " + question.getId() + ". " + question.getStem());
tvStem.setTextColor(Color.BLACK);
cbMultipleA.setText(question.getA());
cbMultipleB.setText(question.getB());
cbMultipleC.setText(question.getC());
cbMultipleD.setText(question.getD());
// 清空控件选中状态
cbMultipleA.setChecked(false);
cbMultipleB.setChecked(false);
cbMultipleC.setChecked(false);
cbMultipleD.setChecked(false);
answer = answers[questionIndex];
if (answer != null) {
for (int i = 0; i < answer.length(); i++) {
switch (answer.charAt(i)) {
case 'A':
cbMultipleA.setChecked(true);
break;
case 'B':
cbMultipleB.setChecked(true);
break;
case 'C':
cbMultipleC.setChecked(true);
break;
case 'D':
cbMultipleD.setChecked(true);
break;
}
}
}
break;
case 3:
llJudgement.setVisibility(View.VISIBLE);
llSingleChoice.setVisibility(View.INVISIBLE);
llMultipleChoice.setVisibility(View.INVISIBLE);
tvStem.setText("[判断] " + question.getId() + ". " + question.getStem());
tvStem.setTextColor(Color.BLUE);
// 清空控件选中状态
rbJudgementT.setChecked(false);
rbJudgementF.setChecked(false);
rgJudgement.check(-1);
// 根据用户答案来设定单选按钮状态
answer = answers[questionIndex];
if (answer != null) {
switch (answer) {
case "A":
rbJudgementT.setChecked(true);
break;
case "B":
rbJudgementF.setChecked(true);
break;
}
}
}
}
/**
* 退出
*
* @param view
*/
public void doExit(View view) {
finish();
}
/**
* 上一题
*
* @param view
*/
public void doPrevious(View view) {
// 判断用户是否做了本题
switch (questions.get(questionIndex).getType()) {
case 1:
if (rbSingleA.isChecked() || rbSingleB.isChecked() || rbSingleC.isChecked() || rbSingleD.isChecked()) {
saveAnswer();
}
break;
case 2:
if (cbMultipleA.isChecked() || cbMultipleB.isChecked() || cbMultipleC.isChecked() || cbMultipleD.isChecked()) {
saveAnswer();
}
break;
case 3:
if (rbJudgementT.isChecked() || rbJudgementF.isChecked()) {
saveAnswer();
}
break;
}
if (questionIndex > 0) {
questionIndex--;
} else {
questionIndex = questions.size() - 1;
}
// 根据题型设置界面
setInterfaceByType(questions.get(questionIndex));
}
/**
* 下一题
*
* @param view
*/
public void doNext(View view) {
// 判断用户是否做了本题
switch (questions.get(questionIndex).getType()) {
case 1:
if (rbSingleA.isChecked() || rbSingleB.isChecked() || rbSingleC.isChecked() || rbSingleD.isChecked()) {
saveAnswer();
}
break;
case 2:
if (cbMultipleA.isChecked() || cbMultipleB.isChecked() || cbMultipleC.isChecked() || cbMultipleD.isChecked()) {
saveAnswer();
}
break;
case 3:
if (rbJudgementT.isChecked() || rbJudgementF.isChecked()) {
saveAnswer();
}
break;
}
Log.d("test", (questionIndex + 1) + answers[questionIndex]);
if (questionIndex < questions.size() - 1) {
questionIndex++;
} else {
questionIndex = 0;
}
// 根据题型设置界面
setInterfaceByType(questions.get(questionIndex));
}
/**
* 提交按钮单击事件处理方法
*
* @param view
*/
public void doSubmit(View view) {
// 保存当前题目答案
saveAnswer();
// 计算成绩点
int points = 0;
for (int i = 0; i < questions.size(); i++) {
if (null != answers[i]) {
if (answers[i].equals(questions.get(i).getAnswer())) {
points++;
}
}
}
// 按百分制来折算分数
double score = points * 100 / questions.size();
// 根据分数给出评语
String comment = "";
if (score >= 90) {
comment = "分数:" + score + "\n评语:棒棒哒~";
} else if (score >=60) {
comment = "分数:" + score + "\n评语:还行吧!";
} else {
comment = "分数:" + score + "\n评语:好好干吧!";
}
// 利用警告对话框来显示测试结果
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.mipmap.ic_launcher_round)
.setTitle("测试结果")
.setMessage(comment)
.setPositiveButton("确定", null)
.create()
.show();
}
/**
* 保存用户选择的答案
*/
private void saveAnswer() {
switch (questions.get(questionIndex).getType()) {
case 1: // 单选题
if (rbSingleA.isChecked()) {
answers[questionIndex] = "A";
} else if (rbSingleB.isChecked()) {
answers[questionIndex] = "B";
} else if (rbSingleC.isChecked()) {
answers[questionIndex] = "C";
} else {
answers[questionIndex] = "D";
}
break;
case 2: // 多选题
StringBuilder builder = new StringBuilder();
if (cbMultipleA.isChecked()) {
builder.append("A");
}
if (cbMultipleB.isChecked()) {
builder.append("B");
}
if (cbMultipleC.isChecked()) {
builder.append("C");
}
if (cbMultipleD.isChecked()) {
builder.append("D");
}
answers[questionIndex] = builder.toString();
break;
case 3: // 判断题
if (rbJudgementT.isChecked()) {
answers[questionIndex] = "A";
} else {
answers[questionIndex] = "B";
}
break;
}
}
}