教育系统APP(六)

用一切抱怨的时间去努力
## 回顾上一期任务

25

任务实施

个人资料加上QQ号属性
在个人资料下添加一个“QQ号”属性,初始状态文字显示“未添加”,点击进入修改页面,输入框的键盘类型只能为数字。
(提示:editText.setInputType(InputType.TYPE_CLASS_NUMBER) )
输入框最多只能输入12位数字,点击保存后个人资料界面能正常显示保存后的结果。

教育系统APP(六)的发布

先解决上一次的问题-教育系统APP(五)

DBUtils.java

package cn.edu.gdmec.android.boxuegu.utils;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import cn.edu.gdmec.android.boxuegu.bean.UserBean;
import cn.edu.gdmec.android.boxuegu.sqlite.SQLiteHelper;

public class DBUtils {
    private static DBUtils instance = null;
    private static SQLiteHelper helper;
    private static SQLiteDatabase db;

    /**
     * 构造方法,只有当类被实例化时候调用
     * 实例化SQLiteHelper类,从中得到一个课读写的数据库
     **/
    public DBUtils(Context context) {
        helper = new SQLiteHelper(context);
        db = helper.getWritableDatabase();
    }

    /**
     * 得到这个类的实例
     **/
    public static DBUtils getInstance(Context context) {
        if (instance == null) {
            instance = new DBUtils(context);
        }
        return instance;
    }

    /**
     * 保存个人资料信息
     **/
    public void saveUserInfo(UserBean bean) {
        ContentValues cv = new ContentValues();
        cv.put("userName", bean.userName);
        cv.put("nickName", bean.nickName);
        cv.put("sex", bean.sex);
        cv.put("signature", bean.signature);
        cv.put("qq",bean.qq);
        //Convenience method for inserting a row into the database.
        //注意,我们是从数据库使用插入方法,传入表名和数据集完成插入
        db.insert(SQLiteHelper.U_USER_INFO, null, cv);
    }

    /**
     * 获取个人资料信息
     **/
    public UserBean getUserInfo(String userName) {
        String sql = "SELECT * FROM " + SQLiteHelper.U_USER_INFO + " WHERE userName=?";
        //?和下面数组内元素会逐个替换,可以多条件查询=?and =?
        //You may include ?s in where clause in the query, which will be replaced by the values from selectionArgs.
        Cursor cursor = db.rawQuery(sql, new String[]{userName});
        UserBean bean = null;
        //Move the cursor to the next row.
        while (cursor.moveToNext()) {
            bean = new UserBean();
            //根据列索引获取对应的数值,因为这里查询结果只有一个,我们也不需要对模型UserBean进行修改,
            //直接将对应用户名的所有数据从表中动态赋值给bean
            bean.userName = cursor.getString(cursor.getColumnIndex("userName"));
            bean.nickName = cursor.getString(cursor.getColumnIndex("nickName"));
            bean.sex = cursor.getString(cursor.getColumnIndex("sex"));
            bean.signature = cursor.getString(cursor.getColumnIndex("signature"));
            bean.qq = cursor.getString(cursor.getColumnIndex("qq"));
        }
        cursor.close();
        return bean;
    }

    /**
     * 修改个人资料信息,这里的key指代表字段,value表示数值
     **/
    public void updateUserInfo(String key, String value, String userName) {
        ContentValues cv = new ContentValues();
        cv.put(key, value);
        //Convenience method for updating rows in the database.
        db.update(SQLiteHelper.U_USER_INFO, cv, "userName=?", new String[]
                {userName});
    }
}

SQLiteHelper.java

package cn.edu.gdmec.android.boxuegu.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class SQLiteHelper extends SQLiteOpenHelper {
    private static final int DB_VERSION = 1;
    public static String DB_NAME = "bxg.db";
    public static final String U_USER_INFO = "userInfo";

    public SQLiteHelper(Context context){
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        /**
         * 当这个SQLiteOpenHelper的子类类被实例化时会创建指定名的数据库,在onCreate中创建个人信息表
         * **/
        db.execSQL("CREATE TABLE IF NOT EXISTS " + U_USER_INFO + "( "
                + "_id  INTEGER PRIMARY KEY AUTOINCREMENT, "
                + "userName VARCHAR, "
                + "nickName VARCHAR, "
                + "sex VARCHAR, "
                + "signature VARCHAR, "
                + "qq VARCHAR "
                + ")");
    }

    /**
     * 当数据库版本号增加才会调用此方法
     **/
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + U_USER_INFO);
        onCreate(db);
    }
}

UserBean.java

package cn.edu.gdmec.android.boxuegu.bean;

public class UserBean {
    public String userName;//用户名
    public String nickName;//昵称
    public String sex;//性别
    public String signature;//签名
    public String qq;//qq
}

UserInfoActivity.java

package cn.edu.gdmec.android.boxuegu.activity;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.bean.UserBean;
import cn.edu.gdmec.android.boxuegu.utils.AnalysisUtils;
import cn.edu.gdmec.android.boxuegu.utils.DBUtils;

public class UserInfoActivity extends Activity implements View.OnClickListener{
    //标题栏
    private RelativeLayout title_bar;
    private TextView tv_back;
    private TextView tv_main_title;
    //
    private RelativeLayout rl_head;
    private ImageView iv_head_icon;
    private RelativeLayout rl_account;//
    private TextView tv_user_name;
    private RelativeLayout rl_nickName;
    private TextView tv_nick_name;
    private RelativeLayout rl_sex;
    private TextView tv_sex;
    private RelativeLayout rl_signature;
    private TextView tv_signature;
    private RelativeLayout rl_qq;
    private TextView tv_qq;
    //
    private String spUserName;
    private String new_info;
    private static final int CHANGE_NICKNAME = 1;
    private static final int CHANGE_SIGNATURE = 2;
    private static final int CHANGE_QQ = 3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_info);
        //设置此界面为竖屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        spUserName= AnalysisUtils.readLoginUserName(this);
        initView();
        initDate();
    }
    private void initDate() {
        UserBean bean = null;
        //实例化DBUtils,同时调用其方法获取个人信息资料
        bean = DBUtils.getInstance(this).getUserInfo(spUserName);
        //如果第一次进入,数据库没有保留用户信息
        if (bean == null) {
            bean = new UserBean();
            bean.userName = spUserName;
            bean.nickName = "问答精灵";
            bean.sex = "男";
            bean.signature = "这个人很懒,什么都没留下...";
            bean.qq = "未添加";
            //保存到数据库
            DBUtils.getInstance(this).saveUserInfo(bean);
        }
        setValue(bean);
    }
    private void initView() {
        //个人资料界面
        tv_back = findViewById(R.id.tv_back);
        tv_main_title = findViewById(R.id.tv_main_title);
        tv_main_title.setText("个人资料界面");
        title_bar = findViewById(R.id.title_bar);
        title_bar.setBackgroundColor(Color.parseColor("#30B4FF"));
        /**
         * rl_head iv_head_icon
         * rl_account tv_user_name
         * rl_nickName tv_nick_name
         * rl_sex tv_sex
         * rl_signature tv_signature
         * rl_qq tv_qq
         */
        rl_head=findViewById(R.id.rl_head);
        iv_head_icon=findViewById(R.id.iv_head_icon);
        rl_account=findViewById(R.id.rl_account);
        tv_user_name=findViewById(R.id.tv_user_name);
        rl_nickName=findViewById(R.id.rl_nickName);
        tv_nick_name=findViewById(R.id.tv_nick_name);
        rl_sex=findViewById(R.id.rl_sex);
        tv_sex=findViewById(R.id.tv_sex);
        rl_signature=findViewById(R.id.rl_signature);
        tv_signature=findViewById(R.id.tv_signature);
        rl_qq=findViewById(R.id.rl_qq);
        tv_qq=findViewById(R.id.tv_qq);
        //
        tv_back.setOnClickListener(this);
        rl_head.setOnClickListener(this);
        rl_account.setOnClickListener(this);
        rl_nickName.setOnClickListener(this);
        rl_sex.setOnClickListener(this);
        rl_signature.setOnClickListener(this);
        rl_qq.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_back:
                this.finish();
                break;
            case R.id.rl_nickName:
                //昵称
                String name = tv_nick_name.getText().toString();
                Bundle bdName = new Bundle();
                bdName.putString("content", name);      //传递界面上的昵称数据
                bdName.putString("title", "昵称");
                bdName.putInt("flag", 1);
                //ActivityUserInfoActivity的Onclick()里昵称和签名响应加上跳转代码
                enterActivityForResult(ChangeUserInfoActivity.class, CHANGE_NICKNAME, bdName);//跳转到修改界面
                break;
            case R.id.rl_sex:
                String sex = tv_sex.getText().toString();
                sexDialog(sex);
                break;
            case R.id.rl_signature:
                //签名
                String signature = tv_signature.getText().toString();
                Bundle bdSignature = new Bundle();
                bdSignature.putString("content", signature); //传递界面上的签名数据
                bdSignature.putString("title", "签名");
                bdSignature.putInt("flag", 2);
                //ActivityUserInfoActivity的Onclick()里昵称和签名响应加上跳转代码
                enterActivityForResult(ChangeUserInfoActivity.class, CHANGE_SIGNATURE, bdSignature);
                break;
            case R.id.rl_qq:
                String qq = tv_qq.getText().toString();
                Bundle bdqq = new Bundle();
                bdqq.putString("content", qq); //传递界面上的签名数据
                bdqq.putString("title", "QQ号");
                bdqq.putInt("flag", 3);
                //ActivityUserInfoActivity的Onclick()里昵称和签名响应加上跳转代码
                enterActivityForResult(ChangeUserInfoActivity.class, CHANGE_QQ, bdqq);
                break;
            default:
                break;
        }
    }

    /**
     * 为界面空间设置值
     **/
    private void setValue(UserBean bean) {
        tv_user_name.setText(bean.userName);
        tv_nick_name.setText(bean.nickName);
        tv_sex.setText(bean.sex);
        tv_signature.setText(bean.signature);
        tv_qq.setText(bean.qq);
    }
    /**
     * 设置性别弹出框
     **/
    private void sexDialog(String sex) {
        int sexFlag = 0;
        if ("男".equals(sex)) {
            sexFlag = 0;
        } else if ("女".equals(sex)) {
            sexFlag = 1;
        }
        final String items[] = {"男", "女"};
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("性别");
        //sexFlag用来区分显示被选中项,如果sexFlag的值和在数组中的索引严格符合,下方which也可用sexFlag代替
        builder.setSingleChoiceItems(items, sexFlag, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                Toast.makeText(UserInfoActivity.this, items[which], Toast.LENGTH_SHORT).show();
                setSex(items[which]);
            }
        });
        builder.create().show();
    }
    /**
     * 更新性别数据
     **/
    private void setSex(String sex) {
        tv_sex.setText(sex);
        //更新数据库字段
        DBUtils.getInstance(this).updateUserInfo("sex", sex, spUserName);
    }

    /**
     * 其实就是把需要传递的数值放置于bundle中,bundle作为附加到intent中
     * 获取回传数据是需要的跳转方法,第三个参数标示跳转是传递的数据
     **/
    public void enterActivityForResult(Class<?> to, int requestCode, Bundle b) {
        Intent i = new Intent(this, to);
        i.putExtras(b);
        startActivityForResult(i, requestCode);
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case CHANGE_NICKNAME:
                if (data != null) {
                    new_info = data.getStringExtra("nickName");
                    if (TextUtils.isEmpty(new_info)) {
                        return;
                    }
                    tv_nick_name.setText(new_info);
                    //更新数据库中昵称字段
                    DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("nickName",
                            new_info, spUserName);
                }
                break;
            case CHANGE_SIGNATURE:
                if (data != null) {
                    new_info = data.getStringExtra("signature");
                    if (TextUtils.isEmpty(new_info)) {
                        return;
                    }
                    tv_signature.setText(new_info);
                    //更新数据库中签名字段
                    DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("signature",
                            new_info, spUserName);
                }
                break;
            case CHANGE_QQ:
                if (data != null) {
                    new_info = data.getStringExtra("qq");
                    if (TextUtils.isEmpty(new_info)) {
                        return;
                    }
                    tv_qq.setText(new_info);
                    //更新数据库中QQ字段
                    DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("qq",
                            new_info, spUserName);
                }
                break;
        }
    }
}

ChangeUserInfoActivity.java

package cn.edu.gdmec.android.boxuegu.activity;

import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.Selection;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import cn.edu.gdmec.android.boxuegu.R;

public class ChangeUserInfoActivity extends AppCompatActivity implements View.OnClickListener{
    //标题栏
    private TextView tv_back;
    private TextView tv_main_title;
    private TextView tv_save;
    private RelativeLayout rl_title_bar;
    //
    private EditText et_content;
    private ImageView iv_delete;
    private String title, content;
    private int flag;  //flag为1时表示修改昵称,为2时表示修改签名,为3时表示修改QQ号
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_change_user_info);
        //设置此界面为竖屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        initView();
    }
    private void initView() {
        tv_back = (TextView) findViewById(R.id.tv_back);
        tv_main_title = (TextView) findViewById(R.id.tv_main_title);
        tv_save = (TextView) findViewById(R.id.tv_save);
        rl_title_bar = (RelativeLayout) findViewById(R.id.title_bar);
        et_content = (EditText) findViewById(R.id.et_content);
        iv_delete = (ImageView) findViewById(R.id.iv_delete);
        //从个人资料界面传递过来的标题和内容
        title = getIntent().getStringExtra("title");
        content = getIntent().getStringExtra("content");
        flag = getIntent().getIntExtra("flag", 0);
        tv_main_title.setText(title);
        tv_save.setVisibility(View.VISIBLE);
        rl_title_bar.setBackgroundColor(Color.parseColor("#30B4FF"));

        tv_back.setOnClickListener(this);
        iv_delete.setOnClickListener(this);
        tv_save.setOnClickListener(this);

        if (!TextUtils.isEmpty(content)){
            et_content.setText(content);
            et_content.setSelection(content.length());
        }
        contentListener();
    }

    /**
     * 监听个人资料修改界面输入的文字
     **/
    private void contentListener() {
        et_content.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                Editable editable = et_content.getText();
                int len = editable.length();//输入文本的长度
                if (len >= 0) {
                    iv_delete.setVisibility(View.VISIBLE);
                } else {
                    iv_delete.setVisibility(View.GONE);
                }
                switch (flag) {
                    case 1://昵称,最多8个文字,超过则截取多余文字
                        if (len > 8) {
                            int selEndIndex = Selection.getSelectionEnd(editable);
                            String str = editable.toString();
                            //截取新字符串
                            String newStr = str.substring(0, 8);
                            et_content.setText(newStr);
                            editable = et_content.getText();
                            //新字符串长度
                            int newLen = editable.length();
                            //旧光标位置超过新字符串长度
                            if (selEndIndex > newLen) {
                                selEndIndex = editable.length();
                            }
                            //设置新光标所在位置
                            Selection.setSelection(editable, selEndIndex);
                        }
                        break;
                    case 2: //签名,做多16,
                        if (len > 16) {
                            int selEndIndex = Selection.getSelectionEnd(editable);
                            String str = editable.toString();
                            String newStr = str.substring(0, 16);
                            et_content.setText(newStr);
                            editable = et_content.getText();
                            int newLen = editable.length();
                            if (selEndIndex > newLen) {
                                selEndIndex = editable.length();
                            }
                            Selection.setSelection(editable, selEndIndex);
                        }
                        break;
                    case 3: //qq,做多16,
                        if (len > 12) {
                            int selEndIndex = Selection.getSelectionEnd(editable);
                            String str = editable.toString();
                            String newStr = str.substring(0, 12);
                            et_content.setText(newStr);
                            editable = et_content.getText();
                            int newLen = editable.length();
                            if (selEndIndex > newLen) {
                                selEndIndex = editable.length();
                            }
                            Selection.setSelection(editable, selEndIndex);
                        }
                        break;
                    default:
                        break;
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.tv_back:
                finish();
                break;
            case R.id.iv_delete:
                et_content.setText("");
                break;
            case R.id.tv_save:
                Intent data = new Intent();
                String etContent = et_content.getText().toString().trim();
                switch (flag) {
                    case 1:
                        if (!TextUtils.isEmpty(etContent)) {
                            data.putExtra("nickName", etContent);
                            setResult(RESULT_OK, data);
                            Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
                            ChangeUserInfoActivity.this.finish();
                        } else {
                            Toast.makeText(this, "昵称不能为空", Toast.LENGTH_SHORT).show();
                        }
                        break;
                    case 2:
                        if (!TextUtils.isEmpty(etContent)) {
                            data.putExtra("signature", etContent);
                            setResult(RESULT_OK, data);
                            Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
                            ChangeUserInfoActivity.this.finish();
                        } else {
                            Toast.makeText(this, "签名不能为空", Toast.LENGTH_SHORT).show();
                        }
                        break;
                    case 3:
                        if (!TextUtils.isEmpty(etContent)) {
                            data.putExtra("qq", etContent);
                            setResult(RESULT_OK, data);
                            Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
                            ChangeUserInfoActivity.this.finish();
                        } else {
                            Toast.makeText(this, "QQ号不能为空", Toast.LENGTH_SHORT).show();
                        }
                        break;
                }
        }
    }
}

ok,大功告成!

教育系统APP(六)-“习题”的模块

项目实操

习题

习题界面
习题界面Adapter
习题界面逻辑代码

习题详情

习题详情界面

习题数据

习题详情界面adapter
习题详情逻辑代码

任务实施

判断题数
保存答题状态

学习目标

掌握习题列表界面的开发,实现用ListView完成习题列表的展示
掌握习题详情界面的开发,实现用RecyclerView完成习题详情的展示
习题模块主要以习题的形式来检测学生对教材中知识点的掌握情况。当点击习题列表时会跳转到习题详情界面,在该界面中点击选项时会立即显示正确答案。本章将针对习题模块进行详细讲解。

项目实操

习题
习题界面
导入图片

26

修改fragment_exercises.xml

<?xml version="1.0" encoding="utf-8"?>
<!--练习界面布局-->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/white">
    <ListView
        android:id="@+id/lv_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginBottom="55dp"
        android:divider="#E4E4E4"
        android:dividerHeight="1dp">
    </ListView>
</LinearLayout>

这是ListVIew的第一步。接下来实ListView中的每一列Item。
在layout文件夹中创建一个布局文件,命名为exercise_list_item.xml
item里放3个TextView控件,分别为习题序号、章节标题、习题数量。

exercise_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<!--练习列表项布局-->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="horizontal"
    android:paddingBottom="15dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="15dp">
    <TextView
        android:id="@+id/tv_order"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        android:background="@drawable/exercises_bg_1"
        android:gravity="center"
        android:textColor="@android:color/white"
        android:textSize="16sp"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="15dp"
        android:gravity="center_vertical"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="第一章Android基础入门"
            android:textColor="#000000"
            android:textSize="14sp"/>
        <!--android:singleLine="true"-->
        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="2dp"
            android:text="共计5题"
            android:textColor="#a3a3a3"
            android:textSize="12sp"/>
        <!--android:singleLine="true"-->
    </LinearLayout>
</LinearLayout>

ListView的列表和单列布局写完后,我们先来给我们的数据定一个属性类。
在bean包中创建一个ExercisesBean类。

ExercisesBean.java

package cn.edu.gdmec.android.boxuegu.bean;

public class ExercisesBean {
    public int id;//每章习题id
    public String title;//每章习题标题
    public String content;//每章习题的数目
    public int background;//每章习题前边的序号背景
    public int subjectId;//每道习题的ID
    public String subject;//每道习题的题干
    public String a;//每道题的A选项
    public String b;//每道题的B选项
    public String c;//每道题的C选项
    public String d;//每道题的D选项
    public int answer;//每道题的正确答案
    public int select;//用户选中的那项
}

习题界面Adapter
ListView需要一个数据适配器对其进行数据适配,即Adapter。这是使用一个ListView的第三个步骤。我们可以在exercise_list_item.xml中用插件直接生成一个Adapter,里面自动帮我们写好了ViewHolder(可以减少缓存)。

新建一个Adapter包,把我们的Adapter移进去,在adapter包中,创建ExercisesListItemAdapter.java

ExercisesListItemAdapter.java

package cn.edu.gdmec.android.boxuegu.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.bean.ExercisesBean;

public class ExercisesListItemAdapter extends BaseAdapter {

    private List<ExercisesBean> objects = new ArrayList<ExercisesBean>();
    private Context context;
    private LayoutInflater layoutInflater;

    public ExercisesListItemAdapter(Context context){
        this.context=context;
        this.layoutInflater=LayoutInflater.from(context);
    }
    /**
     * 设置数据更新界面
     */
    public void setData(List<ExercisesBean> objects){
        this.objects = objects;
        notifyDataSetChanged();
    }
    //
    public void updateView(List<ExercisesBean> objects){
        this.objects = objects;
        this.notifyDataSetChanged();
    }
    @Override
    public int getCount() {
        return objects == null ? 0 : objects.size();
    }

    /**
     * 根据position得到对应的Item的对象
     */
    @Override
    public ExercisesBean getItem(int position) {
        return objects.get(position);
    }

    /**
     * 根据position得到对应Item的对象
     */
    @Override
    public long getItemId(int position) {
        return position;
    }

    /**
     * 得到相应position对应的Item视图,position是当前Item的位置
     * convertView参数就是滚出屏幕的Item的View
     * 第一次进入或滑动屏幕时候被调用
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.exercises_list_item, null);
            convertView.setTag(new ViewHolder(convertView));
        }
        initializeViews((ExercisesBean) getItem(position), (ViewHolder) convertView.getTag(),
                position, convertView);
        return convertView;
    }

    private void initializeViews(ExercisesBean object, ViewHolder holder,
                                 int position, View convertView) {
        final ExercisesBean bean = getItem(position);
        if (bean != null) {
            holder.tvOrder.setText(position + 1 + "");
            holder.tvTitle.setText(bean.title);
            holder.tvOrder.setBackgroundResource(bean.background);
            convertView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (bean == null) {
                        return;
                    }
                    //跳转到习题界面
                }
            });
        }
    }

    protected class ViewHolder {
        private TextView tvOrder;
        private TextView tvTitle;
        private TextView tvContent;

        public ViewHolder(View view) {
            tvOrder = (TextView) view.findViewById(R.id.tv_order);
            tvTitle = (TextView) view.findViewById(R.id.tv_title);
            tvContent = (TextView) view.findViewById(R.id.tv_content);
        }
    }
}

习题界面逻辑代码
写完了适配器,我们来做ListView的第5步,我们回到fragment界面完善习题界面的逻辑代码。
ExercisesFragment.java

package cn.edu.gdmec.android.boxuegu.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.adapter.ExercisesListItemAdapter;
import cn.edu.gdmec.android.boxuegu.bean.ExercisesBean;

public class ExercisesFragment extends Fragment {

    private ListView lvList;//来源fragment_exercises
    private ExercisesListItemAdapter adapter; //适配器
    private List<ExercisesBean> ebl; //列表集合

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_exercises, null);
    }
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initData();
        lvList = view.findViewById(R.id.lv_list);
        adapter = new ExercisesListItemAdapter(getActivity());
        adapter.setData(ebl);
        lvList.setAdapter(adapter);
    }

    private void initData(){
        ebl = new ArrayList<ExercisesBean>();
        for (int i=0;i<10;i++){
            ExercisesBean bean = new ExercisesBean();
            bean.id=(i+1);
            switch (i){
                case 0:
                    bean.title="第1章 Android基础入门";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_1);
                    break;
                case 1:
                    bean.title="第2章 Android UI开发";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_2);
                    break;
                case 2:
                    bean.title="第3章 Activity";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_3);
                    break;
                case 3:
                    bean.title="第4章 数据存储";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_4);
                    break;
                case 4:
                    bean.title="第5章 SQLite数据库";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_1);
                    break;
                case 5:
                    bean.title="第6章 广播接收者";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_2);
                    break;
                case 6:
                    bean.title="第7章 服务";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_3);
                    break;
                case 7:
                    bean.title="第8章 内容提供者";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_4);
                    break;
                case 8:
                    bean.title="第9章 网络编程";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_1);
                    break;
                case 9:
                    bean.title="第10章 高级编程";
                    bean.content="共计5题";
                    bean.background=(R.drawable.exercises_bg_2);
                    break;
                default:
                    break;
            }
            ebl.add(bean);
        }
    }
}

习题详情

习题详情界面
习题界面我们用ListView,习题详情我们来用一下RecyclerView。
新建一个布局文件,命名为activity_exercises_detail.xml

activity_exercises_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical">
    <!--标题栏-->
    <include layout="@layout/main_title_bar"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="15dp"
        android:text="选择题"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="16sp"
        android:textStyle="bold"/>
    <!--android:visibility="gone"-->
    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:id="@+id/rv_list"
        />
    <!--<ListView
        android:id="@+id/lv_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:divider="@null"/>-->
    <TextView
        android:id="@+id/tv_di"
        android:text="第一页"
        android:gravity="center"
        android:textSize="20sp"
        android:textColor="@android:color/black"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

注意:很多同学的项目可能会出现找不到v7.widget.RecyclerView的情况。具体解决办法参考:
https://blog.csdn.net/u011150924/article/details/52298445
顺便截一下我自己的build.gradle(Moudle:app)的图给大家做参考

27

导入完成后,我们来给recyclerView写个item,没错,和ListView很相似。
新建一个布局文件,命名为exercises_detail_list_item.xml

exercises_detail_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<!--练习题目布局-->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical"
    android:padding="15dp">
    <TextView
        android:id="@+id/tv_subject"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:lineSpacingMultiplier="1.5"
        android:textColor="#000000"
        android:textSize="14sp"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv_a"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:src="@drawable/exercises_a"/>
        <TextView
            android:id="@+id/tv_a"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="8dp"
            android:lineSpacingMultiplier="1.5"
            android:textColor="#000000"
            android:textSize="12sp"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv_b"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:src="@drawable/exercises_b"/>
        <TextView
            android:id="@+id/tv_b"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="8dp"
            android:lineSpacingMultiplier="1.5"
            android:textColor="#000000"
            android:textSize="12sp"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv_c"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:src="@drawable/exercises_c"/>
        <TextView
            android:id="@+id/tv_c"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="8dp"
            android:lineSpacingMultiplier="1.5"
            android:textColor="#000000"
            android:textSize="12sp"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv_d"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:src="@drawable/exercises_d"/>
        <TextView
            android:id="@+id/tv_d"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="8dp"
            android:lineSpacingMultiplier="1.5"
            android:textColor="#000000"
            android:textSize="12sp"/>

    </LinearLayout>
</LinearLayout>

习题数据

写完了item的布局,先别急着写适配器,我们下来解决题目数据的读取。
创建一个文件夹assets,把项目资源中的XML文件都放进去。

28

我们需要一个XML数据解析方法来解析这些文件。
到AnalysisUtils.java中添加一个getExercisesInfos()方法。
AnalysisUtils.java

    public static List<ExercisesBean> getExercisesInfos(InputStream is) throws Exception{
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(is,"utf-8");
        List<ExercisesBean> exercisesInfos=null;
        ExercisesBean exercisesInfo=null;
        int type = parser.getEventType();
        while (type!=XmlPullParser.END_DOCUMENT){
            switch (type){
                case XmlPullParser.START_TAG:
                    if ("infos".equals(parser.getName())){
                        exercisesInfos=new ArrayList<ExercisesBean>();
                    }else if ("exercises".equals(parser.getName())){
                        exercisesInfo=new ExercisesBean();
                        String ids=parser.getAttributeValue(0);
                        exercisesInfo.subjectId = Integer.parseInt(ids);
                    }else if ("subject".equals(parser.getName())){
                        String subject=parser.nextText();
                        exercisesInfo.subject = subject;
                    }else if ("a".equals(parser.getName())){
                        String a=parser.nextText();
                        exercisesInfo.a = a;
                    }else if ("b".equals(parser.getName())){
                        String b=parser.nextText();
                        exercisesInfo.b = b;
                    }else if ("c".equals(parser.getName())){
                        String c=parser.nextText();
                        exercisesInfo.c = c;
                    }else if ("d".equals(parser.getName())){
                        String d=parser.nextText();
                        exercisesInfo.d = d;
                    }else if ("answer".equals(parser.getName())){
                        String answer=parser.nextText();
                        exercisesInfo.answer = Integer.parseInt(answer);
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if ("exercises".equals(parser.getName())){
                        exercisesInfos.add(exercisesInfo);
                        exercisesInfo=null;
                    }
                    break;
            }
            type=parser.next();
        }
        return exercisesInfos;
    }

再添加一个setABCDEnable()方法。
AnalysisUtils.java

        iv_a.setEnabled(value);
        iv_b.setEnabled(value);
        iv_c.setEnabled(value);
        iv_d.setEnabled(value);
    }

习题详情界面adapter

习题详情界面的适配器不再继承BaseAdapter了,改为继承RecyclerView的RecyclerView.Adapter<>,里面填上自己的ViewHolder,下面是适配器的代码,大家可以观察一下跟ListView的适配器有哪些不同。
还是从item界面用插件生成adapter,但是Code generator 生成的只有继承BaseAdapter的文件,所以需要一些修改。
ExercisesDetailListItemAdapter.java

写到这里,注意了!你会发现会红,那是因为你没有添加依赖!

implementation 'com.android.support:recyclerview-v7:26.1.0'

创建ExercisesDetailListItemAdapter.java

package cn.edu.gdmec.android.boxuegu.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.bean.ExercisesBean;
import cn.edu.gdmec.android.boxuegu.utils.AnalysisUtils;

public class ExercisesDetailListItemAdapter extends
        RecyclerView.Adapter<ExercisesDetailListItemAdapter.ViewHolder> {
    private List<ExercisesBean> objects = new ArrayList<ExercisesBean>();
    private ArrayList<String> selectedPosition = new ArrayList<String>();
    private Context context;
    private LayoutInflater layoutInflater;
    private OnSelectListener onSelectListener;

    public ExercisesDetailListItemAdapter(Context context, OnSelectListener onSelectListener) {
        this.context = context;
        this.onSelectListener = onSelectListener;
        this.layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.exercises_detail_list_item, parent,
                false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        initializeViews(objects.get(position), holder, position);
    }

    public void setData(List<ExercisesBean> objects) {
        this.objects = objects;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemCount() {
        return objects.size();
    }

    private void initializeViews(ExercisesBean object, final ViewHolder holder,
                                 final int position) {
        ExercisesBean bean = object;
        if (bean != null) {
            holder.tvSubject.setText(bean.subject);
            holder.tvA.setText(bean.a);
            holder.tvB.setText(bean.b);
            holder.tvC.setText(bean.c);
            holder.tvD.setText(bean.d);
        }
        if (!selectedPosition.contains("" + position)) {
            holder.ivA.setImageResource(R.drawable.exercises_a);
            holder.ivB.setImageResource(R.drawable.exercises_b);
            holder.ivC.setImageResource(R.drawable.exercises_c);
            holder.ivD.setImageResource(R.drawable.exercises_d);
            AnalysisUtils.setABCDEnable(true, holder.ivA, holder.ivB, holder.ivC,
                    holder.ivD);
        } else {
            AnalysisUtils.setABCDEnable(false, holder.ivA, holder.ivB, holder.ivC,
                    holder.ivD);
            switch (bean.select) {
                case 0:
                    if (bean.answer == 1) {
                        holder.ivA.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 2) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivB.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 3) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivC.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 4) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                        holder.ivD.setImageResource(R.drawable.exercises_right_icon);
                    }
                    break;
                case 1:
                    holder.ivA.setImageResource(R.drawable.exercises_error_icon);
                    if (bean.answer == 2) {
                        holder.ivB.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 3) {
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivC.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 4) {
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                        holder.ivD.setImageResource(R.drawable.exercises_right_icon);
                    }
                    break;
                case 2:
                    holder.ivB.setImageResource(R.drawable.exercises_error_icon);
                    if (bean.answer == 1) {
                        holder.ivA.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 3) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivC.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 4) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                        holder.ivD.setImageResource(R.drawable.exercises_right_icon);
                    }
                    break;
                case 3:
                    holder.ivC.setImageResource(R.drawable.exercises_error_icon);
                    if (bean.answer == 1) {
                        holder.ivA.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 2) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivB.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivD.setImageResource(R.drawable.exercises_d);
                    } else if (bean.answer == 4) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivD.setImageResource(R.drawable.exercises_right_icon);
                    }
                    break;
                case 4:
                    holder.ivD.setImageResource(R.drawable.exercises_error_icon);
                    if (bean.answer == 1) {
                        holder.ivA.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                    } else if (bean.answer == 2) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivB.setImageResource(R.drawable.exercises_right_icon);
                        holder.ivC.setImageResource(R.drawable.exercises_c);
                    } else if (bean.answer == 3) {
                        holder.ivA.setImageResource(R.drawable.exercises_a);
                        holder.ivB.setImageResource(R.drawable.exercises_b);
                        holder.ivC.setImageResource(R.drawable.exercises_right_icon);
                    }
                    break;

            }

        }
        holder.ivA.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (selectedPosition.contains("" + position)) {
                    selectedPosition.remove("" + position);
                } else {
                    selectedPosition.add(position + "");
                }
                onSelectListener.onSelectA(position, holder.ivA,
                        holder.ivB, holder.ivC, holder.ivD);
            }
        });
        holder.ivB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (selectedPosition.contains("" + position)) {
                    selectedPosition.remove("" + position);
                } else {
                    selectedPosition.add(position + "");
                }
                onSelectListener.onSelectB(position, holder.ivA,
                        holder.ivB, holder.ivC, holder.ivD);
            }
        });
        holder.ivC.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (selectedPosition.contains("" + position)) {
                    selectedPosition.remove("" + position);
                } else {
                    selectedPosition.add(position + "");
                }
                onSelectListener.onSelectC(position, holder.ivA,
                        holder.ivB, holder.ivC, holder.ivD);
            }
        });
        holder.ivD.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (selectedPosition.contains("" + position)) {
                    selectedPosition.remove("" + position);
                } else {
                    selectedPosition.add(position + "");
                }
                onSelectListener.onSelectD(position, holder.ivA,
                        holder.ivB, holder.ivC, holder.ivD);
            }
        });

    }


    protected class ViewHolder extends RecyclerView.ViewHolder {
        private TextView tvSubject;
        private ImageView ivA;
        private TextView tvA;
        private ImageView ivB;
        private TextView tvB;
        private ImageView ivC;
        private TextView tvC;
        private ImageView ivD;
        private TextView tvD;

        public ViewHolder(View view) {
            super(view);
            tvSubject = (TextView) view.findViewById(R.id.tv_subject);
            ivA = (ImageView) view.findViewById(R.id.iv_a);
            tvA = (TextView) view.findViewById(R.id.tv_a);
            ivB = (ImageView) view.findViewById(R.id.iv_b);
            tvB = (TextView) view.findViewById(R.id.tv_b);
            ivC = (ImageView) view.findViewById(R.id.iv_c);
            tvC = (TextView) view.findViewById(R.id.tv_c);
            ivD = (ImageView) view.findViewById(R.id.iv_d);
            tvD = (TextView) view.findViewById(R.id.tv_d);
        }
    }

    public interface OnSelectListener {
        void onSelectA(int position, ImageView iv_a,
                       ImageView iv_b, ImageView iv_c,
                       ImageView iv_d);

        void onSelectB(int position, ImageView iv_a,
                       ImageView iv_b, ImageView iv_c,
                       ImageView iv_d);

        void onSelectC(int position, ImageView iv_a,
                       ImageView iv_b, ImageView iv_c,
                       ImageView iv_d);

        void onSelectD(int position, ImageView iv_a,
                       ImageView iv_b, ImageView iv_c,
                       ImageView iv_d);
    }
}

添加依赖后进入build.gradle(Module.app)进行修改,注意进行理解,模仿!

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    implementation 'com.android.support:recyclerview-v7:26.1.0'
}

习题详情逻辑代码

为了体现出RecyclerView的异同,我将习题详情显示改为横向显示。

创建ExercisesDetailActivity.java

package cn.edu.gdmec.android.boxuegu.activity;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.adapter.ExercisesDetailListItemAdapter;
import cn.edu.gdmec.android.boxuegu.bean.ExercisesBean;
import cn.edu.gdmec.android.boxuegu.utils.AnalysisUtils;

public class ExercisesDetailActivity extends Activity {
    private TextView tv_back;
    private TextView tv_main_title;
    private RelativeLayout title_bar;
    private int id;
    private String title;
    private RecyclerView rv_list;

    private List<ExercisesBean> ebl;
    private ExercisesDetailListItemAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exercises_detail);
        id = getIntent().getIntExtra("id",0);
        title = getIntent().getStringExtra("title");
        ebl = new ArrayList<ExercisesBean>();
        initData();
        initView();
    }

    private void initData() {
        //从xml文件中获取习题数据
        try {
            InputStream is = getResources().getAssets().open("chapter" + id + ".xml");
            ebl = AnalysisUtils.getExercisesInfos(is);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initView() {
        tv_back = findViewById(R.id.tv_back);
        tv_main_title = findViewById(R.id.tv_main_title);
        tv_main_title.setText(title);
        title_bar = findViewById(R.id.title_bar);
        title_bar.setBackgroundColor(Color.parseColor("#30B4FF"));
        //
        rv_list = findViewById(R.id.rv_list);
        rv_list.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));

        tv_back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ExercisesDetailActivity.this.finish();
            }
        });
        adapter = new ExercisesDetailListItemAdapter(ExercisesDetailActivity.this,
                new ExercisesDetailListItemAdapter.OnSelectListener() {
                    @Override
                    public void onSelectA(int position, ImageView iv_a, ImageView iv_b, ImageView iv_c, ImageView iv_d) {
                        //判断如果答案不是1即A选项
                        if (ebl.get(position).answer != 1) {
                            ebl.get(position).select = 1;
                        } else {
                            ebl.get(position).select = 0;
                        }
                        switch (ebl.get(position).answer) {
                            case 1:
                                iv_a.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 2:
                                iv_a.setImageResource(R.drawable.exercises_error_icon);
                                iv_b.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 3:
                                iv_a.setImageResource(R.drawable.exercises_error_icon);
                                iv_c.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 4:
                                iv_a.setImageResource(R.drawable.exercises_error_icon);
                                iv_d.setImageResource(R.drawable.exercises_right_icon);
                                break;
                        }
                        AnalysisUtils.setABCDEnable(false, iv_a, iv_b, iv_c, iv_d);
                    }

                    @Override
                    public void onSelectB(int position, ImageView iv_a, ImageView iv_b, ImageView iv_c, ImageView iv_d) {
                        //判断如果答案不是2即B选项
                        if (ebl.get(position).answer != 2) {
                            ebl.get(position).select = 2;
                        } else {
                            ebl.get(position).select = 0;
                        }
                        switch (ebl.get(position).answer) {
                            case 1:
                                iv_a.setImageResource(R.drawable.exercises_right_icon);
                                iv_b.setImageResource(R.drawable.exercises_error_icon);
                                break;
                            case 2:
                                iv_b.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 3:
                                iv_b.setImageResource(R.drawable.exercises_error_icon);
                                iv_c.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 4:
                                iv_b.setImageResource(R.drawable.exercises_error_icon);
                                iv_d.setImageResource(R.drawable.exercises_right_icon);
                                break;
                        }
                        AnalysisUtils.setABCDEnable(false, iv_a, iv_b, iv_c, iv_d);
                    }

                    @Override
                    public void onSelectC(int position, ImageView iv_a, ImageView iv_b, ImageView iv_c, ImageView iv_d) {
                        //判断如果答案不是3即C选项
                        if (ebl.get(position).answer != 3) {
                            ebl.get(position).select = 3;
                        } else {
                            ebl.get(position).select = 0;
                        }
                        switch (ebl.get(position).answer) {
                            case 1:
                                iv_a.setImageResource(R.drawable.exercises_right_icon);
                                iv_c.setImageResource(R.drawable.exercises_error_icon);
                                break;
                            case 2:
                                iv_b.setImageResource(R.drawable.exercises_right_icon);
                                iv_c.setImageResource(R.drawable.exercises_error_icon);
                                break;
                            case 3:
                                iv_c.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 4:
                                iv_c.setImageResource(R.drawable.exercises_error_icon);
                                iv_d.setImageResource(R.drawable.exercises_right_icon);
                                break;
                        }
                        AnalysisUtils.setABCDEnable(false, iv_a, iv_b, iv_c, iv_d);
                    }

                    @Override
                    public void onSelectD(int position, ImageView iv_a, ImageView iv_b, ImageView iv_c, ImageView iv_d) {
                        //判断如果答案不是4即D选项
                        if (ebl.get(position).answer != 4) {
                            ebl.get(position).select = 4;
                        } else {
                            ebl.get(position).select = 0;
                        }
                        switch (ebl.get(position).answer) {
                            case 1:
                                iv_a.setImageResource(R.drawable.exercises_right_icon);
                                iv_d.setImageResource(R.drawable.exercises_error_icon);
                                break;
                            case 2:
                                iv_d.setImageResource(R.drawable.exercises_error_icon);
                                iv_b.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 3:
                                iv_d.setImageResource(R.drawable.exercises_error_icon);
                                iv_c.setImageResource(R.drawable.exercises_right_icon);
                                break;
                            case 4:
                                iv_d.setImageResource(R.drawable.exercises_right_icon);
                                break;
                        }
                        AnalysisUtils.setABCDEnable(false, iv_a, iv_b, iv_c, iv_d);
                    }
                });
        adapter.setData(ebl);
        rv_list.setAdapter(adapter);
    }
}

然后到ExercisesListItemAdapter.java中添加跳转页面的代码
ExercisesListItemAdapter.java

//跳转到习题界面
                    Intent intent = new Intent(context, ExercisesDetailActivity.class);
                    intent.putExtra("id", bean.id);
                    intent.putExtra("title", bean.title);
                    ((Activity) context).startActivityForResult(intent, 000);

到AndroidManifest.xml中声明ExercisesDetailActivity

<!--添加实现类-->
        <activity android:name=".activity.MainActivity"></activity>
        <activity android:name=".activity.LoginActivity"></activity>
        <activity android:name=".activity.RegisterActivity"></activity>
        <activity android:name=".activity.SettingActivity"></activity>
        <activity android:name=".activity.ModifyPswActivity"></activity>
        <activity android:name=".activity.FindPswActivity"></activity>
        <activity android:name=".activity.UserInfoActivity"></activity>
        <activity android:name=".activity.ChangeUserInfoActivity"></activity>
        <activity android:name=".activity.ExercisesDetailActivity"></activity>

如果有人有一些frgement刷新的小BUG

由于任务实施里需要用到回调,我们这里就先用startActivityForResult跳转(为了解决frgement刷新的小BUG)。也顺便给大家演示如何再adapter里使用startActivityForResult()。
再到MainActivity里添加回调方法。
MainActivity.java

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (data!=null){
            boolean isLogin=data.getBooleanExtra("isLogin",false);
            if (isLogin){
                setSelectStatus(0);
            }
            else {
                setSelectStatus(2);
            }
        }
        if (requestCode == 000) {
            setSelectStatus(1);
        }
    }

完成!可以运行了。

看看这次包结构的变化

31

32

任务实施

判断题数
点击完选项之后,底部的文本控件要变换刚刚点击的题目的题号。
注意:在里面用到adapter与Activity的信息回调,具体过程参考
https://blog.csdn.net/dl10210950/article/details/52918019

29

保存答题状态
当5道题都回答过一遍后,点击返回习题界面,习题下的文本标签要变成“已完成”。

30

总结

进步了哦~


文章作者: Jeskson
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Jeskson !
评论
 上一篇
教育系统APP(七) 教育系统APP(七)
用一切抱怨的时间去努力 ## 回顾上一期任务 判断题数点击完选项之后,底部的文本控件要变换刚刚点击的题目的题号。注意:在里面用到adapter与Activity的信息回调,具体过程参考 保存答题状态当5道题都回答过一遍后,点击返回习题
2018-04-27
下一篇 
教育系统APP(五) 教育系统APP(五)
用一切抱怨的时间去努力 ## 回顾上一期任务 ## 任务实施 修复fragment的小BUG在未登录状态下,点击“点击登陆”,登陆完成后,应该显示“我”的界面,并且正常显示用户名。 在登陆状态下,点击“设置”->点击退出登录,应该继
2018-04-25
  目录