简单的基于Android的网上学习系统的设计-2

写在前面的话

       由于毕业设计的需要,本人自学了Android的开发,做了一款基于Android的课程网上学习系统。可以实现课程在线观看,发布通知,签到定位,在线测试等功能。但毕竟本人不是专业的软件专业,因而整个系统和程序中也会存在很多不足,而且,这也是我第一次在CSDN上写这种博客,所以对于不足之处,欢迎大家提出指导意见,批评指正。写这篇博客,主要是因为在软件的设计中,也会遇到很多的问题,但通过在网上查阅资料,得到了很多的帮助,因而希望也能写一篇博客,给大家一些参考,帮助到有需要的人,同时,也是对自己的开发的一个记录。

         之前已经对“签到定位”进行了一个介绍:https://blog.csdn.net/qq_28053421/article/details/105788953。接下来继续对“在线测试”功能进行记录。

在线测试 

功能简介

        在线测试想必大家也都很熟悉,这里主要是两个方面:老师发布测试,学生进行测试。测试主要分为两类:作业和考试。考试是有一个考试时间的,并且只有一次考试机会。

功能实现

    老师发布测试的部分

      发布测试的界面如下(这是直接在layout布局预览里截图出来的,所以里面会有ListView的item的显示):

      点击”添加题目“后,进入添加题目的界面: 

        在这里,我们要进行一个题目类型的判断,如,用户选择的单选题,那么就只能勾选一个正确选项,多选题,则要勾选两个及以上的选项,同时,也要对正确答案进行一个拼接,以方便存入数据库。在添加题目时,我将题目都存在了本地的SQLite数据库里,这样可以随时查看添加的题目,在点击发布题目后,会将本地数据库的题目数据也删除。主要代码如下: 

package com.sjhbysj.aixuexi.activities;

import java.io.Serializable;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Messenger;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;

import com.sjhbysj.aixuexi.R;
import com.sjhbysj.aixuexi.config.Constants;
import com.sjhbysj.aixuexi.domain.Question;
import com.sjhbysj.aixuexi.service.TestService;
import com.sjhbysj.aixuexi.utils.MyXUtils;
/**
 * 用户添加题目的activity
 * @author Hasee-Hua
 *
 */
public class AddQuestionActivity extends Activity {

	private RadioGroup rg_addquestion_type;  //题目类型
	private EditText et_addquestion_question;  //题干
	private CheckBox cb_addquestion_select_1;  //选择框 1
	private CheckBox cb_addquestion_select_2;  //选择框 2
	private CheckBox cb_addquestion_select_3;  //选择框 3
	private EditText et_addquestion_answer_1;  //答案选项1
	private EditText et_addquestion_answer_2;  //答案选项2
	private EditText et_addquestion_answer_3;  //答案选项3
	private EditText et_addquestion_grade;  //题目分数
	private Button btn_addquestion_ok;  //确认按钮
	private Button btn_addquestion_delete;  //删除按钮
	
	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case Constants.ADD_QUESTION_SUCCESS:
				//添加题目成功---则自动返回上一个页面,并让上一页刷新数据
				setResult(Constants.CHANGE_QUESTION);
				finish();
				break;

			default:
				break;
			}
		};
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_addquestion);
		
		initView();
		initData();
		initListener();
	}

	private void initListener() {
		//为 题目类型 设置一个监听,当选择类型为 选择题 时,自动填充答案选项。
		rg_addquestion_type.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			
			@Override
			public void onCheckedChanged(RadioGroup group, int checkedId) {
				if(checkedId == R.id.rb_addquestion_judgment){
					//选择题目类型为选择题
					et_addquestion_answer_1.setText("对");
					et_addquestion_answer_2.setText("错");
					//为防止之前对第三个选项做过设置
					et_addquestion_answer_3.setText("");  //将第三个选项清空
					cb_addquestion_select_3.setChecked(false); //将第三个选项的勾选也去掉
					//在将第三个选项给隐藏
					et_addquestion_answer_3.setVisibility(View.GONE);
					cb_addquestion_select_3.setVisibility(View.GONE);
				}else{
					//显示第三个选项
					et_addquestion_answer_3.setVisibility(View.VISIBLE);
					cb_addquestion_select_3.setVisibility(View.VISIBLE);
				}
			}
		});
		
		//设置确认按钮的监听
		btn_addquestion_ok.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				dealData();  //处理用户输入的数据
			}
		});
		
	}

	private void initData() {
		
	}

	private void initView() {
		......  //初始化控件
	
		
		//这是用户添加题目的,没有删除功能,但因为和查看问题详情共用一个页面,所以这里让按钮不显示出来
		btn_addquestion_delete.setVisibility(View.GONE);
	}
	
	/**
	 * 处理用户输入的数据
	 */
	private void dealData() {
		boolean etState = false;  //判断所有EditText是否填写完整的标志位
		boolean cbState = false;  //判断所有CheckBox是否填写完整的标志位
		int typeId = rg_addquestion_type.getCheckedRadioButtonId();
		String type = "单选题";  //默认选择
		if(typeId == R.id.rb_addquestion_multichoice){
			type = "多选题";
		}else if(typeId == R.id.rb_addquestion_judgment){
			type = "判断题";
		}
		
		String question = et_addquestion_question.getText().toString().trim();
		String answer_1 = et_addquestion_answer_1.getText().toString().trim();
		String answer_2 = et_addquestion_answer_2.getText().toString().trim();
		String answer_3 = et_addquestion_answer_3.getText().toString().trim();
		String grade = et_addquestion_grade.getText().toString().trim();
		String answer = "";  //正确答案--开始为空
		
		//判断EditText输入框
		//判断所有要输入的 输入框
		if("判断题".equals(type)){
			//为判断题,则答案选项中 只需要输入 前两个选项 就可以,即 选项三 的输入框不用填
			//判断输入框
			if(!TextUtils.isEmpty(grade) && !TextUtils.isEmpty(question) && !TextUtils.isEmpty(answer_1) && 
					!TextUtils.isEmpty(answer_2)){
				//说明 输入框都已 填写
				etState = true;  //更改EditText状态
				//判断CheckBox 选择框----只有一个选择框框能被选中,并且第三个不能选
				if((cb_addquestion_select_1.isChecked() && !cb_addquestion_select_2.isChecked() && !cb_addquestion_select_3.isChecked()) ||
						(!cb_addquestion_select_1.isChecked() && cb_addquestion_select_2.isChecked() && !cb_addquestion_select_3.isChecked())){
					//说明选择满足要求
					cbState = true;  //更改CheckBox状态
					//获得正确答案
					if(cb_addquestion_select_1.isChecked()){
						//选择的 选项1---即  A
						answer = cb_addquestion_select_1.getText().toString().trim();
					}else if(cb_addquestion_select_2.isChecked()){
						//选择的 选项2---即  B
						answer = cb_addquestion_select_2.getText().toString().trim();
					}
				}else{
					Toast.makeText(AddQuestionActivity.this, "请勾选出正确选项,选择题只能勾选一个正确项", 0).show();
				}
			}else{
				Toast.makeText(AddQuestionActivity.this, "您还有输入框没有填写哦", 0).show();
			}
		}else{
			//说明为选择题,则三个选项都要填写
			//判断输入框
			if(!TextUtils.isEmpty(grade) &&  !TextUtils.isEmpty(question) && !TextUtils.isEmpty(answer_1) && 
					!TextUtils.isEmpty(answer_2) && !TextUtils.isEmpty(answer_3)){
				//说明 输入框都已 填写
				etState = true;  //更改EditText状态
				if("单选题".equals(type)){
					//为单选题,则只能有 一个 选择框 被选中
					if((cb_addquestion_select_1.isChecked() && !cb_addquestion_select_2.isChecked() && !cb_addquestion_select_3.isChecked()) ||
							(!cb_addquestion_select_1.isChecked() && cb_addquestion_select_2.isChecked() && !cb_addquestion_select_3.isChecked()) ||
							(!cb_addquestion_select_1.isChecked() && !cb_addquestion_select_2.isChecked() && cb_addquestion_select_3.isChecked())){
						//说明选择满足要求
						cbState = true;  //更改CheckBox状态
						//获得正确答案
						if(cb_addquestion_select_1.isChecked()){
							//选择的 选项1---即A
							answer = cb_addquestion_select_1.getText().toString().trim();
						}else if(cb_addquestion_select_2.isChecked()){
							//选择的 选项2---即B
							answer = cb_addquestion_select_2.getText().toString().trim();
						}else if(cb_addquestion_select_3.isChecked()){
							//选择的 选项3---即C
							answer = cb_addquestion_select_3.getText().toString().trim();
						}
					}else{
						Toast.makeText(AddQuestionActivity.this, "请勾选出正确选项,单选题只能勾选一个正确项", 0).show();
					}
				}else{
					//为多选题,则 要有 两个及以上 的 选择框 被选中
					if((cb_addquestion_select_1.isChecked() && cb_addquestion_select_2.isChecked() && !cb_addquestion_select_3.isChecked()) ||  //选择:A B
							(cb_addquestion_select_1.isChecked() && !cb_addquestion_select_2.isChecked() && cb_addquestion_select_3.isChecked()) ||  //选择:A C
							(!cb_addquestion_select_1.isChecked() && cb_addquestion_select_2.isChecked() && cb_addquestion_select_3.isChecked()) ||  //选择:B C
							(cb_addquestion_select_1.isChecked() && cb_addquestion_select_2.isChecked() && cb_addquestion_select_3.isChecked())){  //选择:A B C
						//说明选择满足要求
						cbState = true;  //更改CheckBox状态
						//多选获得的答案为 类似 AB 型,表示答案为A和B,后期可根据该特定规律进行字符切割
						if(cb_addquestion_select_1.isChecked()){
							//选项1被选中了
							answer += cb_addquestion_select_1.getText().toString().trim();
						}
						if(cb_addquestion_select_2.isChecked()){
							//选项2被选中了
							answer += cb_addquestion_select_2.getText().toString().trim();
						}
						if(cb_addquestion_select_3.isChecked()){
							//选项3被选中了
							answer += cb_addquestion_select_3.getText().toString().trim();
						}
					}else{
						Toast.makeText(AddQuestionActivity.this, "请勾选出正确选项,多选题需勾选两个及以上正确项", 0).show();
					}
				}
			}else{
				Toast.makeText(AddQuestionActivity.this, "您还有输入框没有填写哦", 0).show();
			}
		}
		
		//确定按钮做最终判断
		if(etState && cbState){
			//说明全部都已填写完成
			//为该题设置题号
			//说明要添加一道题---则题号+1
			TestService.titleNumber++;
			//处理数据---写入本地数据库
			Question questionBean = new Question("question-"+MyXUtils.generateUUID(), null, TestService.titleNumber+"", type, question, answer_1, answer_2, answer_3, answer, grade);
			//启动服务
			Intent service = new Intent(AddQuestionActivity.this, TestService.class);
			service.putExtra("operation", "addQuestion");
			service.putExtra("questionBean", (Serializable)questionBean);
			service.putExtra("messenger", new Messenger(handler));
			startService(service);
			
			//恢复标志位
			etState = false;
			cbState = false;
		}
	}
}

       在添加题目的页面点击确定后,会将题目存入本地数据库,然后自动返回上一个页面,并刷新数据。如图: 

添加第一道题后自动返回显示的界面

       当题目都添加完成后,点击“发布测试”,会先检查数据的填写情况,当填写无误后,就将数据发送到服务端并存入数据库,数据以json字符串形式发送 

/**-----“发布测试”按钮部分 的程序------**/

//发布测试 按钮的监听
btn_createtest_release.setOnClickListener(new OnClickListener() {
			
	@Override
	public void onClick(View v) {
	//检查所有项目是否都已填写

	if(TestService.questions.size() == 0){
	    //说明还没有添加题目
	    Toast.makeText(CreateTestActivity.this, "您还没有添加题目", 0).show();
	    return;
	}
	String name = et_createtest_testname.getText().toString().trim();
	if(TextUtils.isEmpty(name)){
	    Toast.makeText(CreateTestActivity.this, "请填写测试名称", 0).show();
	    return;
	}
				
	String examTime = null;
	String testType = "作业";  //默认选择的为作业
	//如果选择的考试,则需要填写考试时间
	if(rg_createtest_testtype.getCheckedRadioButtonId() == R.id.rb_createtest_exam){
	    //选择的为 考试
	    testType = "考试";
	    //需要填写考试时间
	    examTime = et_createtest_examtime.getText().toString().trim();
	    if(TextUtils.isEmpty(examTime)){
	        Toast.makeText(CreateTestActivity.this, "请填写考试时间", 0).show();
	        return;
	    }
	}
	if(!deadlineSelected){  //默认为false,当选择了日期后变为true
	    //说明提交截止日期还没有选择
	    Toast.makeText(CreateTestActivity.this, "请选择截止日期", 0).show();
	    return;
	}
				
	//到这里,说明都已填写,可以提交
	//封装数据
	Test test = new Test();
	test.setName(name);
	test.setQuestionCount(TestService.questions.size()+"");
	test.setType(testType);
	//遍历题目,计算总分
	int sumGrade = 0;
	for (Question q : TestService.questions) {
	    int grade = Integer.parseInt(q.getGrade());
	    sumGrade += grade;
        }
	test.setGrade(sumGrade+"");
	test.setDeadline(deadline);
	if("考试".equals(testType)){
	    test.setExamTime(examTime);
	}
	test.setReleaseClass(mClass.getJoinClassCode());
	//显示 正在发布 进度条
	showReleaseingDialog();
	//启动服务,发布测试
	Intent service = new Intent(CreateTestActivity.this, TestService.class);
	service.putExtra("operation", "releaseTest");
	service.putExtra("test", (Serializable)test);
	service.putExtra("messenger", new Messenger(handler));
	startService(service);
    }
});

学生在线测试部分

       学生在“测试列表”页面可以看到所有已发布的测试和提交信息,这里同样是使用的一个ListView来进行显示,当点击里面的一个item后,就可以进入该测试。至于“已提交”和“未提交”的判断,我是先在服务端数据库里建了一个表(student_scores),这个表主要用于存储学生的测试得分,然后,在进入“测试列表”页面时,我会根据用户名(username)去请求这个表中 该用户的 所有的测试提交信息,然后遍历提交信息,根据测试的id(testId)判断有没有提交某一个测试

学生的“测试列表”页面
student_scores
序号 列名 数据类型 说明
1 username varchar 用户名
2 testId varchar 测试的id号
3 score varchar 测试得分
4 answerTime timestamp 测试时间,系统自动维护

       学生进入某一个测试后,系统先会判断该测试是否已经提交了,如果已经提交了,那么进入后显示的是考生的答题情况页面,如图1,如果没有提交过,那么就会判断是否已经过了截止日期,如果过了,那么就不能测试提交,没过的话就可以进行测试。当然,系统还会判断一下测试的类型,如果是考试,那么就会给出提示,让考生注意时间等,并且在确认考试后开始倒计时,测试页面如图2。

图1
图2

       学生的答题情况我是简单的先用一个List数组暂存,当提交测试时,直接将这里的数据封装传输。学生进行测试部分的代码如下:   

package com.sjhbysj.aixuexi.activities;

import java.io.Serializable;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Messenger;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.sjhbysj.aixuexi.R;
import com.sjhbysj.aixuexi.config.Constants;
import com.sjhbysj.aixuexi.domain.Question;
import com.sjhbysj.aixuexi.domain.StudentAnswer;
import com.sjhbysj.aixuexi.domain.StudentScore;
import com.sjhbysj.aixuexi.domain.Test;
import com.sjhbysj.aixuexi.service.TestService;
import com.sjhbysj.aixuexi.utils.MyXUtils;
import com.sjhbysj.aixuexi.view.CountDown;
import com.sjhbysj.aixuexi.view.CountDown.OnTimeCompleteListener;

public class StudentTestActivity extends Activity {

	private TextView tv_studenttest_type;
	private CountDown cd_studenttest_countdown;
	private TextView tv_studenttest_number;
	private TextView tv_studenttest_questiontype;
	private TextView tv_studenttest_grade;
	private TextView tv_studenttest_question;
	private RadioGroup rg_studenttest_select;
	private RadioButton rb_studenttest_A;
	private RadioButton rb_studenttest_B;
	private RadioButton rb_studenttest_C;
	private LinearLayout ll_studenttest_cb;
	private CheckBox cb_studenttest_A;
	private CheckBox cb_studenttest_B;
	private CheckBox cb_studenttest_C;
	private Button btn_studenttest_last;
	private TextView tv_studenttest_currentposition;
	private TextView tv_studenttest_totalnumber;
	private Button btn_studenttest_next;
	
	private Test test;
	private Question currentQuestion;  //当前显示的题目
	private int currentPosition = 0;
	private boolean isFirst = true;  //是否第一次答题
	private int score = 0;  //测试得分
	private ProgressDialog dialog;
	
	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case Constants.REQUEST_QUESTION_SUCCESS:
				//获得了测试的 试题
				//清空 学生的作答 的集合
				TestService.studentAnswers.clear();
				if("考试".equals(test.getType())){
					//弹出提示框,准备倒计时
					showExamAlertDialog();
				}
				//显示第一题题目
				showQuestion(currentPosition);
				break;
			case Constants.CHECK_IN_TEST_SUCCESS:
				//交卷完成,跳转到 结果显示 的页面
				dialog.dismiss();
				Intent intent = new Intent(StudentTestActivity.this, TestResultActivity.class);
				intent.putExtra("score", score);
				startActivityForResult(intent, Constants.CHANGE_TEST);
				break;
			case Constants.INTERNET_ERROR:
				Toast.makeText(StudentTestActivity.this, "网络错误", 0).show();
				break;

			default:
				break;
			}
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_studenttest);
		
		initView();
		initData();
		initListener();
	}

	private void initListener() {
		// 上一题的点击按钮
		btn_studenttest_last.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//判断是否在第一道题上
				if(currentPosition == 0){
					//不能再往上翻
					Toast.makeText(StudentTestActivity.this, "已经是第一题了", 0).show();
					return;
				}
				//显示上一题
				currentPosition--;
				showQuestion(currentPosition);
			}
		});
		
		// 下一题 或 提交测试(当处于最后一道题时) 的点击按钮
		btn_studenttest_next.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//判断用户 有没有 去做这道题
				if(cb_studenttest_A.isChecked() || cb_studenttest_B.isChecked() || cb_studenttest_C.isChecked() ||
						rb_studenttest_A.isChecked() || rb_studenttest_B.isChecked() || rb_studenttest_C.isChecked()){
					//说明做了这道题,则判断要执行的操作
					if("提交测试".equals(btn_studenttest_next.getText().toString().trim())){
						//把 提交按钮 所在页面 的数据存入list集合
						dealStudentAnswer();
						//判断是否全部的题目都做完了
						if(TestService.studentAnswers.size() != TestService.questions.size()){
							//没有做完
							Toast.makeText(StudentTestActivity.this, "还有题目没有做哦", 0).show();
						}else{
							//做完了,提交试卷
							showloadingDialog("正在交卷");
							checkInTest();
						}
					}else if("下一题".equals(btn_studenttest_next.getText().toString().trim())){
						//将这道题做的答案存入list集合
						dealStudentAnswer();
						//显示下一题
						currentPosition++;
						showQuestion(currentPosition);
					}
				}else{
					//说明没有做这道题
					//判断操作
					if("提交测试".equals(btn_studenttest_next.getText().toString().trim())){
						//说明是在最后一道题上,但最后一道题没有写,所以提示用户要做 这道题
						Toast.makeText(StudentTestActivity.this, "还有题目没有做哦", 0).show();
					}else if("下一题".equals(btn_studenttest_next.getText().toString().trim())){
						// 不存数据,直接显示下一题
						currentPosition++;
						showQuestion(currentPosition);
					}
				}
			}
		});

		//倒计时结束的监听
		cd_studenttest_countdown.setOnTimeCompleteListener(new OnTimeCompleteListener() {
			
			@Override
			public void onTimeComplete() {
				showloadingDialog("考试结束,正在交卷");
				checkInTest();
			}
		});
	}
	
	/**
	 * 计算得分,启动服务,提交试卷
	 */
	private void checkInTest() {
		//计算得分
		for (Question question : TestService.questions) {
			for (StudentAnswer studentAnswer : TestService.studentAnswers) {
				if(studentAnswer.getQuestionId().equals(question.getQuestionId())){
					//找到了对应的题目
					//判断正误
					if(studentAnswer.getStudentAnswer().equals(question.getCorrectAnswer())){
						//答案正确
						//拿到该题的分数,并计算得分
						score += Integer.parseInt(question.getGrade());
					}
				}
			}
		}
		//封装数据
		StudentScore studentScore = new StudentScore(TestService.loginUser.getUserName(), test.getId(), score+"");
		//启动服务,提交
		Intent service = new Intent(StudentTestActivity.this, TestService.class);
		service.putExtra("operation", "checkInTest");
		service.putExtra("studentScore", (Serializable)studentScore);
		service.putExtra("messenger", new Messenger(handler));
		startService(service);
	}

	private void initData() {
		Intent intent = getIntent();
		test = (Test) intent.getSerializableExtra("test");
		
		//检查是否已经过了截止日期
		String currentTime = MyXUtils.getCurrentTime();
		//得到 yyyy-MM-dd HH:mm 型的时间
		currentTime = currentTime.substring(0, 16);
		//与 截止时间比较--可以先将里面的符号都给删掉,变为存数字的字符串,然后转化比较( .replace("-", "").replace(" ", "").replace(":", "") )
		//但实现发现,直接用原始字符串比较也可以得出正确结果
		if(currentTime.compareTo(test.getDeadline()) > 0){
			//说明已经过了截止时间
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setTitle("提示")
					.setMessage("该测试已经过了截止提交日期,无法答题")
					.setNeutralButton("确定", new DialogInterface.OnClickListener() {
						
						@Override
						public void onClick(DialogInterface dialog, int which) {
							finish();  //退出页面
						}
					});
			builder.show();
		}
			
		//显示信息
		//题目类型
		tv_studenttest_type.setText(test.getType());
		//倒计时
		if("作业".equals(test.getType())){
			//不显示倒计时控件
			cd_studenttest_countdown.setVisibility(View.GONE);
		}else if("考试".equals(test.getType())){
			//获得考试时间
			int examTime = Integer.parseInt(test.getExamTime());
			//将分钟转化为秒
			examTime = examTime*60;
			//初始化倒计时
			cd_studenttest_countdown.initTime(examTime);
		}
		//总题数
		tv_studenttest_totalnumber.setText(test.getQuestionCount());
		
		//启动服务,获取题目
		Intent service = new Intent(StudentTestActivity.this, TestService.class);
		service.putExtra("operation", "requestQuestion");
		service.putExtra("test", (Serializable)test);
		service.putExtra("messenger", new Messenger(handler));
		startService(service);
	}

	private void initView() {
		......  //控件的初始化
	}
	
	/**
	 * 将用户 选择的答案存入集合
	 */
	private void dealStudentAnswer() {
		String sAnswer = "";
		boolean updateList = false;  //是否更新了 学生作答的 list集合
		if("多选题".equals(currentQuestion.getType())){
			//拼接答案
			if(cb_studenttest_A.isChecked()){
				//选项A被选中了
				sAnswer += "A:";
			}
			if(cb_studenttest_B.isChecked()){
				//选项B被选中了
				sAnswer += "B:";
			}
			if(cb_studenttest_C.isChecked()){
				//选项C被选中了
				sAnswer += "C:";
			}
		}else{
			//为 单选 或者 判断
			int id = rg_studenttest_select.getCheckedRadioButtonId();
			if(id == R.id.rb_studenttest_A){
				sAnswer = "A:";
			}
			if(id == R.id.rb_studenttest_B){
				sAnswer = "B:";
			}
			if(id == R.id.rb_studenttest_C){
				sAnswer = "C:";
			}
		}
		
		//判断答案正误
		String isCorrect = "F";
		if(sAnswer.equals(currentQuestion.getCorrectAnswer())){
			isCorrect = "T";
		}
		
		//封装数据
		StudentAnswer stuAnswer = new StudentAnswer(TestService.loginUser.getUserName(), currentQuestion.getQuestionId(), test.getId(), sAnswer, isCorrect);
													       
		if(isFirst){
			//说明为第一次做题---直接将数据加入集合
			TestService.studentAnswers.add(stuAnswer);
			isFirst = false;
		}else{
			//说明已经做了题目,即集合里有数据了,可以遍历集合。当集合为空时,不会执行遍历函数
			StudentAnswer studentAnswer = new StudentAnswer();
			//遍历 学生已作答的list集合 ,看这道题之前有没有写过---如果写过,则更新数据
			for (int i = 0; i < TestService.studentAnswers.size(); i++) {
				studentAnswer = TestService.studentAnswers.get(i);
				if(studentAnswer.getQuestionId().equals(currentQuestion.getQuestionId())){
					//说明本题已经作答了---更新数据
					TestService.studentAnswers.set(i, stuAnswer);
					updateList = true;  //更新了集合,即这道题之前写过,不再另外添加到list集合里
					break;  //已得到了结果,可直接跳出循环
				}
			}
			if(!updateList){
				//说明 遍历完整个 学生作答的list集合 也没有找到当前显示的题目---即这道题还没有做过,那么直接加入到list集合
				TestService.studentAnswers.add(stuAnswer);
				updateList = false;  //恢复标志
			}
		}
	}
	
	/**
	 * 显示对应位置的题目
	 * @param position
	 */
	private void showQuestion(int position) {
		//拿到对应的题目
		currentQuestion = TestService.questions.get(position);
		//显示题目内容
		tv_studenttest_number.setText(currentQuestion.getNumber());
		tv_studenttest_questiontype.setText(currentQuestion.getType());
		tv_studenttest_grade.setText("(分值:" + currentQuestion.getGrade() + ")");
		tv_studenttest_question.setText(currentQuestion.getQuestion());
		//清空选择--避免其余题目的选择的干扰
		rg_studenttest_select.clearCheck();
		cb_studenttest_A.setChecked(false);
		cb_studenttest_B.setChecked(false);
		cb_studenttest_C.setChecked(false);
		if("单选题".equals(currentQuestion.getType())){
			//则显示单选框--即多选框隐藏
			rg_studenttest_select.setVisibility(View.VISIBLE);
			ll_studenttest_cb.setVisibility(View.GONE);
			rb_studenttest_C.setVisibility(View.VISIBLE);  //防止前面有判断题
			//显示选项内容
			rb_studenttest_A.setText("A:" + currentQuestion.getAnswer_1());
			rb_studenttest_B.setText("B:" + currentQuestion.getAnswer_2());
			rb_studenttest_C.setText("C:" + currentQuestion.getAnswer_3());
		}else if("多选题".equals(currentQuestion.getType())){
			//则显示多选框--即隐藏单选框
			rg_studenttest_select.setVisibility(View.GONE);
			ll_studenttest_cb.setVisibility(View.VISIBLE);
			//显示选项内容
			cb_studenttest_A.setText("A:" + currentQuestion.getAnswer_1());
			cb_studenttest_B.setText("B:" + currentQuestion.getAnswer_2());
			cb_studenttest_C.setText("C:" + currentQuestion.getAnswer_3());
		}else if("判断题".equals(currentQuestion.getType())){
			//则显示单选框--即多选框隐藏
			rg_studenttest_select.setVisibility(View.VISIBLE);
			ll_studenttest_cb.setVisibility(View.GONE);
			//且只显示两个选项
			rb_studenttest_C.setVisibility(View.GONE);
			//显示选项内容
			rb_studenttest_A.setText("A:" + currentQuestion.getAnswer_1());
			rb_studenttest_B.setText("B:" + currentQuestion.getAnswer_2());
		}
		
		//如果学生 选择了答案,再回过头来看时,要显示他选择的答案
		//遍历学生 作答答案 的list集合,看是否 做过 当前显示的题目---因为学生 作答的list集合的数据的位置 并不是和 题目集合 一一对应的,可能他中间会先跳过某道题,所以要遍历查找
		for (StudentAnswer studentAnswer : TestService.studentAnswers) {
			if(studentAnswer.getQuestionId().equals(currentQuestion.getQuestionId())){
				//说明本题已经作答了---显示作答的答案
				if("多选题".equals(currentQuestion.getType())){
					//切割答案
					String[] stuAnswers = studentAnswer.getStudentAnswer().split(":");
					for (int i = 0; i < stuAnswers.length; i++) {
						if("A".equals(stuAnswers[i])){
							cb_studenttest_A.setChecked(true);
						}
						if("B".equals(stuAnswers[i])){
							cb_studenttest_B.setChecked(true);
						}
						if("C".equals(stuAnswers[i])){
							cb_studenttest_C.setChecked(true);
						}
					}
				}else{
					//说明为 单选 或判断
					if("A:".equals(studentAnswer.getStudentAnswer())){
						rb_studenttest_A.setChecked(true);
					}
					if("B:".equals(studentAnswer.getStudentAnswer())){
						rb_studenttest_B.setChecked(true);
					}
					if("C:".equals(studentAnswer.getStudentAnswer())){
						rb_studenttest_C.setChecked(true);
					}
				}
				break;  //已经查找到了结果,不需要再循环了
			}
		}
		//显示当前位置
		int cp = position+1; //因为position是从0开始算的,所以+
		tv_studenttest_currentposition.setText(cp+"");
		
		//判断该题是否是最后一道题
		if(position == TestService.questions.size()-1){
			//说明是最后一道题---显示为 提交测试
			btn_studenttest_next.setText("提交测试");
		}else{
			btn_studenttest_next.setText("下一题");  //当从最后一题往前翻时,也要变化 显示
		}
	}
	
	/**
	 * 考试提醒对话框
	 */
	private void showExamAlertDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(StudentTestActivity.this);
		builder.setTitle("提示")
				.setMessage("该测试类型为 考试。请注意:\n1.开始后将启动倒计时,请把握好考试时间。\n2.考试只有一次机会,中途退出将自动提交答卷,请保证手机电量充足,网络畅通。")
				.setPositiveButton("开始考试", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						cd_studenttest_countdown.reStart();
					}
				}).setNegativeButton("不考了", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// 直接返回上一个页面
						setResult(Constants.CHANGE_TEST);
						finish();
					}
				});
		builder.show();
	}
	
	/**
	 * 显示加载框
	 */
	private void showloadingDialog(String message) {
		dialog = new ProgressDialog(this);
		dialog.setMessage(message);
		dialog.setCanceledOnTouchOutside(false);  //设置点击对话框之外的地方不会取消对话框 
		dialog.show();
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if(resultCode == Constants.CHANGE_TEST){
			//从结果页面跳转回来,则自动返回至测试列表页面
			setResult(Constants.CHANGE_TEST);
			finish();
		}
	}
	
	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		if(keyCode == KeyEvent.KEYCODE_BACK){
			if("考试".equals(test.getType())){
				AlertDialog.Builder builder = new AlertDialog.Builder(this);
				builder.setTitle("提示")
						.setMessage("退出后将会自动交卷,确定退出吗。")
						.setPositiveButton("确定", new DialogInterface.OnClickListener() {
							
							@Override
							public void onClick(DialogInterface dialog, int which) {
								//交卷
								showloadingDialog("正在交卷");
								checkInTest();
							}
						}).setNegativeButton("取消", null);
				builder.show();
			}else{
				//不是考试,则可以直接退出
				finish();
			}
			return true;
		}
		return super.onKeyUp(keyCode, event);
	}
}

最后

 博客中可能有些地方描述的也不是很清楚,如果有问题,欢迎大家留言讨论。不足之处也欢迎大家指出。

 转载请标明出处。谢谢支持!

猜你喜欢

转载自blog.csdn.net/qq_28053421/article/details/105795067