【android】安卓大作业「课程日历」


完整代码在末尾有github链接

项目要求

项目: 课程日历
-项目概况: 项目记录一周的课程信息。
•用户可以编辑周一~周五的课程表(每天最多安排5门课程) ;
•用户可以按日查看课程表。
-项目要求:
•项目包含2个活动及其对应的布局:
① 显示课程活动:单击“周一”~“周五”按钮中的一个,按时间顺序显示当日的课程信息(上课时间、课程名称、教室);单击“编辑”按钮,进入下一个活动;
② 编辑课程活动:针对选定的周几,可以新增修改删除当日的课程。编辑完毕后,用户单击“保存”按钮则更新当日课程表,或单击“撤销”按钮取消刚才的编辑操作,或单击“返回”按钮,回到显示课程活动。
•布局设计:
① 显示课程活动布局:选用合适的视图控件显示课程信息;
② 编辑课程活动布局:选用恰当的视图控件提供课程编辑方式。
•功能设计:
① 能完成活动之间的跳转;
② 用数据库、数据表存储课程信息;
③ 能编辑和查询单日课程信息。


项目流程图

在这里插入图片描述


结果展示

原始界面:
在这里插入图片描述

点击周一按钮后界面:(其余周数就不进行展示了,差不多)
在这里插入图片描述

选中周数后点击编辑按钮:
在这里插入图片描述

没有选中周数就点击编辑按钮出现的提示Toast:
在这里插入图片描述

输入相关课程信息后点击新增按钮:
在这里插入图片描述

在新增后点击撤销按钮:
在这里插入图片描述

在之前没有编辑操作或者已经撤销一次之后再次点击撤销会弹出提示:
在这里插入图片描述

三个editview如果有一个为空时点击新增按钮会出现的提示:
在这里插入图片描述

一天内课程数为5再点击新建:
在这里插入图片描述

点击listview中的课程会进行提示:
在这里插入图片描述

在选中课程之后点击删除按钮:
在这里插入图片描述

在删除操作后点击撤销按钮:
在这里插入图片描述

在没有选中课程就点击删除按钮出现的提示:
在这里插入图片描述

在选中第一个课程后并且在输入框中输入新的时间以及教室后点击保存按钮:
在这里插入图片描述

在保存之后点击撤销按钮:
在这里插入图片描述

点击返回按钮:
在这里插入图片描述

UI设计

在MainActivity中有使用六个按钮,分别对应的是周一,周二,周三,周四,周五和返回。在下方还有一个listview,用来显示查询出来的课程信息。
listView对应的layout使用的也是相对布局,包含三个TextView,用来分别显示课程的名称,时间以及上课教室。
EditActivity里面包含一个listview,用来显示查询出来的课程信息以及供用户进行选中,五个按钮,分别对应的是新增,删除,保存,撤销以及返回,还有一个textview用来对用户进行提示,3个EditText用来读取需要编辑的课程信息。
MainActivity:
在这里插入图片描述

EditActivity:
在这里插入图片描述

Listview的layout:

在这里插入图片描述

activity_main.xml代码

<?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>

activity_edit.xml代码

<?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>

activity_class.xml代码

<?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>

功能设计

简单功能说明

在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,显示新增的课程。


以下代码附有注释


MainActivity.java代码

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;
        }
    }
}

EditActivity.java代码

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;
        }
    }
}

Class.java代码

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);
    }
}

MyHelper.java代码

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) {
    
    

    }
}


总结反思

  1. 一开始困扰我的是关于listview的问题:就是在MainActivity中,尽管我的listview是放在中下方的位置的,距离顶部还有三分之一的距离,大小也做了限制,但是在实际运行过程中发现课程信息还是会显示在屏幕的最顶上,好像是没有做限制一样。想了半天不知道怎么一回事,后来发现只需要给listview加一个marginTop属性就可以解决这个问题了。
  2. 第二个是关于跨Activity传递数据的问题,本来可以简单的直接使用Intent,然后putExtra就可以了,但是我发现好像这样是不能传递ArrayList类型的,所以我使用了bundle来存储ArrayList,然后发现这样的话需要将Class类Parcelabled才可以,这样才最终完成了将list_class传递给编辑界面的功能。
  3. 第三个是关于怎么按照时间排序的,一开始没什么头绪,后来找到可以使用Collection.sort来搞定,不过需要写一个TimeSort的函数。
  4. 第四个是怎么选中listview上的课程,因为删除和保存两个功能都是需要提前选中课程才可以进行操作的,所以怎么选中要进行操作的课程就是个问题了。后来发现可以给listview2设置点击监听器,通过setOnItemClickListener这个方法来设置,参数new一个AdapterView.OnItemClickListener实例,重写OnItemClick方法就可以实现了。
  5. 第五个是怎么使得在我们对数据库课程信息做出了编辑操作之后实时在listview中体现出来。一开始我只是加了一个适配器的notifyDataSetChanged方法,但是发现并没有生效。原来是需要把list_class中的内容也更改了,这样才会使得可以实现动态刷新。
  6. 第六个是在保存时,如果只是想修改课程时间,而不修改课程名称和教室,那么就需要重新输入一遍信息,要不然就会变成空白。所以后来我在save函数里加入了判断,如果edittext中为空白就不存入values中,这样也就解决了这个问题。

本项目我觉得还是有很多地方可以提升和改进的。比如可以在MainActivity中设置成左右滑切换哪一天。还有在EditActivity中可以给每一节课加一个单选框,这样相比起Toast来提示选择的哪一节课更直观。还有关于数据库的数据结构设计还可以更好一点(其实是依托答辩 ),添加主键可以防止出现一些错误。关于撤回可以设计成使用数据库的事务回滚来完成。


完整代码:
github链接
gitee链接
新手上路,有错请指正;

猜你喜欢

转载自blog.csdn.net/qq_33884853/article/details/128555403