好了,前面三篇文章,已经完成了题目的导入了,接下来要开始进入刷题模式了。
再回顾一下刷题要完成的功能:
-
做对当前题,选项变绿并跳到下一题,做错选项变红并显示解析
-
手动跳下一题,上一题
-
查看答案,隐藏答案
在此说明,虽然功能是实现了,但是代码写的比较复杂,自己当初也是改了很久的,后面是想到另外一个办法了,但是自己又懒得改了。(主要是那时写完这段已经头昏脑胀了,自己都乱了)可能之后心情好了就会改了,哈哈哈。
好了,废话不多说,既然代码自己写的有点麻烦,还是先说思路吧。
-
首先进行查询数据库,把数据库的数据全部查询出来,放在数组中(当然是为了之后操作方便些了)
-
因为有单选和多选,所以要有两个layout,一个是单选,一个是多选的,来回切换。应该是还有别的办法的,那时网上找了很多解决单选多选的问题的,有说自己做选择框的,因为自己能力有限,所以用了笨办法实现它。我在activity中显示两个layout,当初可能代码改的有点乱了,没改对,于是笨办法就是首先显示的是单选的layout,多选的layout都是new出来的,代码有点多。(之后会努力改进的)
-
布局解决后就把数据绑定到控件即可
###1.查询数据库
List<QuestionBean> xitiList;
xitiList = new ArrayList<QuestionBean>();
public void chaxun(){
//把数据库的数据查询出来
Cursor cursor = db.query("xiti", null, null, null, null, null, null, null);
while (cursor.moveToNext()) {
//对应数据库表格的列,一一对应
int _id = cursor.getInt(0);
String title= cursor.getString(1);
String optionA = cursor.getString(2);
String optionB = cursor.getString(3);
String optionC = cursor.getString(4);
String optionD = cursor.getString(5);
String answer = cursor.getString(6);
String jiexi = cursor.getString(7);
QuestionBean q = new QuestionBean(_id, title, optionA, optionB, optionC, optionD, answer, jiexi);
xitiList.add(q); //List<QuestionBean> xitiList; 数组
}
}
###2.单选设置
####2.1单选布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="考题"
>
<requestFocus />
</TextView>
<!-- android:layout_marginTop="2dp" 控件间的距离 -->
<RadioGroup
android:id="@+id/rg_base"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp" >
<RadioButton
android:id="@+id/rb_option_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选项"
android:textSize="15sp" />
<RadioButton
android:id="@+id/rb_option_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选项"
android:textSize="15sp" />
<RadioButton
android:id="@+id/rb_option_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选项"
android:textSize="15sp" />
<RadioButton
android:id="@+id/rb_option_d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选项"
android:textSize="15sp" />
</RadioGroup>
<!-- android:text="答案" -->
<TextView
android:id="@+id/text_answer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
/>
<!-- android:text="解析" -->
<TextView
android:id="@+id/text_jiexi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
/>
</LinearLayout>
<Button
android:id="@+id/btn_previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:text="上一题"
/>
<Button
android:id="@+id/btn_look"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:text="查看答案"
/>
<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="下一题"
/>
</RelativeLayout>
####2.2 单选数据绑定
if(question.getOptionC().equals("")){ //如果选择C为空,说明是判断题
rb_option_c.setVisibility(View.GONE);//把C、D选项隐藏
rb_option_d.setVisibility(View.GONE);
//设置题目tv_title内容
tv_title.setText((currentQuestionIndex + 1) + "." + question.getTitle());
rb_option_a.setText(question.getOptionA()); //设置A选项的内容
rb_option_b.setText(question.getOptionB()); //设置B选项的内容
}
else {
tv_title.setText((currentQuestionIndex + 1) + "." + question.getTitle());
rb_option_a.setText(question.getOptionA());
rb_option_b.setText(question.getOptionB());
rb_option_c.setText(question.getOptionC());
rb_option_d.setText(question.getOptionD());
}
###3.多选设置
不是在xml文件写的,控件都是new出来的,代码量挺多的
####3.1 先把控件new出来
private void initView2() {
tv_title_t = new TextView(this); //题目
text_answer_t = new TextView(this); //答案
text_jiexi_t = new TextView(this); //解析
cb_option_a = new CheckBox(this); //多选框A
cb_option_b = new CheckBox(this); //多选框B
cb_option_c = new CheckBox(this); //多选框C
cb_option_d = new CheckBox(this); //多选框D
bt_tijiao = new Button(this); //提交按钮
btn_previous_t = new Button(this); //上一题按钮
btn_look_t = new Button(this); //查看答案按钮
btn_next_t = new Button(this); //下一题按钮
}
####3.2 把控件有序的布局和绑定数据
private void dxbuju() {
initView2(); //多选布局,控件都是new出来的
//activity_shuati是空白的,因为有内容就会与单选的内容冲突覆盖了
ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.activity_shuati, null);
viewGroup.addView(tv_title_t); //在activity_shuati布局中添加题目tv_title_t控件
//相对布局RelativeLayout.LayoutParams.WRAP_CONTENT为包裹内容,第一个参数是宽,第二个参数是高
RelativeLayout.LayoutParams params_titile = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
tv_title_t.setText((currentQuestionIndex + 1) + "." + question.getTitle()); //设置题目内容
tv_title_t.setTextSize(18); //设置字体大小
tv_title_t.setTextColor(Color.BLACK); //设置字体颜色
tv_title_t.setId(1); //设置控件的id
tv_title_t.setLayoutParams(params_titile); //将设置的控件属性添加到布局中
viewGroup.addView(cb_option_a); //在activity_shuati布局中添加多选Acb_option_a控件
cb_option_a.setText(question.getOptionA()); //设置选项A的内容
cb_option_a.setTextSize(15);
RelativeLayout.LayoutParams params_a = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params_a.addRule(RelativeLayout.BELOW, 1); //cb_option_a控件位于id为1的控件下
cb_option_a.setLayoutParams(params_a);
cb_option_a.setId(2);
//...
//此处省略了其他的控件的设置,与上类似
setContentView(viewGroup); //显示布局
}
因为其他控件设置都类似,在此就不一一注释了。
###4.实现上一题时记录下自己选过的题目,思路如下:
- 将选过的答案存入数组中
定义的数组如下:
//0b00000001-A 0b00000010-B 0b00000100-C 0b00001000-C
//select A: answerList.add(new Integer(1))
//select B: answerList.add(new Integer(2))
//select C: answerList.add(new Integer(4))
//select D: answerList.add(new Integer(8))
//select A,C,D: answerList.add(new Integer(13))
List<Integer> answerList = new ArrayList<Integer>();
下面实现每一种情况,数组中存入的数据
####4.1 单选
private void fanhui() {
//判断记录所选答案数组的数据
switch (answerList.get(currentQuestionIndex)) {
case 1://只选了A选项
panduan_a(); //判断所选的是否正确
break;
case 2:
panduan_b();
break;
case 4:
panduan_c();
break;
case 16:
panduan_d();
break;
case 3://选过A、B选项
panduan_a();
panduan_b();
break;
//...
//这里省略了其他情况
default:
break;
}
}
上面代码中出现的panduan_a()功能是判断正确答案与所选的是否一致,如果正确选项内容显示绿色,否则显示红色,在此只贴了其中一个,其他的类似。
private void panduan_a() {
if (!question.getAnswer().equals("A")) {
rb_option_a.setTextColor(Color.RED);
}else{
rb_option_a.setTextColor(Color.GREEN);
}
}
####4.2 多选
其实多选的与单选的类似
private void Dfanhui() {
switch (answerList.get(currentQuestionIndex)) {
case 1: //将选过的选项选中
cb_option_a.setChecked(true);
break;
case 2:
cb_option_b.setChecked(true);
break;
case 4:
cb_option_c.setChecked(true);
break;
case 16:
cb_option_d.setChecked(true);
break;
case 3:
cb_option_a.setChecked(true);
cb_option_b.setChecked(true);
break;
//...
//这里省略了其他选过的情况
default:
break;
}
}
这里的判断与单选有所不同,因为多选在都选对时,要点击提交才去判断对错,不要担心会自动跳到下一题了,在重新设置为选中状态时,再判断所选的与答案是否一致,错误的选项变红,正确的变绿色
private void pundun() {
boolean A = question.getAnswer().contains("A");
boolean B = question.getAnswer().contains("B");
boolean C = question.getAnswer().contains("C");
boolean D = question.getAnswer().contains("D");
if(A){
if(cb_option_a.isChecked()){
cb_option_a.setTextColor(Color.GREEN);
}
}
else{
if(cb_option_a.isChecked()){
cb_option_a.setTextColor(Color.RED);
}
}
if(B){
if(cb_option_b.isChecked()){
cb_option_b.setTextColor(Color.GREEN);
}
}
else{
if(cb_option_b.isChecked()){
cb_option_b.setTextColor(Color.RED);
}
}
if(C){
if(cb_option_c.isChecked()){
cb_option_c.setTextColor(Color.GREEN);
}
}
else{
if(cb_option_c.isChecked()){
cb_option_c.setTextColor(Color.RED);
}
}
if(D){
if(cb_option_d.isChecked()){
cb_option_d.setTextColor(Color.GREEN);
}
}
else{
if(cb_option_d.isChecked()){
cb_option_d.setTextColor(Color.RED);
}
}
}
###5.题目跳转以及判断的问题
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton rb_option = (RadioButton) findViewById(checkedId);
//如果选项中没有选中,就不用进行判断了,因为在做对一题后会自动跳转到下一题,
//要把之前选的取消选中状态,就会触发这个方法的调用,就导致可能会再跳到下一题了
if(!rb_option.isChecked()){
return;
}
//判读选中状态,在答案的数组上写入答案的状态
if (checkedId == rb_option_a.getId()) {
option = "A";
daan = daan + 1;
} else if (checkedId == rb_option_b.getId()) {
option = "B";
daan = daan + 2;
} else if (checkedId == rb_option_c.getId()) {
option = "C";
daan = daan + 4;
} else if (checkedId == rb_option_d.getId()) {
option = "D";
daan = daan + 16;
}
//下标是题目号 一一对应
//第一个参数是下标,第二个参数是答案的状态
answerList.set(currentQuestionIndex, daan);
System.out.println(answerList + "");
System.out.println(answerList.get(currentQuestionIndex) + "");
//做错时选项内容变化,并显示解析
if (!option.equals(question.getAnswer())) {
rb_option.setTextColor(Color.RED);
text_jiexi.setText("解析:"+ question.getjiexi());
}
//做对时内容颜色变绿,并延时一段时间
else{
rb_option.setTextColor(Color.GREEN);
mHandler .postDelayed(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(1);
}
}, 500);
}
}
注意private int currentQuestionIndex = 0;是题号数
这里附上
private Handler mHandler = null;
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//半s后执行代码
if(!question.getAnswer().equals("A")&&!question.getAnswer().equals("B")&&!question.getAnswer().equals("C")&&!question.getAnswer().equals("D")){
Dnext();
}else {
next();
}
}
};
###6.最后附上绑定数据,具体的调用
private void setData() {
question = xitiList.get(currentQuestionIndex);
answerList.add(0);
daan = 0;
System.out.println(answerList+ "");
if(!question.getAnswer().equals("A")&&!question.getAnswer().equals("B")&&!question.getAnswer().equals("C")&&!question.getAnswer().equals("D")){
dxbuju();
anniu();
Dfanhui();//多选的返回时判断用户的选择
pundun();
}else{
setContentView(R.layout.activity_strat);
initView();
fanhui();
if(question.getOptionC().equals("")){ //如果选择C为空,说明是判断题
rb_option_c.setVisibility(View.GONE);//把C、D选项隐藏
rb_option_d.setVisibility(View.GONE);
//设置题目tv_title内容
tv_title.setText((currentQuestionIndex + 1) + "." + question.getTitle());
rb_option_a.setText(question.getOptionA()); //设置A选项的内容
rb_option_b.setText(question.getOptionB()); //设置B选项的内容
}
else {
tv_title.setText((currentQuestionIndex + 1) + "." + question.getTitle());
rb_option_a.setText(question.getOptionA());
rb_option_b.setText(question.getOptionB());
rb_option_c.setText(question.getOptionC());
rb_option_d.setText(question.getOptionD());
}
// 给RadioButton设置监听
rg_base.setOnCheckedChangeListener(this);
}
}
上面我认为是难点,也是我做项目比较难搞定的部分,下面这些是简单的功能,这里只填了单选的,多选思路也是类似的,就不在此啰嗦了哈。
###7. 上一题
private void previous(){
if (currentQuestionIndex > 0) {
currentQuestionIndex--;
// 将选项被选中的状态清空
rb_option_a.setChecked(false);
rb_option_b.setChecked(false);
rb_option_c.setChecked(false);
rb_option_d.setChecked(false);
answerList.get(currentQuestionIndex);
text_answer.setText(" ");
text_jiexi.setText(" ");
setData();
} else {
Toast.makeText(StartActivity.this, "已经到头啦!", Toast.LENGTH_SHORT)
.show();
}
}
###8.下一题
private void next(){
if (currentQuestionIndex < sizeOfList - 1) {
currentQuestionIndex++;
// 将选项被选中的状态清空
rb_option_a.setChecked(false);
rb_option_b.setChecked(false);
rb_option_c.setChecked(false);
rb_option_d.setChecked(false);
text_answer.setText(" ");
text_jiexi.setText(" ");
setData();
} else {
Toast.makeText(StartActivity.this, "这已经是最后一题啦!",
Toast.LENGTH_SHORT).show();
}
}
###9.查看答案
if(btn_look.getText().equals("查看答案")){
text_answer.setText("答案:" + question.getAnswer());
btn_look.setText("隐藏答案");
}else{
text_answer.setText("");
btn_look.setText("查看答案");
}
到此为止,这个项目的难点已经总结完毕了,如有不妥之处,欢迎指教。
一、简单刷题APP(题库是Excel)之项目功能和效果图
二、简单刷题APP(题库是Excel)之实现文件管理器添加题库
三、简单刷题APP(题库是Excel)之在APP添加题目
欢迎加群学习交流