安卓項目在線考試系統,防駕考寶典,送給在愁期末項目的學弟學妹們

在此聲明,此在線考試系統是利用業餘時間寫的一個Demo,功能並沒有完善,還有兩個功能模塊沒寫完,代碼註釋詳細,

並且我會在文章結尾附上源碼的下載地址。

我們先來看兩個功能模塊的效果圖,覺得喜歡你再下載源碼,由於github賬號忘記了,所以源碼只能放在博客裏.

注:次項目沒用到網絡,考試題目都來自己本地數據庫裏面的數據 數據表在res  raw下,名爲kaoshi.db

如有看不懂的地方,或者源碼跑不起來可關注我的快手id:北海狂鮫

私聊我 我看到了就會幫你解決

功能模塊一  順序練習

功能模塊二 隨機練習



下面上一部分代碼,代碼有點多,我就不全部貼上來了

首先在總佈局裏面我用到了約束佈局 需要導入一個依賴

compile 'com.android.support.constraint:constraint-layout:1.0.2'

然後就是一個db文件的數據庫, 數據結構如下(如果不會查看db文件,可查看我的上一篇博客,有介紹怎麼查看數據表)

接下來是總體的佈局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.hnkjxy.z.onlinetestsystemsdemo.MainActivity">

    <LinearLayout
        android:id="@+id/main_activity_headings"
        android:gravity="center"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:background="@color/LightBlue"
        android:layout_height="40dp">
        <TextView
            android:text="在線考試系統"
            android:textSize="20dp"
            android:textColor="@color/white"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
             />
    </LinearLayout>

    <LinearLayout
        app:layout_constraintTop_toBottomOf="@+id/main_activity_Wrong_topic_practise_imageView"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:background="@drawable/layout_round_a"
        android:layout_width="250dp"
        android:gravity="center"
        android:layout_height="250dp">
        <LinearLayout
            android:id="@+id/l2"
            android:gravity="center"
            android:background="@drawable/layout_round_b"
            android:layout_width="220dp"
            android:layout_height="220dp">
            <LinearLayout
                android:id="@+id/l3"
                android:background="@drawable/layout_round_c"
                android:layout_width="180dp"
                android:gravity="center"
                android:layout_height="180dp">
                <TextView
                    android:text="在線考試"
                    android:textColor="@color/white"
                    android:textSize="30dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

    <ImageView
        android:id="@+id/main_activity_simulation_test_imageView"
        android:layout_marginTop="20dp"
        app:layout_constraintTop_toBottomOf="@id/main_activity_headings"
        android:background="@mipmap/monikaoshi"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="30dp"/>
    <TextView
        android:id="@+id/main_activity_simulation_test_text"
        android:text="@string/simulationTest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/main_activity_simulation_test_imageView"
        app:layout_constraintLeft_toLeftOf="@id/main_activity_simulation_test_imageView"
        android:textSize="12dp"
        app:layout_constraintRight_toRightOf="@id/main_activity_simulation_test_imageView"
        android:layout_marginTop="10dp"/>

    <ImageView
        android:id="@+id/main_activity_Wrong_topic_practise_imageView"
        android:layout_marginTop="20dp"
        app:layout_constraintTop_toBottomOf="@id/main_activity_headings"
        android:background="@mipmap/cuoti"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginRight="30dp"/>
    <TextView
        android:id="@+id/main_activity_wrong_topic_practise_text"
        android:text="@string/wrongTopicpractise"
        android:textSize="12dp"
        app:layout_constraintLeft_toLeftOf="@id/main_activity_Wrong_topic_practise_imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/main_activity_Wrong_topic_practise_imageView"
        app:layout_constraintRight_toRightOf="@id/main_activity_Wrong_topic_practise_imageView"
        android:layout_marginTop="10dp"/>

    <ImageView
        android:id="@+id/main_activity_random_contact_imageView"
        app:layout_constraintTop_toBottomOf="@id/main_activity_Wrong_topic_practise_imageView"
        android:layout_marginTop="240dp"
        android:background="@mipmap/suiji"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginRight="30dp"/>
    <TextView
        android:id="@+id/main_activity_random_contact_text"
        android:text="@string/RandomContact"
        android:textSize="12dp"
        app:layout_constraintLeft_toLeftOf="@id/main_activity_random_contact_imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/main_activity_random_contact_imageView"
        app:layout_constraintRight_toRightOf="@id/main_activity_random_contact_imageView"
        android:layout_marginTop="10dp"/>

    <ImageView
        android:id="@+id/main_activity_my_collect_imageView"
        app:layout_constraintTop_toBottomOf="@id/main_activity_simulation_test_imageView"
        android:layout_marginTop="240dp"
        android:background="@mipmap/shoucang"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="30dp"/>
    <TextView
        android:id="@+id/main_activity_my_collect_text"
        android:text="@string/myCollect"
        android:textSize="12dp"
        app:layout_constraintLeft_toLeftOf="@id/main_activity_my_collect_imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/main_activity_my_collect_imageView"
        app:layout_constraintRight_toRightOf="@id/main_activity_my_collect_imageView"
        android:layout_marginTop="10dp"/>
</android.support.constraint.ConstraintLayout>

 注:佈局裏面用到了一些文字,圖片,還有背景樣式都在源碼裏,這裏我就貼部分出來,圖片就不貼了,源碼裏有

  接下來是背景,自定義的圓角

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false">
    <solid android:color="@color/a"/>
    <padding
        android:left="2dp"
        android:top="1dp"
        android:right="2dp"
        android:bottom="1dp" />
    <size android:width="15dp"
        android:height="15dp" />

</shape>

 還有就是文字了 我也貼一下吧

<resources>
    <string name="app_name">OnlineTestSystemsDemo</string>
    <string name="simulationTest">順序練習</string>
    <string name="wrongTopicpractise">錯題練習</string>
    <string name="myCollect">我的收藏</string>
    <string name="RandomContact">隨機練習</string>
</resources>

接下來就是MainActivity的代碼了,分別爲幾個功能模塊的點擊事件

package com.hnkjxy.z.onlinetestsystemsdemo;

import android.Manifest;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.hnkjxy.z.onlinetestsystemsdemo.othersActivity.OnlinetestActivity;
import com.hnkjxy.z.onlinetestsystemsdemo.othersActivity.RandomPracticeActivity;
import com.hnkjxy.z.onlinetestsystemsdemo.othersActivity.SimulationActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ImageView main_activity_simulation_test_imageView, main_activity_Wrong_topic_practise_imageView,
            main_activity_my_collect_imageView, main_activity_random_contact_imageView;
    TextView main_activity_simulation_test_text, main_activity_wrong_topic_practise_text,
            main_activity_my_collect_text, main_activity_random_contact_text;
    LinearLayout l3;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //        找activity_main佈局的方法
        activityMainFindViewById();
//        安卓動態申請權限  因爲在高版本的安卓手機上跑不申請會閃退  記住同時在Manifest裏配置權限
    //檢查權限
        if(ActivityCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
//            申請權限
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
            }

        if(ActivityCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)!= PackageManager.PERMISSION_GRANTED){
//            申請權限
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS},1);
        }
        if(ActivityCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
//            申請權限
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
        }
    }

    //        找activity_main佈局的方法
    private void activityMainFindViewById() {
//        佈局四個角落的圖片id
        main_activity_simulation_test_imageView = (ImageView) findViewById(R.id.main_activity_simulation_test_imageView);
        main_activity_Wrong_topic_practise_imageView = (ImageView) findViewById(R.id.main_activity_Wrong_topic_practise_imageView);
        main_activity_my_collect_imageView = (ImageView) findViewById(R.id.main_activity_my_collect_imageView);
        main_activity_random_contact_imageView = (ImageView) findViewById(R.id.main_activity_random_contact_imageView);
//     佈局四個圖片下的文字的id
        main_activity_simulation_test_text = (TextView) findViewById(R.id.main_activity_simulation_test_text);
        main_activity_wrong_topic_practise_text = (TextView) findViewById(R.id.main_activity_wrong_topic_practise_text);
        main_activity_my_collect_text = (TextView) findViewById(R.id.main_activity_my_collect_text);
        main_activity_random_contact_text = (TextView) findViewById(R.id.main_activity_random_contact_text);
//       linearlayout的佈局id
        l3 = (LinearLayout) findViewById(R.id.l3);
//
//     佈局id找到後開始給他們註冊點擊事件
//       註冊點擊事件的方法
        registrationSetOnClickListener();
    }

    //    註冊點擊事件方法
    private void registrationSetOnClickListener() {
        main_activity_simulation_test_imageView.setOnClickListener(this);
        main_activity_Wrong_topic_practise_imageView.setOnClickListener(this);
        main_activity_my_collect_imageView.setOnClickListener(this);
        main_activity_random_contact_imageView.setOnClickListener(this);

        main_activity_simulation_test_text.setOnClickListener(this);
        main_activity_wrong_topic_practise_text.setOnClickListener(this);
        main_activity_my_collect_text.setOnClickListener(this);
        main_activity_random_contact_text.setOnClickListener(this);

        l3.setOnClickListener(this);
    }


    //    這是實現OnClickListener接口必須寫的一個方法  ,在裏面寫點擊之後的邏輯
//    在代碼的第十行實現的接口
    @Override
    public void onClick(View v) {
        Intent intent;
        AlertDialog.Builder ad = new AlertDialog.Builder(MainActivity.this);
        switch (v.getId()) {
//            模擬考試和文字點擊事件的跳轉
            case R.id.main_activity_simulation_test_imageView:
                intent = new Intent(MainActivity.this, SimulationActivity.class);
                startActivity(intent);
                break;
            case R.id.main_activity_simulation_test_text:
                intent = new Intent(MainActivity.this, SimulationActivity.class);
                startActivity(intent);
                break;
//          在線考試的點擊事件
            case R.id.l3:
                intent = new Intent(MainActivity.this, OnlinetestActivity.class);
                startActivity(intent);
                break;
// 隨機練習文字的擊事件
            case R.id.main_activity_random_contact_text:
                intent = new Intent(MainActivity.this, RandomPracticeActivity.class);
                startActivity(intent);
                break;
//                隨機練習圖片的點擊事件
            case R.id.main_activity_random_contact_imageView:
                intent = new Intent(MainActivity.this, RandomPracticeActivity.class);
                startActivity(intent);
                break;

//                收藏的圖標點擊
            case R.id.main_activity_my_collect_imageView:
                ad.setTitle("通知");
                ad.setMessage("此功能暫未實現,對代碼有疑問或者不懂可以私聊我快手號\r\n快手id:北海狂鮫");
                ad.setPositiveButton("我知道了", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int i) {
//                        點擊隱藏對話框
                        dialog.dismiss();
                    }
                });
//                創建對話框
                ad.create();
//                讓用戶必須選擇對話框,解決彈出對話框點擊空白對話框消失的問題
                ad.setCancelable(false);
//                顯示對話框
                ad.show();

                break;
//               收藏的文字點擊
            case R.id.main_activity_my_collect_text:
                ad.setTitle("通知");
                ad.setMessage("此功能暫未實現,對代碼有疑問或者不懂可以私聊我快手號\r\n快手id:北海狂鮫");
                ad.setPositiveButton("我知道了", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int i) {
//                        點擊隱藏對話框
                        dialog.dismiss();
                    }
                });
//                創建對話框
                ad.create();
//                讓用戶必須選擇對話框,解決彈出對話框點擊空白對話框消失的問題
                ad.setCancelable(false);
//                顯示對話框
                ad.show();
                break;
//                錯題練習圖片點擊事件
            case R.id.main_activity_Wrong_topic_practise_imageView:
                break;
//                錯題練習文字點擊事件
            case R.id.main_activity_wrong_topic_practise_text:
//                AlertDialog.Builder add=new AlertDialog.Builder(MainActivity.this);
//                add.setTitle("通知");
//                add.setMessage("暫無錯題數據");
//                add.setPositiveButton("我知道了", new DialogInterface.OnClickListener() {
//                    @Override
//                    public void onClick(DialogInterface dialog, int which) {
//                        dialog.dismiss();
//                    }
//                });
                break;
        }
    }
}

還有幾個工具類我也貼出來吧,第一個是存放變量名的類

package com.hnkjxy.z.onlinetestsystemsdemo.Finally;

import android.os.Environment;

import java.io.File;

/**
 * Created by zhouweixiong on 2017/12/21.
 */

/**
 * 定義一些常量
 * 一些表名和字段名
 * 不可修改字段名,否則會得不到數據
 * 在res目錄下面有一個raw文件夾,raw裏面有一個數據表
 * 如果要android studio查看此表,就去下載一個插件 database
 */

public class MyFinally {
    public static final String TABLE_NAME = "t_question";//表名
    public static final String TABLE_SOUCANG_NAME = "t_soucang";//表名
    //    字段名
    public static final String T01_COLUMN_ID = "question_id";
    public static final String T01_COLUMN_OPTION_TYPE = "option_type";
    public static final String T01_COLUMN_SOU_TYPE = "sou_type";
    public static final String T01_COLUMN_ERROR_TYPE = "error_type";
    //Environment.getExternalStorageDirectory()  獲得根路徑
//File.separator是用來分隔同一個路徑字符串中的目錄的,例如:
//    C:\Program Files\Common Files
//    就是指“\”
    public static final String FILE_PAPER_PATH = Environment.getExternalStorageDirectory() + File.separator + "kaoshi";
    //  文件的詳細地址,找到此文件
//    FILE_PAPER_PATH 是第31行的地址,拼起來就是詳細的文件地址和文件名
    public static final String FILE_PATH = FILE_PAPER_PATH + File.separator + "kaoshi.db";
}

再就是創建系統文件夾和把數據表寫入文件夾裏的工具類

package com.hnkjxy.z.onlinetestsystemsdemo.Dao;

import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import com.hnkjxy.z.onlinetestsystemsdemo.Finally.MyFinally;
import com.hnkjxy.z.onlinetestsystemsdemo.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * Created by zhouweixiong on 2017/12/22.
 */

public class DBWriteSDCard {
    private static final String TAG = "ReleaseDataBase";
    private Context context;

    public DBWriteSDCard(Context context) {
        super();
        this.context = context;
    }


    public void whetherToWriteFile() {// 把raw下的sq寫進sd卡
        //        如果你的儲存卡存在並且可用
//        只有在SD卡狀態爲MEDIA_MOUNTED時/mnt/sdcard目錄纔是可讀可寫,並且可以創建目錄及文件
        // 判斷sd卡是否掛載
        if (Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState())) {

            // 建立sd卡對象
            File file = new File(MyFinally.FILE_PAPER_PATH);
//            如果沒有此文件夾就創建
            if (!file.exists()) {
//                創建
                file.mkdirs();
            } else {
                Log.d(TAG,"sd已有");
            }
//            實例化文件名對象
            File filePath = new File(MyFinally.FILE_PATH);// 建立sd卡下 的db文件
//             如果文件不存在
            if (!filePath.exists()) {
//                不存在就把raw目錄下的kaoshi文件通過流讀出來,讀出來是爲了等會好寫進去
                InputStream in = this.context.getResources().openRawResource(
                        R.raw.kaoshi);
//                對程序異常奔潰的捕捉 try catch
                try {
//                  FileOutputStream是文件輸出流,是用於將數據寫入File或 FileDescriptor的輸出流
//                  實例化文件輸入流對象(文件名)
                    FileOutputStream fileOutputStream = new FileOutputStream(MyFinally.FILE_PATH);// 得到輸出流 文件夾下文件路徑
//                    定義了一個byte類型的數組,數組長度爲8192
                    byte[] buffer = new byte[8192];
                    int t = 0;
                    while ((t = in.read(buffer)) != -1) {// 半讀邊寫
                        fileOutputStream.write(buffer, 0, t);
                    }
//                    開了流就一定要記得關  因爲會佔用系統資源
//                   文件讀寫完 關閉流
                    in.close();
                    fileOutputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }


        }

    }


}

接下來是一個比較重要重要的類了,解析本地數據庫的類,其他功能模塊都到了此類裏的方法來獲取題目

package com.hnkjxy.z.onlinetestsystemsdemo.Dao;

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

import com.hnkjxy.z.onlinetestsystemsdemo.Finally.MyFinally;
import com.hnkjxy.z.onlinetestsystemsdemo.entityClass.Question;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;

/**
 * Created by zhouweixiong on 2017/12/21.
 */

public class ExamDao {
    //調錯用的
    private static final String TAG = "ExamDao";
    //  用來操控數據表的,獲取數據等
//    建議百度 SQLiteDatabase 的詳細用法
    public static SQLiteDatabase sqLiteDatabase ;
    //上下文
//    其他功能模塊要用到的
    private Context context;

    public ExamDao(Context context) {
        this.context = context;
    }

    //    定義一個指數
    private static int index = 0;

    //    打開數據庫的方法
    public void openDatabase() {
//        判斷如果沒有數據表就打開數據表
        if (sqLiteDatabase == null) {
//            DBWriteSDCard這個類的作用是 判斷是否有沒有此文件夾和此文件,沒有就創建,和寫入數據庫到SD卡的
//            有的話就不會創建
            DBWriteSDCard dbWriteSDCard = new DBWriteSDCard(context);
//            whetherToWriteFile方法裏面寫的就是上述的註釋
            dbWriteSDCard.whetherToWriteFile();
//        建議詳細去了解SQLiteDatabase的方法  MyFinally.FILE_PATH 是MyFinally類寫的常量的路徑,也就是打開文件的路徑
            sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(MyFinally.FILE_PATH, null);

        }
    }

    //    關閉數據庫的方法
    public void closeDatabase() {
//判斷如果打開了就關閉
        if (sqLiteDatabase != null) {
//            SQLiteDatabase的close方法
            sqLiteDatabase.close();
            sqLiteDatabase = null;
        }
    }

    // 按順序查詢得到題目的方法
//    返回一個ArrayList<Question>的集合
    public ArrayList<Question> sequenceQuery() {
//        實例化一個集合 用來保存數據
        ArrayList<Question> arrayList = new ArrayList<Question>();
//  判斷有沒有打開數據庫 沒有就打開
        if (sqLiteDatabase == null) {
//            上面寫的打開數據庫的方法
            openDatabase();
        }
//  判斷有沒有打開數據庫 有就進行操作
        if (sqLiteDatabase != null) {
// 對於數據庫記錄的操作,可以使用Cursor(遊標)來進行
//            sqLiteDatabase.query 查詢數據表,後面的null是查詢條件,這裏是按順序獲得所有數據
            Cursor cursor = sqLiteDatabase.query(MyFinally.TABLE_NAME,
                    null, null, null, null,
                    null, null);
//循環 添加下一條
            while (cursor != null && cursor.moveToNext()) {
//                把得到的數據添加到數組中去
//                對應Question類的數據   參數是表示列數
                arrayList.add(new Question(cursor.getInt(0), cursor.getInt(1),
                        cursor.getString(2), cursor.getString(3),
                        cursor.getBlob(4), cursor.getInt(5),
                        cursor.getString(6), cursor.getString(7), cursor.getString(8),
                        cursor.getString(9), cursor.getString(10), cursor.getInt(11), cursor.getInt(12),
                        cursor.getInt(13), cursor.getInt(14)));
            }
//  循環執行完關閉cursor
            cursor.close();
        }
//        關閉數據庫的連接
         closeDatabase();
//        返回數組(已獲得的數據都在數組裏面)
        return arrayList;
    }


    //得到所以題目試題
    public ArrayList<Question> getAllTopic(int type) {
//        同上面方法註釋
        ArrayList<Question> arrayList = new ArrayList<Question>();

        if (sqLiteDatabase == null) {
            openDatabase();
        }
        if(sqLiteDatabase != null){
//            type=0就得到一百題  否則就得到所有題目
            if(type==0){
//               limit 設置query語句返回行的數量,相當於SQL語句中的“LIMIT”關鍵字,
//            傳遞null表示沒有設置limit語句。注意格式爲String,傳遞的時候需要傳遞數字字符串,例如“12
//                  這裏的代碼意思是隻能出一百題  type=0就只有一百題
                Cursor cursor = sqLiteDatabase.query(MyFinally.TABLE_NAME, null, null, null, null,
                        null,null,"100" );
                while (cursor != null&&cursor.moveToNext()) {
                    arrayList.add(new  Question(cursor.getInt(0),cursor.getInt(1),
                            cursor.getString(2), cursor.getString(3),
                            cursor.getBlob(4), cursor.getInt(5),
                            cursor.getString(6), cursor.getString(7), cursor.getString(8),
                            cursor.getString(9),cursor.getString(10),cursor.getInt(11),cursor.getInt(12),
                            cursor.getInt(13),cursor.getInt(14)));
                }
                cursor.close();
            }else{
                Cursor cursor = sqLiteDatabase.query(MyFinally.TABLE_NAME, null, null, null, null,
                        null, null,null);
                while (cursor != null&&cursor.moveToNext()) {
                    arrayList.add(new  Question(cursor.getInt(0),cursor.getInt(1),
                            cursor.getString(2), cursor.getString(3),
                            cursor.getBlob(4), cursor.getInt(5),
                            cursor.getString(6), cursor.getString(7), cursor.getString(8),
                            cursor.getString(9),cursor.getString(10),cursor.getInt(11),cursor.getInt(12),
                            cursor.getInt(13),cursor.getInt(14)));
                }
                cursor.close();
            }
        }
        closeDatabase();
        return arrayList;

    }

//    更新 也就是修改數據  values:代表想要更新的數據   這個方法只傳了三個參數進來  修改數據則有四個參數,因爲第一個參數
//    表名是固定了的
    public int updateQuestion(ContentValues values  , String where  , String []  param){
        int questens=0;
        if (sqLiteDatabase == null) {
            openDatabase();
        }
        if(sqLiteDatabase != null){
//            sqLiteDatabase更新數據表的方法 第一個參數是表名  第二個是要更新的數據
//            第三第四連起來用的 第三個是哪一條(這裏傳字段名+佔位符,佔位符就是?號) 第四個就是那一條的具體數據 就是第三個佔位符
            questens =sqLiteDatabase.update("t_question", values, where, param);
        }
        closeDatabase();
        return questens;
    }

    public  ArrayList<Question> RandomgetTopic() {
//        註釋同上面一樣
        HashSet<Question> questions = new HashSet<Question>();
        if (sqLiteDatabase == null) {
            openDatabase();
        }
        if(sqLiteDatabase != null){
//            先查詢數據表
            Cursor cursor1 = sqLiteDatabase.query(MyFinally.TABLE_NAME, null, null, null, null,
                    null, null,null);
//            得到數據表的行數 count是126 意思就是有126條數據
            int count = cursor1.getCount();
//            只是這裏的差別 隨機得到題目
            index =    count/100;
            Random  random = new Random();
            index=  (random.nextInt(index)*10);

            Log.d(TAG, "random.nextInt(index);="+index);


            Cursor cursor = sqLiteDatabase.query(MyFinally.TABLE_NAME, null, null, null, null,
                    null, null,index+","+(100));
            while (cursor != null&&cursor.moveToNext()) {

                questions.add(new  Question(cursor.getInt(0),cursor.getInt(1),
                        cursor.getString(2), cursor.getString(3),
                        cursor.getBlob(4), cursor.getInt(5),
                        cursor.getString(6), cursor.getString(7), cursor.getString(8),
                        cursor.getString(9),cursor.getString(10),cursor.getInt(11),cursor.getInt(12),
                        cursor.getInt(13),cursor.getInt(14)));
            }
            cursor.close();
        }
        closeDatabase();
//      set轉list
        ArrayList<Question> arrayList = new ArrayList<Question>(questions);
        return arrayList;
    }

}

接下貼一個功能模塊的代碼,就貼在線考試這個功能模塊的代碼的,首先是這個功能模塊的佈局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.hnkjxy.z.onlinetestsystemsdemo.othersActivity.OnlinetestActivity">

    <LinearLayout
        android:id="@+id/activity_onlinetest_headings"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="@color/LightBlue"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="在線考試"
            android:textColor="@color/white"
            android:textSize="20dp" />
    </LinearLayout>

    <Chronometer
        android:id="@+id/activity_onlinetest_countdown"
        android:textSize="20dp"
        android:gravity="center"
        android:textColor="@color/red"
        app:layout_constraintTop_toBottomOf="@id/activity_onlinetest_headings"
        android:layout_width="match_parent"
        android:layout_below="@id/activity_onlinetest_headings"
        android:layout_height="30dp" />

    <android.support.v4.view.ViewPager
        android:id="@+id/activity_onlinetest_viewPager"
        android:layout_width="match_parent"
        app:layout_constraintTop_toBottomOf="@id/activity_onlinetest_countdown"
        android:layout_height="390dp"
        >

    </android.support.v4.view.ViewPager>
    <LinearLayout
        android:orientation="horizontal"
        app:layout_constraintBottom_toTopOf="parent"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:id="@+id/activity_onlinetest_their_papers"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="交卷"
            android:gravity="center"
            android:textColor="@color/black"
            android:layout_height="match_parent" />

    </LinearLayout>
</android.support.constraint.ConstraintLayout>

接下來是代碼了,此功能模塊還有一個倒計時的功能,因爲在線考試嘛,沒有時間限制不好,源碼會有註釋,這裏我就不多嘩嘩

package com.hnkjxy.z.onlinetestsystemsdemo.othersActivity;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;


import com.hnkjxy.z.onlinetestsystemsdemo.Dao.ExamDao;
import com.hnkjxy.z.onlinetestsystemsdemo.MainActivity;
import com.hnkjxy.z.onlinetestsystemsdemo.R;
import com.hnkjxy.z.onlinetestsystemsdemo.entityClass.Question;

import java.util.ArrayList;

public class OnlinetestActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener,
        View.OnClickListener, RadioGroup.OnCheckedChangeListener, Chronometer.OnChronometerTickListener {

    //    定義控件id
    private RadioButton onlinetest_radioA;
    private RadioButton onlinetest_radioB;
    private RadioButton onlinetest_radioC;
    private RadioButton onlinetest_radioD;

    //  計時器
    public Chronometer chronometer;
    //    考試題目顯示
    private TextView onlinetest_show_question;
    //    考試圖片顯示
    private ImageView onlinetest_imageview;
    // 做題選擇
    private RadioGroup onlinetest_radioGroup;

    private TextView activity_onlinetest_their_papers;
    private ViewPager viewpager;
    private static ArrayList<View> viewpagelist;
    //    對錯多少題
    private Integer errorCount = 0;
    private Integer scoreCount = 0;
    private Integer rightCount = 0;
    //   指數
    private int index;
    //倒計時的時間
    int minutes = 44, seconds = 59;//45
    //    做題的頁數,做完滑動的
    private Integer viewpagerIndex = 0;
    //
    private static OnlinetestActivity onlinetestActivity;
    //    實例化獲得題目的類
    private ExamDao examDao;
    //   所有考試題目
    public static ArrayList<Question> arrayList;
    //  答題選項
    public int answer;
    //
    public Intent intent;
    //  標記
    public int flag;
    //自己定義的view的myadapter
    private myadapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_onlinetest);
        //        實例化ExamDao
        examDao = new ExamDao(this);
//
        intent = getIntent();
// flag 傳參數用的
        initData();
        init();
    }

    @SuppressLint("WrongConstant")
    public void init() {
        viewpager = (ViewPager) findViewById(R.id.activity_onlinetest_viewPager);
        viewpager.setOnPageChangeListener(this);
//        實例化自己定義的myadapter
        adapter = new myadapter();
//        viewpager.setAdapter(new myadapter());
        viewpager.setAdapter(adapter);
        //初始化交卷
        activity_onlinetest_their_papers = (TextView) findViewById(R.id.activity_onlinetest_their_papers);
        //初始化時間
        chronometer = (Chronometer) findViewById(R.id.activity_onlinetest_countdown);
        //初始化時間顯示
        SharedPreferences shar = getSharedPreferences("saveTime",
                Activity.MODE_PRIVATE);

//        倒計時設置  nowtime()是下面寫的一個方法
        chronometer.setText(nowtime());
        chronometer.setVisibility(0);
        chronometer.start();
        chronometer.setOnChronometerTickListener(this);
//        點擊事件
        activity_onlinetest_their_papers.setOnClickListener(this);
//        設置頁碼
        viewpager.setCurrentItem(viewpagerIndex);
    }

    private CharSequence nowtime() {
        if (seconds < 10) {
            return (minutes + ":0" + seconds);
        } else {
            return (minutes + ":" + seconds);
        }

    }

    @SuppressLint("WrongConstant")
    public void initData() {
        arrayList = examDao.getAllTopic(0);// 查詢所有題目

        LayoutInflater inflter = LayoutInflater.from(this);
        StringBuffer questionId = new StringBuffer();
        viewpagelist = new ArrayList<View>();
        for (int i = 0; i < arrayList.size(); i++) {
            Question q = arrayList.get(i);
            // arrayList.get(i)    應該改成    Question q = arrayList.get(i);  你那樣寫有效率問題
            if (i == arrayList.size() - 1) {
                questionId.append(q.getQuestion_id());
            } else {
                questionId.append(q.getQuestion_id() + "#");
            }

            View view = inflter.inflate(R.layout.activity_onlinetest_viewpager, null);
            onlinetest_show_question = (TextView) view.findViewById(R.id.onlinetest_show_question);
            onlinetest_show_question.setText(q.getLabel() + q.getQuestion());
            /**
             * 獲取圖片
             */
            onlinetest_imageview = (ImageView) view.findViewById(R.id.onlinetest_imageview);

            if (null != q.getBlob()) {
                // 0意思是可見的
                onlinetest_imageview.setVisibility(0);
                // 獲取圖片
                Bitmap bitmap = BitmapFactory.decodeByteArray(q
                        .getBlob(), 0, q.getBlob().length);
                onlinetest_imageview.setImageBitmap(bitmap);

            } else {
                onlinetest_imageview.setVisibility(8);
                // 常量值爲4,意思是不可見的
                // 常量值爲8,意思是不可見的,而且不佔用佈局空間
            }
            onlinetest_radioA = view.findViewById(R.id.onlinetest_radioA);
            /**
             * 獲得a選項內容
             */
            onlinetest_radioA.setText(q.getOptionA());

            onlinetest_radioB = view.findViewById(R.id.onlinetest_radioB);
            /**
             * 獲得b選項內容
             */
            onlinetest_radioB.setText(q.getOptionB());

            onlinetest_radioC = view.findViewById(R.id.onlinetest_radioC);

            /**
             * 獲得c選項內容
             * 爲什麼C,D會有判斷了,因爲有的題目是判斷題,判斷題沒有C,D選擇  所以判斷一下
             * 沒有內容不要顯示C,D選項
             */
            if ("null".equals(q.getOptionC())) {
                onlinetest_radioC.setVisibility(View.GONE);
            } else {
                onlinetest_radioC.setText(q.getOptionC());
                onlinetest_radioC.setVisibility(0);
            }
            onlinetest_radioD = view.findViewById(R.id.onlinetest_radioD);

            /**
             * 獲得d選項內容
             */
            if ("null".equals(q.getOptionD())) {
                onlinetest_radioD.setVisibility(View.GONE);
            } else {
                onlinetest_radioD.setText(q.getOptionD());
                onlinetest_radioD.setVisibility(0);
            }
            if (q.getOption_type() == 1) {

                if (q.getUser_Answer() == 1) {
                    onlinetest_radioA.setChecked(true);
                } else if (q.getUser_Answer() == 2) {
                    onlinetest_radioB.setChecked(true);
                } else if (q.getUser_Answer() == 3) {
                    onlinetest_radioC.setChecked(true);
                } else {
                    onlinetest_radioD.setChecked(true);
                }

                onlinetest_radioA.setEnabled(false);
                onlinetest_radioB.setEnabled(false);
                onlinetest_radioC.setEnabled(false);
                onlinetest_radioD.setEnabled(false);
                viewpagerIndex += 1;


            }
            onlinetest_radioGroup = view.findViewById(R.id.onlinetest_radioGroup);
            onlinetest_radioGroup.setOnCheckedChangeListener(this);
            viewpagelist.add(view);

        }
    }


    //    內部類  viewpager適配器   即做完題左右滑動切換下一道上一道
    class myadapter extends PagerAdapter {

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return viewpagelist.size();
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            // TODO Auto-generated method stub
            return arg0 == arg1;
        }

        @Override
        public Object instantiateItem(View container, int position) {
            ((ViewPager) container).addView(viewpagelist.get(position));
            return viewpagelist.get(position);
        }

        @Override
        public void destroyItem(View container, int position, Object object) {
            ((ViewPager) container).removeView(viewpagelist.get(position));
        }

    }

    public void onPageScrollStateChanged(int arg0) {
        // TODO Auto-generated method stub

    }

    public void onPageScrolled(int arg0, float arg1, int arg2) {
        // TODO Auto-generated method stub

    }

    public void onPageSelected(int v) {

    }

    @SuppressLint("WrongConstant")
    public void onClick(View v) {
//        交卷的點擊事件
        switch (v.getId()) {
            case R.id.activity_onlinetest_their_papers:
                Toast.makeText(OnlinetestActivity.this, "得分" + scoreCount + "\r\n對題" + rightCount
                        + "\r\n錯題" + errorCount, Toast.LENGTH_SHORT).show();
                AlertDialog.Builder ad = new AlertDialog.Builder(OnlinetestActivity.this);

                ad.setTitle("結束考試?");
                ad.setMessage("考試還沒結束,是否交卷?\r\n再檢查一下看還有未做題吧");
                ad.setPositiveButton("是", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int i) {
//                        點擊是結束當前Activity
                        finish();

                    }
                });
                ad.setNegativeButton("接着考試", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int i) {
//                        讓對話框從屏幕上消失
                        dialog.dismiss();

                    }
                });
//                創建對話框
                ad.create();
//                讓用戶必須選擇對話框,解決彈出對話框點擊空白對話框消失的問題
                ad.setCancelable(false);
//                顯示對話框
                ad.show();
//得分,答錯多少題 答對多少題
                int score = 0;
                int answerCount = 0;
                int error = 0;
                int size = arrayList.size();
                for (int i = 0; i < size; i++) {
                    Question q = arrayList.get(i);
                    if (q.getOption_type() == 1) {
                        answerCount += 1;
                        if (q.getAnswer() == q.getUser_Answer()) {
                            score += 10;
                        } else {
                            error += 1;
                        }
                    }
                }
                break;
        }

    }

    @SuppressLint("WrongConstant")
    public void onCheckedChanged(RadioGroup arg0, int checkid) {
        boolean isRigth = false;
        boolean isOnChangge = false;
        switch (checkid) {

//            ABCD四個選項,判斷你選擇的答案對不對
            case R.id.onlinetest_radioA:
                isOnChangge = true;
//                選擇之後禁止選擇選項的點擊
                noClick();
//                  清除選中狀態
                onlinetest_radioGroup.clearCheck();
                //  判斷答案是否正確
                answer = 1;
                if (arrayList.get(viewpager.getCurrentItem()).getAnswer() == answer) {
                    isRigth = true;
                }
//                自動滑到下一頁
                viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);
                break;

            case R.id.onlinetest_radioB:
                isOnChangge = true;
                noClick();
                onlinetest_radioGroup.clearCheck();

                answer = 2;
                if (arrayList.get(viewpager.getCurrentItem()).getAnswer() == answer) {
                    isRigth = true;
                }
                viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);
                break;
            case R.id.onlinetest_radioC:
                isOnChangge = true;
                noClick();
                onlinetest_radioGroup.clearCheck();

                answer = 3;
                if (arrayList.get(viewpager.getCurrentItem()).getAnswer() == answer) {
                    isRigth = true;
                }
                viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);
                break;
            case R.id.onlinetest_radioD:
                isOnChangge = true;
                noClick();//1
                onlinetest_radioGroup.clearCheck();//2      1和2放在前面纔有效果

                answer = 4;
                if (arrayList.get(viewpager.getCurrentItem()).getAnswer() == answer) {
                    isRigth = true;
                }
                viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);
                break;
        }
        if (isRigth) {
//            分數一道題十分
            scoreCount += 1;
//            對的題數
            rightCount += 1;
        } else {
            if (isOnChangge) {
//                錯題數累加
                errorCount += 1;
//                Toast.makeText 測試同的
//                Toast.makeText(OnlinetestActivity.this, "錯,答案"+arrayList.get(viewpager.getCurrentItem()-1).getAnswer(), Toast.LENGTH_SHORT).show();
//               ContentValues 是名值對 不是鍵值對,對我沒打錯 可能你妹聽過名值對,這裏建議去百度一下,說不清
                ContentValues values = new ContentValues();
                values.put("error_type", 1);
//                把錯題加入數據庫
                examDao.updateQuestion(values, "question_id= ?",
                        new String[]{arrayList.get(viewpager.getCurrentItem() - 1).getQuestion_id() + ""});
//                arrayList.get(viewpager.getCurrentItem() - 1).setError_type(1);
            }

            //      選擇完題目判斷錯題個數  判斷如果錯了十題就停止考試
//            if (errorCount == 10) {
//                AlertDialog.Builder ad = new AlertDialog.Builder(OnlinetestActivity.this);
//
//                ad.setTitle("模擬考試已結束");
//                ad.setMessage("模擬考試結束,因爲你已答錯十題");
//
//                ad.setPositiveButton("離開考試", new DialogInterface.OnClickListener() {
//
//                    @Override
//                    public void onClick(DialogInterface dialog, int i) {
//                        Intent intent = new Intent(OnlinetestActivity.this, MainActivity.class);
//                        startActivity(intent);
////                    銷燬掉當前Activity
//                        finish();
//                    }
//                });
//
////                創建對話框
//                ad.create();
////            解決彈出對話框點擊空白和返回鍵消失的問題
//                ad.setCancelable(false);
////                顯示對話框
//                ad.show();
//                return;
//
//            }
        }
//        更新
        if (isOnChangge) {
            ContentValues values = new ContentValues();
//            這個
            values.put("option_type", 1);
//        記住之前做了的題你選擇的答案
            values.put("USER_ANSWER", answer);
            //LIST 下標示重0開始的 , 應該要減一
            arrayList.get(viewpager.getCurrentItem() - 1).setOption_type(1);
        }


    }

    //時間顯示
    public void onChronometerTick(Chronometer moni_chronometer) {

        // TODO Auto-generated method stub
        seconds--;
        if (seconds == -1) {
            minutes--;
            seconds = 59;
        }
        if (minutes == 0 && seconds == 00) {
            moni_chronometer.stop();
//            因爲一些問題 在倒計時結束時 強制讓他變成0:00
//            可以把這行代碼註釋掉跑下看看
            moni_chronometer.setText("0:00");

            AlertDialog.Builder ad = new AlertDialog.Builder(OnlinetestActivity.this);

            ad.setTitle("結束已考試");
            ad.setMessage("考試時間到停止作答");
            ad.setPositiveButton("交卷", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int i) {
                    Intent intent = new Intent(OnlinetestActivity.this, MainActivity.class);
                    startActivity(intent);
//                    銷燬掉當前Activity
                    finish();
                }
            });
//                創建對話框
            ad.create();
            ad.setCancelable(false);
//                顯示對話框
            ad.show();


        } else {
            moni_chronometer.setTextColor(Color.RED);
            moni_chronometer.setText(nowtime());
        }


    }

    /**
     * 禁止點擊的方法
     */
    public void noClick() {
        initRadioButton();
        onlinetest_radioA.setEnabled(false);
        onlinetest_radioB.setEnabled(false);
        onlinetest_radioC.setEnabled(false);
        onlinetest_radioD.setEnabled(false);
    }

    /**
     * 初始化radiobutton  這個方法決定點擊有沒有用
     */
    public void initRadioButton() {
        onlinetest_radioA = viewpagelist.get(viewpager.getCurrentItem()).findViewById(R.id.onlinetest_radioA);
        onlinetest_radioB = viewpagelist.get(viewpager.getCurrentItem()).findViewById(R.id.onlinetest_radioB);
        onlinetest_radioC = viewpagelist.get(viewpager.getCurrentItem()).findViewById(R.id.onlinetest_radioC);
        onlinetest_radioD = viewpagelist.get(viewpager.getCurrentItem()).findViewById(R.id.onlinetest_radioD);
    }


    //    監聽手機自帶的按鍵
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
//        如果點擊的返回鍵
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            AlertDialog.Builder ad = new AlertDialog.Builder(OnlinetestActivity.this);

            ad.setTitle("結束考試?");
            ad.setMessage("考試還沒結束,是否交卷?\r\n再檢查一下看還有未做題吧");
            ad.setPositiveButton("是", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int i) {
//                        點擊是結束當前Activity
                    finish();

                }
            });
            ad.setNegativeButton("接着考試", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int i) {
//                        讓對話框從屏幕上消失
                    dialog.dismiss();

                }
            });
//                創建對話框
            ad.create();
//                讓用戶必須選擇對話框,解決彈出對話框點擊空白對話框消失的問題
            ad.setCancelable(false);
//                顯示對話框
            ad.show();
        }
        return false;

    }

}

    複製上面代碼修改一些地方是可以跑出一個功能模塊的

    希望對大家有幫助,寫的不好的地方還請多多指教

   對了貼上源碼下載地址在線考試系統下載地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章