项目: 课程日历
-项目概况: 项目记录一周的课程信息。
?用户可以编辑周一~周五的课程表(每天最多安排5门课程) ;
?用户可以按日查看课程表。
-项目要求:
?项目包含2个活动及其对应的布局:
① 显示课程活动:单击“周一”~“周五”按钮中的一个,按时间顺序显示当日的课程信息(上课时间、课程名称、教室);单击“编辑”按钮,进入下一个活动;
② 编辑课程活动:针对选定的周几,可以新增、修改或删除当日的课程。编辑完毕后,用户单击“保存”按钮则更新当日课程表,或单击“撤销”按钮取消刚才的编辑操作,或单击“返回”按钮,回到显示课程活动。
?布局设计:
① 显示课程活动布局:选用合适的视图控件显示课程信息;
② 编辑课程活动布局:选用恰当的视图控件提供课程编辑方式。
?功能设计:
① 能完成活动之间的跳转;
② 用数据库、数据表存储课程信息;
③ 能编辑和查询单日课程信息。
原始界面:
?
点击周一按钮后界面:(其余周数就不进行展示了,差不多)
选中周数后点击编辑按钮:
没有选中周数就点击编辑按钮出现的提示Toast:
输入相关课程信息后点击新增按钮:
在新增后点击撤销按钮:
在之前没有编辑操作或者已经撤销一次之后再次点击撤销会弹出提示:
三个editview如果有一个为空时点击新增按钮会出现的提示:
一天内课程数为5再点击新建:
点击listview中的课程会进行提示:
在选中课程之后点击删除按钮:
在删除操作后点击撤销按钮:
在没有选中课程就点击删除按钮出现的提示:
在选中第一个课程后并且在输入框中输入新的时间以及教室后点击保存按钮:
在保存之后点击撤销按钮:
点击返回按钮:
在MainActivity中有使用六个按钮,分别对应的是周一,周二,周三,周四,周五和返回。在下方还有一个listview,用来显示查询出来的课程信息。
listView对应的layout使用的也是相对布局,包含三个TextView,用来分别显示课程的名称,时间以及上课教室。
EditActivity里面包含一个listview,用来显示查询出来的课程信息以及供用户进行选中,五个按钮,分别对应的是新增,删除,保存,撤销以及返回,还有一个textview用来对用户进行提示,3个EditText用来读取需要编辑的课程信息。
MainActivity:
EditActivity:
Listview的layout:
<?xml?version="1.0"?encoding="utf-8"?><androidx.constraintlayout.widget.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=".MainActivity"> ????<Button ????????android:id="@+id/button3" ????????android:layout_width="79dp" ????????android:layout_height="54dp" ????????android:text="周三" ????????android:textSize="20sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.524" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.048"?/> ????<Button ????????android:id="@+id/button4" ????????android:layout_width="79dp" ????????android:layout_height="54dp" ????????android:text="周四" ????????android:textSize="20sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.762" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.048"?/> ????<Button ????????android:id="@+id/button2" ????????android:layout_width="79dp" ????????android:layout_height="54dp" ????????android:text="周二" ????????android:textSize="20sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.286" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.048"?/> ????<Button ????????android:id="@+id/button1" ????????android:layout_width="79dp" ????????android:layout_height="54dp" ????????android:text="周一" ????????android:textSize="20sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.048" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.048"?/> ????<Button ????????android:id="@+id/button5" ????????android:layout_width="79dp" ????????android:layout_height="54dp" ????????android:text="周五" ????????android:textSize="20sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.996" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.048"?/> ????<ListView ????????android:id="@+id/list1" ????????android:layout_width="413dp" ????????android:layout_height="367dp" ????????android:layout_marginTop="104dp" ????????app:layout_constraintTop_toTopOf="parent" ????????tools:layout_editor_absoluteX="-1dp"?/> ????<Button ????????android:id="@+id/buttonEdit" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:text="编辑" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.498" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.953"?/></androidx.constraintlayout.widget.ConstraintLayout>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
<?xml?version="1.0"?encoding="utf-8"?><androidx.constraintlayout.widget.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=".EditActivity"> ????<TextView ????????android:id="@+id/textView3" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:text="时间:" ????????android:textSize="24sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.233" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.615"?/> ????<Button ????????android:id="@+id/buttonDelete" ????????android:layout_width="103dp" ????????android:layout_height="57dp" ????????android:text="删除" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.334" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.905"?/> ????<Button ????????android:id="@+id/buttonZ" ????????android:layout_width="103dp" ????????android:layout_height="57dp" ????????android:text="撤销" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="1.0" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.905"?/> ????<Button ????????android:id="@+id/buttonAdd" ????????android:layout_width="103dp" ????????android:layout_height="57dp" ????????android:text="新增" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.0" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.905"?/> ????<Button ????????android:id="@+id/buttonSave" ????????android:layout_width="103dp" ????????android:layout_height="57dp" ????????android:text="保存" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.668" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.905"?/> ????<ListView ????????android:id="@+id/list2" ????????android:layout_width="411dp" ????????android:layout_height="282dp" ????????tools:layout_editor_absoluteX="0dp" ????????tools:layout_editor_absoluteY="0dp"?/> ????<TextView ????????android:id="@+id/textView" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:text="如需修改,请先选中其中一节课" ????????android:textSize="20sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="@+id/list2" ????????app:layout_constraintVertical_bias="0.802"?/> ????<EditText ????????android:id="@+id/editTextTime" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:ems="10" ????????android:inputType="textPersonName" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.781" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="@+id/list2" ????????app:layout_constraintVertical_bias="0.607"?/> ????<EditText ????????android:id="@+id/editTextName" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:ems="10" ????????android:inputType="textPersonName" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.781" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.507"?/> ????<EditText ????????android:id="@+id/editTextRoom" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:ems="10" ????????android:inputType="textPersonName" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.786" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="@+id/list2" ????????app:layout_constraintVertical_bias="0.699"?/> ????<TextView ????????android:id="@+id/textView4" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:text="教室:" ????????android:textSize="24sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.233" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.705"?/> ????<TextView ????????android:id="@+id/textView2" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:text="课程名:" ????????android:textSize="24sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.174" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.516"?/> ????<Button ????????android:id="@+id/buttonBack" ????????android:layout_width="wrap_content" ????????android:layout_height="wrap_content" ????????android:text="返回" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.498" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.992"?/></androidx.constraintlayout.widget.ConstraintLayout>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
<?xml?version="1.0"?encoding="utf-8"?><androidx.constraintlayout.widget.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"> ????<TextView ????????android:id="@+id/textViewName" ????????android:layout_width="151dp" ????????android:layout_height="58dp" ????????android:text="TextView" ????????android:textSize="20sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.026" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.021"?/> ????<TextView ????????android:id="@+id/textViewTime" ????????android:layout_width="107dp" ????????android:layout_height="46dp" ????????android:text="TextView" ????????android:textSize="34sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.527" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.023"?/> ????<TextView ????????android:id="@+id/textViewRoom" ????????android:layout_width="108dp" ????????android:layout_height="44dp" ????????android:text="TextView" ????????android:textSize="34sp" ????????app:layout_constraintBottom_toBottomOf="parent" ????????app:layout_constraintEnd_toEndOf="parent" ????????app:layout_constraintHorizontal_bias="0.881" ????????app:layout_constraintStart_toStartOf="parent" ????????app:layout_constraintTop_toTopOf="parent" ????????app:layout_constraintVertical_bias="0.023"?/></androidx.constraintlayout.widget.ConstraintLayout>1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
在MainActivity中有一个编辑按钮,按下可以跳转到EditActivity中。其中的Intent包括了Bundle,里面存储着当前选中的日子中从数据库查询出来的课程信息总和,即list_class(因为需要传递的数据是Arraylist类型的,所以首先需要把Class类Parcel化了才行),以及所选的是周几。
在EditActivity中接收来自MainActivity传递过来的Intent,并读取其中包含的Bundle中的课程数据,并展示在listview2中。
EditActivity中有个返回按钮,按下可以通过Intent重新回到MainActivity中
我创建了一个类,MyHelper,来当做调用SQLite数据库的工具类。在里面的onCreate方法里创建数据表,以及插入一些基本课程信息。
在进入EditActivity界面后,我设置了四个按钮新增,删除,保存,撤销。分别对应不同的方法来进行数据库操作。
在点击新增按钮之后,会首先进行判断,是否三个textview都不为空,一旦有一个为空就会提示用户“不能为空”并且终止操作,因为一旦不进行检测会导致空数据的存入。如都不为空,就将三个editview中的数据传入到insert方法中,调用MyHelper中的getWritableDatabase方法来获取db,将课程信息存入values中,再通过db.insert存入数据库中。然后把课程信息加入到list_class中(这样才可以实现listview的动态刷新),接着调用MyAdapter的notifyDataSetChanged方法来刷新listview,显示新增的课程。
以下代码附有注释
package?com.example.a2022finalproject;import?androidx.appcompat.app.AppCompatActivity;import?android.annotation.SuppressLint;import?android.content.Context;import?android.content.Intent;import?android.database.Cursor;import?android.database.sqlite.SQLiteDatabase;import?android.os.Bundle;import?android.os.Parcelable;import?android.view.LayoutInflater;import?android.view.View;import?android.view.ViewGroup;import?android.widget.BaseAdapter;import?android.widget.Button;import?android.widget.ListView;import?android.widget.TextView;import?android.widget.Toast;import?java.util.ArrayList;import?java.util.Collections;import?java.util.Comparator;import?java.util.List;public?class?MainActivity?extends?AppCompatActivity?implements?View.OnClickListener?{ ????private?Button?btn1,?btn2,?btn3,?btn4,?btn5,?btn6; ????private?ListView?lv; ????private?MyHelper?myHelper?=?new?MyHelper(this); ????private?MyAdapter?ma?=?new?MyAdapter(); ????private?String?weekNo?=?"0"; ????//Class类信息的存储对象 ????private?List<Class>?list_class?=?new?ArrayList<>(); ????@Override ????protected?void?onCreate(Bundle?savedInstanceState)?{ ????????super.onCreate(savedInstanceState); ????????setContentView(R.layout.activity_main); ????????//初始化 ????????init(); ????} ????//?初始化 ????public?void?init()?{ ????????btn1?=?findViewById(R.id.button1); ????????btn2?=?findViewById(R.id.button2); ????????btn3?=?findViewById(R.id.button3); ????????btn4?=?findViewById(R.id.button4); ????????btn5?=?findViewById(R.id.button5); ????????btn6?=?findViewById(R.id.buttonEdit); ????????lv?=?findViewById(R.id.list1); ????????btn1.setOnClickListener(this); ????????btn2.setOnClickListener(this); ????????btn3.setOnClickListener(this); ????????btn4.setOnClickListener(this); ????????btn5.setOnClickListener(this); ????????btn6.setOnClickListener(this); ????} ????//?查找数据库中的课程信息 ????@SuppressLint("Range") ????public?void?query(String?day)?{ ????????SQLiteDatabase?db?=?myHelper.getReadableDatabase(); ????????Cursor?cursor?=?db.query("class",?null,?"weekNo=?",?new?String[]{day},?null,?null,?null); ????????if?(cursor.getCount()?!=?0)?{ ????????????while?(cursor.moveToNext())?{ ????????????????//?加入list_class中存储 ????????????????list_class.add(new?Class(day,?cursor.getString(cursor.getColumnIndex("name")),?cursor.getString(cursor.getColumnIndex("time")),?cursor.getString(cursor.getColumnIndex("room")))); ????????????} ????????} ????????db.close(); ????} ????//?按照时间排序函数 ????public?static?class?TimeSort?implements?Comparator<Class>?{ ????????@Override ????????public?int?compare(Class?aClass,?Class?t1)?{ ????????????return?aClass.getTime().compareTo(t1.getTime()); ????????} ????} ????@Override ????public?void?onClick(View?view)?{ ????????switch?(view.getId())?{ ????????????//?周一 ????????????case?R.id.button1: ????????????????weekNo?=?"1"; ????????????????list_class?=?new?ArrayList<>(); ????????????????query("1"); ????????????????Collections.sort(list_class,?new?TimeSort());//按照时间排序 ????????????????lv.setAdapter(ma);//显示在listview中 ????????????????break; ????????????//?周二 ????????????case?R.id.button2: ????????????????weekNo?=?"2"; ????????????????list_class?=?new?ArrayList<>(); ????????????????query("2"); ????????????????Collections.sort(list_class,?new?TimeSort()); ????????????????lv.setAdapter(ma); ????????????????break; ????????????//?周三 ????????????case?R.id.button3: ????????????????weekNo?=?"3"; ????????????????list_class?=?new?ArrayList<>(); ????????????????query("3"); ????????????????Collections.sort(list_class,?new?TimeSort()); ????????????????lv.setAdapter(ma); ????????????????break; ????????????//?周四 ????????????case?R.id.button4: ????????????????weekNo?=?"4"; ????????????????list_class?=?new?ArrayList<>(); ????????????????query("4"); ????????????????Collections.sort(list_class,?new?TimeSort()); ????????????????lv.setAdapter(ma); ????????????????break; ????????????//?周五 ????????????case?R.id.button5: ????????????????weekNo?=?"5"; ????????????????list_class?=?new?ArrayList<>(); ????????????????query("5"); ????????????????Collections.sort(list_class,?new?TimeSort()); ????????????????lv.setAdapter(ma); ????????????????break; ????????????//?修改课程信息 ????????????case?R.id.buttonEdit: ????????????????//?判断是否选中了某一天 ????????????????if?(weekNo?==?"0"){ ????????????????????Toast.makeText(this,?"请先选择一天从而进行编辑操作",?Toast.LENGTH_LONG).show(); ????????????????} ????????????????else{ ????????????????????//?因为需要传递的数据时ArrayList所以需要使用Bundle来进行传递 ????????????????????Intent?intent?=?new?Intent(MainActivity.this,?EditActivity.class); ????????????????????Bundle?bundle?=?new?Bundle(); ????????????????????//?注意,对应的Class类需要进行Parcelable化 ????????????????????bundle.putParcelableArrayList("list_class",?(ArrayList<??extends?Parcelable>)?list_class); ????????????????????bundle.putString("weekNo",?weekNo); ????????????????????intent.putExtras(bundle); ????????????????????startActivity(intent); ????????????????} ????????????????break; ????????} ????} ????public?class?MyAdapter?extends?BaseAdapter?{ ????????@Override ????????public?int?getCount()?{ ????????????return?list_class.size(); ????????} ????????@Override ????????public?Object?getItem(int?i)?{ ????????????return?list_class.get(i); ????????} ????????@Override ????????public?long?getItemId(int?i)?{ ????????????return?i; ????????} ????????@Override ????????public?View?getView(int?i,?View?view,?ViewGroup?viewGroup)?{ ????????????//?配置listview中的显示效果 ????????????View?newView?=?View.inflate(MainActivity.this,?R.layout.activity_class,?null); ????????????TextView?textView1?=?newView.findViewById(R.id.textViewName); ????????????TextView?textView2?=?newView.findViewById(R.id.textViewTime); ????????????TextView?textView3?=?newView.findViewById(R.id.textViewRoom); ????????????textView1.setText(list_class.get(i).getName()); ????????????textView2.setText(list_class.get(i).getTime()); ????????????textView3.setText(list_class.get(i).getRoom()); ????????????return?newView; ????????} ????}}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
package?com.example.a2022finalproject;import?androidx.appcompat.app.AppCompatActivity;import?android.content.ContentValues;import?android.content.Intent;import?android.database.sqlite.SQLiteDatabase;import?android.os.Bundle;import?android.view.View;import?android.view.ViewGroup;import?android.widget.AdapterView;import?android.widget.BaseAdapter;import?android.widget.Button;import?android.widget.EditText;import?android.widget.ListView;import?android.widget.TextView;import?android.widget.Toast;import?java.util.ArrayList;import?java.util.Collections;import?java.util.Comparator;import?java.util.List;public?class?EditActivity?extends?AppCompatActivity?implements?View.OnClickListener?{ ????private?Button?btnAdd,?btnDelete,?btnZ,?btnSave,?btnBack; ????private?EditText?etName,?etTime,?etRoom; ????private?ListView?list2; ????private?List<Class>?list_class?=?new?ArrayList<>(); ????private?MyAdapter?ma?=?new?MyAdapter(); ????private?MyHelper?myHelper?=?new?MyHelper(this); ????private?String?name,?time,?room,?weekNo; ????private?int?chosenItem?=?-1;//?选中的课程序号 ????private?int?showItem; ????private?String?changedIndex?=?"0";//0代表先前没有进行操作 ????private?Class?changedItem,?changedItem2; ????@Override ????protected?void?onCreate(Bundle?savedInstanceState)?{ ????????super.onCreate(savedInstanceState); ????????setContentView(R.layout.activity_edit); ????????init(); ????} ????//初始化 ????public?void?init()?{ ????????btnAdd?=?findViewById(R.id.buttonAdd); ????????btnDelete?=?findViewById(R.id.buttonDelete); ????????btnZ?=?findViewById(R.id.buttonZ); ????????btnSave?=?findViewById(R.id.buttonSave); ????????btnBack?=?findViewById(R.id.buttonBack); ????????list2?=?findViewById(R.id.list2); ????????//设置listview的点击实践,实现点击课程记录下它对应的序号 ????????list2.setOnItemClickListener(new?AdapterView.OnItemClickListener()?{ ????????????@Override ????????????public?void?onItemClick(AdapterView<?>?adapterView,?View?view,?int?i,?long?l)?{ ????????????????chosenItem?=?i; ????????????????showItem?=?chosenItem?+?1; ????????????????Toast.makeText(EditActivity.this,?"你已选中第"?+?showItem?+?"项",?Toast.LENGTH_SHORT).show(); ????????????} ????????}); ????????btnAdd.setOnClickListener(this); ????????btnDelete.setOnClickListener(this); ????????btnZ.setOnClickListener(this); ????????btnSave.setOnClickListener(this); ????????btnBack.setOnClickListener(this); ????????etName?=?findViewById(R.id.editTextName); ????????etTime?=?findViewById(R.id.editTextTime); ????????etRoom?=?findViewById(R.id.editTextRoom); ????????//接受来自MainActivity中的信息 ????????Intent?intent?=?getIntent(); ????????Bundle?bundle?=?intent.getExtras(); ????????list_class?=?bundle.getParcelableArrayList("list_class"); ????????weekNo?=?bundle.getString("weekNo"); ????????//展示在list2中 ????????list2.setAdapter(ma); ????} ????//插入方法 ????private?boolean?insert(String?name,?String?time,?String?room)?{ ????????changedIndex?=?"insert";//记录本次操作,便于撤销 ????????SQLiteDatabase?db?=?myHelper.getWritableDatabase(); ????????ContentValues?values?=?new?ContentValues(); ????????values.put("weekNo",?weekNo); ????????values.put("name",?name); ????????values.put("time",?time); ????????values.put("room",?room); ????????long?id?=?db.insert("class",?null,?values); ????????db.close(); ????????Class?classNew?=?new?Class(weekNo,?name,?time,?room); ????????//需要同时对list_class中的进行修改,不然notifyDataSetChanged方法不会生效,就不能实现动态刷新 ????????list_class.add(classNew); ????????Collections.sort(list_class,?new?MainActivity.TimeSort());//时间排序 ????????changedItem?=?classNew;//记录下插入的课程信息,便于撤销时删除 ????????ma.notifyDataSetChanged();//刷新listview ????????return?id?>?0; ????} ????//用于撤销中对应删除的反操作 ????private?boolean?insert(Class?item)?{ ????????SQLiteDatabase?db?=?myHelper.getWritableDatabase(); ????????ContentValues?values?=?new?ContentValues(); ????????values.put("weekNo",?weekNo); ????????values.put("name",?item.getName()); ????????values.put("time",?item.getTime()); ????????values.put("room",?item.getRoom()); ????????long?id?=?db.insert("class",?null,?values); ????????db.close(); ????????list_class.add(item); ????????Collections.sort(list_class,?new?MainActivity.TimeSort()); ????????ma.notifyDataSetChanged(); ????????changedIndex?=?"0";//重置操作信息,避免多次撤销 ????????return?id?>?0; ????} ????//删除操作 ????private?boolean?delete(int?chosenItem)?{ ????????changedIndex?=?"delete";//记录操作 ????????Class?item?=?(Class)?list2.getItemAtPosition(chosenItem); ????????changedItem?=?item;//记录删除的课程信息 ????????SQLiteDatabase?db?=?myHelper.getWritableDatabase(); ????????long?id?=?db.delete("class",?"name?=???and?weekNo?=??",?new?String[]{item.getName(),?weekNo}); ????????db.close(); ????????//动态刷新 ????????list_class.remove(item); ????????ma.notifyDataSetChanged(); ????????return?id?>?0; ????} ????//用于撤销中的新增的反操作 ????private?boolean?delete(Class?item)?{ ????????SQLiteDatabase?db?=?myHelper.getWritableDatabase(); ????????long?id?=?db.delete("class",?"name?=???and?weekNo?=??",?new?String[]{item.getName(),?weekNo}); ????????db.close(); ????????list_class.remove(item); ????????ma.notifyDataSetChanged(); ????????changedIndex?=?"0"; ????????return?id?>?0; ????} ????//保存操作,即update ????private?boolean?save(String?name,?String?time,?String?room)?{ ????????changedIndex?=?"save";//记录操作 ????????Class?item?=?(Class)?list2.getItemAtPosition(chosenItem); ????????changedItem?=?item;//记录修改的原课程信息 ????????SQLiteDatabase?db?=?myHelper.getWritableDatabase(); ????????ContentValues?values?=?new?ContentValues(); ????????Class?item2?=?new?Class();//记录更新后的课程信息 ????????if?(!name.isEmpty()){//对于为空的字段判断为不进行修改,保持原状 ????????????values.put("name",?name); ????????????item2.setName(name); ????????}else{ ????????????item2.setName(item.getName()); ????????} ????????if?(!time.isEmpty()){ ????????????values.put("time",?time); ????????????item2.setTime(time); ????????}else{ ????????????item2.setTime(item.getTime()); ????????} ????????if?(!room.isEmpty()){ ????????????values.put("room",?room); ????????????item2.setRoom(room); ????????}else{ ????????????item2.setRoom(item.getRoom()); ????????} ????????//通过周几和课程名称来确定一门课程 ????????int?updateCount?=?db.update("class",?values,?"name?=???and?time?=??",?new?String[]{item.getName(),?item.getTime()}); ????????db.close(); ????????//动态刷新 ????????list_class.remove(item); ????????list_class.add(item2); ????????Collections.sort(list_class,?new?MainActivity.TimeSort()); ????????changedItem2?=?item2; ????????ma.notifyDataSetChanged(); ????????return?updateCount?>?0; ????} ????//用于撤销操作中保存操作的反操作 ????private?boolean?save(Class?item,?Class?item2)?{ ????????SQLiteDatabase?db?=?myHelper.getWritableDatabase(); ????????ContentValues?values?=?new?ContentValues(); ????????if(item.getName()?!=?item2.getName()){ ????????????values.put("name",?item.getName()); ????????} ????????if(item.getTime()?!=?item2.getTime()){ ????????????values.put("time",?item.getTime()); ????????} ????????if(item.getRoom()?!=?item2.getRoom()){ ????????????values.put("room",?item.getRoom()); ????????} ????????int?updateCount?=?db.update("class",?values,?"name?=???and?time?=??",?new?String[]{item2.getName(),?item2.getTime()}); ????????db.close(); ????????//动态刷新 ????????list_class.remove(item2); ????????list_class.add(item); ????????Collections.sort(list_class,?new?MainActivity.TimeSort()); ????????ma.notifyDataSetChanged(); ????????changedIndex?=?"0";//还原操作标记 ????????return?updateCount?>?0; ????} ????@Override ????public?void?onClick(View?view)?{ ????????switch?(view.getId())?{ ????????????case?R.id.buttonAdd: ????????????????if(list_class.size()?>=?5){ ????????????????????Toast.makeText(EditActivity.this,?"新建失败,课程最多一天5门",?Toast.LENGTH_SHORT).show(); ????????????????????break; ????????????????} ????????????????name?=?etName.getText().toString().trim(); ????????????????time?=?etTime.getText().toString().trim(); ????????????????room?=?etRoom.getText().toString().trim(); ????????????????if(name.isEmpty()?||?time.isEmpty()?||?room.isEmpty()){//判断是否为空,避免插入空信息的课程 ????????????????????Toast.makeText(EditActivity.this,?"课程名称,时间,教室不能为空",?Toast.LENGTH_SHORT).show(); ????????????????????break; ????????????????} ????????????????if?(insert(name,?time,?room))?{ ????????????????????Toast.makeText(EditActivity.this,?"新增成功",?Toast.LENGTH_SHORT).show(); ????????????????} ????????????????break; ????????????case?R.id.buttonDelete: ????????????????if?(chosenItem?==?-1){//判断是否选中了课程 ????????????????????Toast.makeText(EditActivity.this,?"请先选择一节课",?Toast.LENGTH_SHORT).show(); ????????????????}else{ ????????????????????if?(delete(chosenItem))?{ ????????????????????????changedIndex?=?"-1";?//?重置,防止误删 ????????????????????????Toast.makeText(EditActivity.this,?"删除成功",?Toast.LENGTH_SHORT).show(); ????????????????????} ????????????????} ????????????????break; ????????????case?R.id.buttonZ: ????????????????if(changedIndex?==?"0"){//判断是否进行过操作 ????????????????????Toast.makeText(EditActivity.this,?"没有需要撤回的操作",?Toast.LENGTH_SHORT).show(); ????????????????}else?if(changedIndex?==?"insert"){ ????????????????????if(delete(changedItem)){ ????????????????????????Toast.makeText(EditActivity.this,?"撤回新增成功",?Toast.LENGTH_SHORT).show(); ????????????????????} ????????????????}else?if(changedIndex?==?"delete"){ ????????????????????if(insert(changedItem)){ ????????????????????????Toast.makeText(EditActivity.this,?"撤回删除成功",?Toast.LENGTH_SHORT).show(); ????????????????????} ????????????????}else?if(changedIndex?==?"save"){ ????????????????????if(save(changedItem,?changedItem2)){ ????????????????????????Toast.makeText(EditActivity.this,?"撤回保存成功",?Toast.LENGTH_SHORT).show(); ????????????????????} ????????????????} ????????????????break; ????????????case?R.id.buttonSave: ????????????????if?(chosenItem?==?-1){//判断是否选中课 ????????????????????Toast.makeText(EditActivity.this,?"请先选择一节课",?Toast.LENGTH_SHORT).show(); ????????????????}else{ ????????????????????name?=?etName.getText().toString().trim(); ????????????????????time?=?etTime.getText().toString().trim(); ????????????????????room?=?etRoom.getText().toString().trim(); ????????????????????if?(save(name,?time,?room))?{ ????????????????????????Toast.makeText(EditActivity.this,?"保存成功",?Toast.LENGTH_SHORT).show(); ????????????????????} ????????????????} ????????????????break; ????????????case?R.id.buttonBack: ????????????????Intent?intent?=?new?Intent(EditActivity.this,?MainActivity.class); ????????????????startActivity(intent); ????????????????break; ????????} ????} ????public?class?MyAdapter?extends?BaseAdapter?{ ????????@Override ????????public?int?getCount()?{ ????????????return?list_class.size(); ????????} ????????@Override ????????public?Object?getItem(int?i)?{ ????????????return?list_class.get(i); ????????} ????????@Override ????????public?long?getItemId(int?i)?{ ????????????return?i; ????????} ????????@Override ????????public?View?getView(int?i,?View?view,?ViewGroup?viewGroup)?{ ????????????View?newView?=?View.inflate(EditActivity.this,?R.layout.activity_class,?null); ????????????TextView?textView1?=?newView.findViewById(R.id.textViewName); ????????????TextView?textView2?=?newView.findViewById(R.id.textViewTime); ????????????TextView?textView3?=?newView.findViewById(R.id.textViewRoom); ????????????textView1.setText(list_class.get(i).getName()); ????????????textView2.setText(list_class.get(i).getTime()); ????????????textView3.setText(list_class.get(i).getRoom()); ????????????return?newView; ????????} ????}}
package?com.example.a2022finalproject;import?android.os.Parcel;import?android.os.Parcelable;public?class?Class?implements?Parcelable?{ ????private?String?weekNo; ????private?String?name; ????private?String?time; ????private?String?room; ????public?Class(String?weekNo,?String?name,?String?time,?String?room){ ????????this.weekNo?=?weekNo; ????????this.name?=?name; ????????this.time?=?time; ????????this.room?=?room; ????} ????public?Class(){ ????} ????//Parcel ????protected?Class(Parcel?in)?{ ????????weekNo?=?in.readString(); ????????name?=?in.readString(); ????????time?=?in.readString(); ????????room?=?in.readString(); ????} ????public?static?final?Creator<Class>?CREATOR?=?new?Creator<Class>()?{ ????????@Override ????????public?Class?createFromParcel(Parcel?in)?{ ????????????return?new?Class(in); ????????} ????????@Override ????????public?Class[]?newArray(int?size)?{ ????????????return?new?Class[size]; ????????} ????}; ????public?String?getName(){ ????????return?name; ????} ????public?void?setName(String?name){ ????????this.name?=?name; ????} ????public?String?getWeekNo(){ ????????return?weekNo; ????} ????public?void?setWeekNo(String?weekNo){ ????????this.weekNo?=?weekNo; ????} ????public?String?getTime(){ ????????return?time; ????} ????public?void?setTime(String?time){ ????????this.time?=?time; ????} ????public?String?getRoom(){ ????????return?room; ????} ????public?void?setRoom(String?room){ ????????this.room?=?room; ????} ????@Override ????public?int?describeContents()?{ ????????return?0; ????} ????@Override ????public?void?writeToParcel(Parcel?parcel,?int?i)?{ ????????parcel.writeString(weekNo); ????????parcel.writeString(name); ????????parcel.writeString(time); ????????parcel.writeString(room); ????}}
package?com.example.a2022finalproject;import?android.content.ContentValues;import?android.content.Context;import?android.database.sqlite.SQLiteDatabase;import?android.database.sqlite.SQLiteOpenHelper;import?androidx.annotation.Nullable;import?java.sql.Time;//数据库操作类public?class?MyHelper?extends?SQLiteOpenHelper?{ ????public?MyHelper(@Nullable?Context?context)?{ ????????super(context,?"class.db",?null,?1); ????} ????@Override ????public?void?onCreate(SQLiteDatabase?db)?{ ????????//初始化数据库,存入一些基本课程信息 ????????db.execSQL("CREATE?TABLE?class(weekNo?VATCHAR(20),?name?VARCHAR(20),?time?VATCHAR(20),?room?VARCHAR(20))"); ????????ContentValues?values?=?new?ContentValues(); ????????values.put("weekNo",?"1"); ????????values.put("name",?"Web应用程序开发"); ????????values.put("time",?"09:40"); ????????values.put("room",?"29-106"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"1"); ????????values.put("name",?"智能移动设备软件开发"); ????????values.put("time",?"14:00"); ????????values.put("room",?"29-106"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"2"); ????????values.put("name",?"编译原理实验"); ????????values.put("time",?"10:35"); ????????values.put("room",?"29-106"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"2"); ????????values.put("name",?"软件项目管理"); ????????values.put("time",?"14:00"); ????????values.put("room",?"23-213"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"2"); ????????values.put("name",?"软件项目管理实验"); ????????values.put("time",?"15:40"); ????????values.put("room",?"20-109"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"3"); ????????values.put("name",?"马克思主义基本原理"); ????????values.put("time",?"08:00"); ????????values.put("room",?"16-103"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"4"); ????????values.put("name",?"编译原理"); ????????values.put("time",?"10:35"); ????????values.put("room",?"23-319"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"5"); ????????values.put("name",?"Python与数据分析"); ????????values.put("time",?"08:45"); ????????values.put("room",?"25-315"); ????????db.insert("class",?null,?values); ????????values?=?new?ContentValues(); ????????values.put("weekNo",?"5"); ????????values.put("name",?"Python与数据分析实验"); ????????values.put("time",?"10:35"); ????????values.put("room",?"20-206"); ????????db.insert("class",?null,?values); ????} ????@Override ????public?void?onUpgrade(SQLiteDatabase?sqLiteDatabase,?int?i,?int?i1)?{ ????}}
一开始困扰我的是关于listview的问题:就是在MainActivity中,尽管我的listview是放在中下方的位置的,距离顶部还有三分之一的距离,大小也做了限制,但是在实际运行过程中发现课程信息还是会显示在屏幕的最顶上,好像是没有做限制一样。想了半天不知道怎么一回事,后来发现只需要给listview加一个marginTop属性就可以解决这个问题了。
第二个是关于跨Activity传递数据的问题,本来可以简单的直接使用Intent,然后putExtra就可以了,但是我发现好像这样是不能传递ArrayList类型的,所以我使用了bundle来存储ArrayList,然后发现这样的话需要将Class类Parcelabled才可以,这样才最终完成了将list_class传递给编辑界面的功能。
第三个是关于怎么按照时间排序的,一开始没什么头绪,后来找到可以使用Collection.sort来搞定,不过需要写一个TimeSort的函数。
第四个是怎么选中listview上的课程,因为删除和保存两个功能都是需要提前选中课程才可以进行操作的,所以怎么选中要进行操作的课程就是个问题了。后来发现可以给listview2设置点击监听器,通过setOnItemClickListener这个方法来设置,参数new一个AdapterView.OnItemClickListener实例,重写OnItemClick方法就可以实现了。
第五个是怎么使得在我们对数据库课程信息做出了编辑操作之后实时在listview中体现出来。一开始我只是加了一个适配器的notifyDataSetChanged方法,但是发现并没有生效。原来是需要把list_class中的内容也更改了,这样才会使得可以实现动态刷新。
第六个是在保存时,如果只是想修改课程时间,而不修改课程名称和教室,那么就需要重新输入一遍信息,要不然就会变成空白。所以后来我在save函数里加入了判断,如果edittext中为空白就不存入values中,这样也就解决了这个问题。
本项目我觉得还是有很多地方可以提升和改进的。比如可以在MainActivity中设置成左右滑切换哪一天。还有在EditActivity中可以给每一节课加一个单选框,这样相比起Toast来提示选择的哪一节课更直观。还有关于数据库的数据结构设计还可以更好一点(其实是依托答辩 ),添加主键可以防止出现一些错误。关于撤回可以设计成使用数据库的事务回滚来完成。