在此聲明,此在線考試系統是利用業餘時間寫的一個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;
}
}
複製上面代碼修改一些地方是可以跑出一個功能模塊的
希望對大家有幫助,寫的不好的地方還請多多指教
對了貼上源碼下載地址在線考試系統下載地址