
用Android手擼一個簡易的個人記賬系統
- ??序言
- 📋一、系統結構設計Design
- 1. 需求分析
- 2. 資料庫設計
- 3. 界面設計
- 4. 程序設計
- 📘二、編碼階段Coding
- 1. 專案結構🗂?
- (1)檔案目錄
- (2)AndroidManifest.xml
- (3)Activity類解讀
- (4)XML解讀
- 2. 靜態頁面?
- (1)用戶登錄頁面activity_main.xml
- (2)用戶注冊頁面activity_register.xml
- (3)用戶個人中心頁面activity_user_center.xml
- (4)用戶搜索記錄頁面activity_search_record.xml
- (5)收支管理頁面activity_manage.xml
- (6)串列資料記錄record_item_layout.xml
- 3. 邏輯結構💡
- (1)DBHelper類
- (2)MainActivity類
- (3)RegisterActivity類
- (4)UserCenterActivity類
- (5)SearchRecordActivity類
- (6)ManageActivity類
- (7)User類
- 🎵三、運行結果Result
- 📈四、結束語
- 🐣彩蛋 One More Thing
- (:不合理設計
- (:番外篇
??序言
前段時間期末周,這學期有一門課叫移動應用開發,這門課的期末作業是用 Android 寫一個個人記賬管理系統, Android 的前臺是用 xml 實作,后臺是用 java 實作,于是,對這兩門語言不太熟悉的周一,開始了漫漫長路的摸索之旅,
接下來就來講解,如何從0到1實作一個簡易的個人記賬系統,
一起來學習⑧~🙃
溫馨小提示: 第二部分的編碼階段代碼較多,可直接滑到第三部分看運行效果,并到第四部分克隆github倉庫代碼,閱讀體驗更加~
📋一、系統結構設計Design
1. 需求分析
首先我們先來看下老師的需求👇
設計和實作一個類似個人財務管理的 Android APP ,資料庫采用 SQLite (也可以直接訪問 Web 端 MySQL 資料庫、或提供 Web 介面訪問 MySQL 資料庫),
APP應具備以下功能:
- 用戶注冊和登錄(這類
APP一般面對個人,用戶不需要分類別); - 收入和支出管理(單條收支記錄的添加、洗掉和修改,收入和支出每一條記錄至少包括日期、型別、金額和說明,)
- 收入和支出查詢(根據時間段、類別等進行查詢)
- 收入和支出統計(例如某個月、某個星期或指定時間段的總收支)
- 其他要求:界面設計應盡量美觀,可以添加一些圖片或背景,
基于以上需求,周一對所要實作的功能進行了整理,請看下方思維導圖:

2. 資料庫設計
分析完成之后,接下來開始設計資料庫,詳情見下方思維導圖:

因為功能較為簡單,所以資料庫只設計了兩張表,
3. 界面設計
設計完資料庫之后,開始楷模潤色該 APP 的界面,基于本次課題需求,周一設計了5個界面,接下來先來看 App 的具體界面設計:

看完五個界面所需要的內容之后,接下來,我們來對它進行原型繪制,請看下圖:

現在,原型圖設計完畢,我們接著設計高保真 App 界面,請看下圖:


4. 程序設計
好了,看完原型圖之后,我們是不是該來想想頁面與頁面之間,是怎么進行互動的呢?
因此,現在我們來對整個程序進行設計,詳情見下方思維導圖:

📘二、編碼階段Coding
1. 專案結構🗂?
(1)檔案目錄
先來看專案的檔案目錄,詳情看下圖👇

(2)AndroidManifest.xml
接下來附上 AndroidManifest.xml 的代碼,具體代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.financial.management">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="個人財務管理App"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.Final">
<activity android:name="com.financial.management.ManageActivity"></activity>
<activity android:name="com.financial.management.SearchRecordActivity" />
<activity android:name="com.financial.management.RegisterActivity"/>
<activity android:name="com.financial.management.UserCenterActivity" />
<activity android:name="com.financial.management.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
(3)Activity類解讀
看完上面兩個內容之后,接下來是Activity類的解讀時間,詳情見下表👇
| 檔案名 | 作用 |
|---|---|
| MainActivity | 用戶登錄頁面Activity,用戶可以進行登錄, |
| RegisterActivity | 用戶注冊頁面Activity,用戶可以進行注冊, |
| UserCenterActivity | 個人中心Activity,對應用戶個人中心的4個按鈕進行功能撰寫,實作用戶收支管理、查看收支、收支統計、退出登錄四大功能, |
| ManageActivity | 收支管理Activity,對用戶的收入和支出進行管理, |
| SearchRecordActivity | 查詢收支Activity,通過條件對資料庫中的資料進行查詢,得出用戶想要查詢的收支結果, |
| DBHelper | 創建資料庫表和資料庫資料,同時實作與資料庫操作相關的登錄和注冊方法, |
| User | 用戶類Activity,用于獲取用戶ID以及密碼, |
(4)XML解讀
解讀完 Activity 類之后,現在來對 XML 的各個檔案進行介紹,詳情見下表👇
| 檔案名 | 作用 |
|---|---|
| activity_main.xml | 用戶登錄頁面,用戶通過輸入賬號和密碼,進行登錄操作, |
| activity_register.xml | 用戶注冊頁面,用戶通過輸入賬號和密碼,進行注冊操作, |
| activity_user_center.xml | 個人中心頁面,當用戶登錄成功以后,進行個人中心頁面,個人中心實作收支管理、查看收支、收支統計、退出登錄四大功能, |
| activity_search_record.xml | 通過選擇年份月份來進行查詢該年該月份的各個收入支出詳情,并且計算總金額以及根據類別來計算該類別的總金額, |
| activity_manage.xml | 用戶對自己的日常開銷進行收支管理,可以進行添加、洗掉和修改等操作, |
| record_item_layout.xml | 用來存盤串列的傳輸資料 |
到這里,大家先對待會要撰寫的 Activity 類和 XML 檔案所要展示的功能先進行一番了解,
2. 靜態頁面?
現在,我們到了真正的編碼階段啦!如果是按照我的編碼習慣的話,我一般會先把靜態頁面進行構建,并把一些需要預留的id等等資訊給先處理好,方便后面寫業務邏輯時可以直接進行系結,
針對以上6個靜態頁面,下面將進行代碼撰寫,
(1)用戶登錄頁面activity_main.xml
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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView1"
android:layout_width="360dp"
android:layout_height="360dp"
android:gravity="center"
android:background="@drawable/login_logo"
android:textColor="#fff"
android:textSize="24dp"
android:layout_marginTop="-30dp"
android:layout_marginHorizontal="45dp"/>
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center|center_horizontal"
android:text="用戶登錄"
android:textColor="#5768C5"
android:textSize="20dp"
android:layout_marginTop="-60dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:paddingVertical="10dp">
<ImageView
android:id="@+id/imageView3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="0"
app:srcCompat="@drawable/account" />
<EditText
android:id="@+id/edt_uid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:ems="10"
android:hint="請輸入您的用戶名"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:paddingVertical="10dp">
<ImageView
android:id="@+id/imageView4"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="0"
app:srcCompat="@drawable/password" />
<EditText
android:id="@+id/edt_upwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="請輸入您的密碼"
android:inputType="textPassword" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="60dp">
<Button
android:id="@+id/btn_login"
android:layout_width="100dp"
android:layout_height="60dp"
android:layout_weight="1"
android:text="登錄"
android:textSize="18dp"
app:backgroundTint="#4757AE"
app:cornerRadius="50dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/btn_register"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:text="還沒有賬號?現在注冊"
android:textColor="#888282"
android:textColorHint="#FFFFFFFF"
android:backgroundTint="#FFFFFFFF"
android:color="#FFFFFF"
/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="#FFFFFF"
android:layout_marginTop="-10dp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
(2)用戶注冊頁面activity_register.xml
activity_register.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=".RegisterActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView10"
android:layout_width="220dp"
android:layout_height="220dp"
android:background="@drawable/register_logo"
android:gravity="center"
android:textColor="#FFEB3B"
android:layout_marginBottom="20dp"/>
<TextView
android:id="@+id/textView5"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="用戶注冊"
android:textColor="#0C6BC2"
android:textSize="22sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:layout_marginTop="10dp">
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_weight="0"
android:text="賬 號: "
android:textColor="#0C6BC2"
android:textSize="22sp" />
<EditText
android:id="@+id/edt_rid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="請輸入需要注冊的賬號"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="20dp"
android:layout_marginVertical="15dp">
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:text="密 碼: "
android:textColor="#0C6BC2"
android:textSize="22sp" />
<EditText
android:id="@+id/edt_rpwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="請輸入密碼"
android:inputType="textPassword" />
</LinearLayout>
<Button
android:id="@+id/btn_registeruser"
android:layout_width="260dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:layout_marginVertical="20dp"
android:background="#2D6C2F"
android:gravity="center"
android:text="注冊"
android:textSize="22sp"
app:backgroundTint="#1C8DE6" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
(3)用戶個人中心頁面activity_user_center.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=".UserCenterActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="120dp"
android:orientation="horizontal"
android:gravity="center">
<ImageView
android:id="@+id/imageView"
android:layout_width="60dp"
android:layout_height="60dp"
app:srcCompat="@drawable/girl"
android:layout_marginHorizontal="30dp"/>
<TextView
android:id="@+id/tv_welcome"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center|left"
android:textColor="#4F92CF"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:layout_marginTop="40dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:background="#FFFFFF"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="24dp"
android:elevation="10dp"
app:cornerRadius="30dp">
<ImageView
android:id="@+id/btn_recordmanage"
android:layout_width="60dp"
android:layout_height="60dp"
app:srcCompat="@drawable/revenue" />
<TextView
android:id="@+id/textView17"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="收支管理"
android:textColor="#252020"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_marginHorizontal="20dp"
android:background="#FFFFFF"
android:padding="24dp"
android:elevation="10dp"
app:cornerRadius="30dp">
<ImageView
android:id="@+id/btn_searchrecord"
android:layout_width="60dp"
android:layout_height="60dp"
app:srcCompat="@drawable/look" />
<TextView
android:id="@+id/textView22"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查看收支"
android:textColor="#FF252020"
android:textSize="18sp"
android:layout_marginTop="20dp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:layout_marginVertical="30dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_marginHorizontal="20dp"
android:background="#FFFFFF"
android:padding="24dp"
android:elevation="10dp"
app:cornerRadius="30dp">
<ImageView
android:id="@+id/btn_exit"
android:layout_width="60dp"
android:layout_height="60dp"
app:srcCompat="@drawable/exit" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="退出登錄"
android:textColor="#FF252020"
android:textSize="18sp"
android:layout_marginTop="20dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_marginHorizontal="20dp"
android:background="#FFFFFF"
android:padding="24dp"
android:elevation="10dp"
app:cornerRadius="30dp">
<ImageView
android:id="@+id/btn_calcmoney"
android:layout_width="60dp"
android:layout_height="60dp"
app:srcCompat="@drawable/statics" />
<TextView
android:id="@+id/textView23"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="收支統計"
android:textColor="#FF252020"
android:textSize="18sp"
android:layout_marginTop="20dp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
(4)用戶搜索記錄頁面activity_search_record.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="wrap_content"
tools:context=".SearchRecordActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_marginTop="50dp"
android:layout_marginBottom="10dp">
<ImageView
android:id="@+id/imageView2"
android:layout_width="120dp"
android:layout_height="120dp"
app:srcCompat="@drawable/income_2" />
<TextView
android:id="@+id/textView20"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="我的收支"
android:textColor="#3F51B5"
android:textSize="20sp"
android:layout_marginTop="10dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="30dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="100dp"
android:orientation="vertical">
<TextView
android:id="@+id/textView33"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:text="日期 "
android:gravity="center_vertical"
android:textColor="#111113"
android:textSize="18sp" />
<TextView
android:id="@+id/textView34"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:text="型別 "
android:gravity="center_vertical"
android:textColor="#FF111113"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_weight="1"
android:orientation="vertical">
<Spinner
android:id="@+id/spin_date"
android:layout_width="match_parent"
android:layout_height="50dp" />
<Spinner
android:id="@+id/spin_type"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="100dp"
android:orientation="vertical"
android:gravity="center_vertical">
<Button
android:id="@+id/btn_search"
android:layout_width="60dp"
android:layout_height="40dp"
android:background="#39DC54"
android:text="搜索"
android:textColor="#FAF9F9"
android:textSize="12sp"
app:backgroundTint="#5E97DA" />
</LinearLayout>
</LinearLayout>
<ImageView
android:layout_width="360dp"
android:layout_height="0.5dp"
android:background="#D1CDCD"
android:layout_gravity="center"
android:paddingHorizontal="24dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:layout_marginHorizontal="24dp">
<TextView
android:id="@+id/textView32"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:text="總金額 "
android:gravity="center_vertical"
android:textColor="#FF111113"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_show"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_weight="1"
android:textColor="#4CAF65"
android:textSize="24sp"
android:gravity="center_vertical"/>
<Button
android:id="@+id/btn_calc"
android:layout_width="60dp"
android:layout_height="40dp"
android:gravity="center_vertical"
android:text="計算"
android:textColor="#FAF9F9"
android:textSize="12sp"
app:backgroundTint="#5E97DA" />
</LinearLayout>
<ImageView
android:layout_width="360dp"
android:layout_height="0.5dp"
android:background="#D1CDCD"
android:layout_gravity="center"
android:paddingHorizontal="20dp"/>
<TextView
android:id="@+id/textView31"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:text="查詢結果 "
android:layout_marginTop="20dp"
android:textColor="#111113"
android:layout_marginHorizontal="24dp"
android:textSize="18sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginVertical="20dp"
android:layout_marginHorizontal="20dp">
<TextView
android:id="@+id/textView29"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="序號"
android:textColor="#6290c8"
android:textStyle="bold"
android:textSize="18sp"
android:gravity="center_horizontal"/>
<TextView
android:id="@+id/textView26"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="日期"
android:textColor="#6290c8"
android:textStyle="bold"
android:textSize="18sp"
android:gravity="center_horizontal"/>
<TextView
android:id="@+id/textView25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="型別"
android:textColor="#6290c8"
android:textStyle="bold"
android:textSize="18sp"
android:gravity="center_horizontal"/>
<TextView
android:id="@+id/textView27"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="金額"
android:textColor="#6290c8"
android:textStyle="bold"
android:textSize="18sp"
android:gravity="center_horizontal"/>
<TextView
android:id="@+id/textView28"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="說明"
android:textColor="#6290c8"
android:textStyle="bold"
android:textSize="18sp"
android:gravity="center_horizontal"/>
</LinearLayout>
<ListView
android:id="@+id/searchlistview"
android:layout_width="match_parent"
android:layout_height="500dp"
android:layout_weight="0"
android:layout_marginHorizontal="20dp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
(5)收支管理頁面activity_manage.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=".ManageActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView2"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginTop="20dp"
app:srcCompat="@drawable/income_1" />
<TextView
android:id="@+id/textView20"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:text="收支管理"
android:textColor="#3F51B5"
android:textSize="20dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/textView36"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:text="您選擇的序號是:"
android:textColor="#152029"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="暫未選擇"
android:textColor="#4CAF50"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/textView29"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:text="序號"
android:textColor="#111819"
android:textSize="18sp" />
<TextView
android:id="@+id/textView26"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="日期"
android:textColor="#111819"
android:textSize="18sp" />
<TextView
android:id="@+id/textView25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="型別"
android:textColor="#111819"
android:textSize="18sp" />
<TextView
android:id="@+id/textView27"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="金額"
android:textColor="#111819"
android:textSize="18sp" />
<TextView
android:id="@+id/textView28"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="說明"
android:textColor="#111819"
android:textSize="18sp" />
</LinearLayout>
<ImageView
android:layout_width="380dp"
android:layout_height="0.5dp"
android:background="#D8D3D3"
android:paddingHorizontal="20dp" />
<ListView
android:id="@+id/recordlistview"
android:layout_width="wrap_content"
android:layout_height="120dp"
android:layout_weight="1"></ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="14dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView18"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="日期: "
android:textColor="#101112"
android:textSize="18sp" />
<EditText
android:id="@+id/edt_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="填寫日期,如:202107表示2021年7月"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="14dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView21"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="型別: "
android:textColor="#101112"
android:textSize="18sp" />
<EditText
android:id="@+id/edt_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="型別為收入或支出"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="14dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="金額: "
android:textColor="#101112"
android:textSize="18sp" />
<EditText
android:id="@+id/edt_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="請輸入金額"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="14dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="說明: "
android:textColor="#101112"
android:textSize="18sp" />
<EditText
android:id="@+id/edt_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="闡述說明"
android:inputType="textPersonName" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="30dp">
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_weight="1"
android:text="添加"
app:backgroundTint="#78C6A3" />
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_weight="1"
android:text="修改"
app:backgroundTint="#56AB91" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_weight="1"
android:text="洗掉"
app:backgroundTint="#358F80" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
(6)串列資料記錄record_item_layout.xml
record_item_layout.xml 主要用途是存盤串列的傳輸資料,具體代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_marginHorizontal="20dp"
android:gravity="center_horizontal"
android:paddingVertical="2dp">
<TextView
android:id="@+id/list_id"
android:layout_width="40dp"
android:layout_height="24dp"
android:layout_weight="1"
android:textSize="18sp"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/list_date"
android:layout_width="90dp"
android:layout_height="24dp"
android:layout_weight="1"
android:textSize="18sp"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/list_type"
android:layout_width="70dp"
android:layout_height="24dp"
android:layout_weight="1"
android:textSize="18sp"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/list_money"
android:layout_width="70dp"
android:layout_height="24dp"
android:layout_weight="1"
android:textSize="18sp"
android:gravity="center_horizontal" />
<TextView
android:id="@+id/list_state"
android:layout_width="90dp"
android:layout_height="24dp"
android:layout_weight="1"
android:textSize="18sp"
android:gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
3. 邏輯結構💡
寫完靜態頁面之后,接下來我們要對每個頁面的邏輯進行撰寫,現在我們來看一下各個 Activity 類所實作的內容都有些什么呢?
(1)DBHelper類
DBHelper 類用于創建資料庫表和資料庫資料,同時實作與資料庫操作相關的登錄和注冊方法,具體代碼實作如下:
package com.financial.management;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "Test.db";
public static final String TABLE_NAME = "userinfo";
public static final String COLUMN_USERID = "uid";
public static final String COLUMN_USERPWD = "upwd";
//創建資料庫陳述句
private static final String CREATE_TABLE = "create table if not exists "
+ TABLE_NAME + "(" + COLUMN_USERID + " text not null primary key,"
+ COLUMN_USERPWD + " text not null)";
public DBHelper(Context context) {
super(context, DB_NAME, null, 1);
}
//創建資料庫方法
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(CREATE_TABLE);
db.execSQL("insert into " + TABLE_NAME + " values('11','11')");
} catch (SQLException e) {
e.printStackTrace();
}
}
//重置資料庫方法(先刪表,再建表)
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists " + TABLE_NAME);
db.execSQL(CREATE_TABLE);
}
//登錄方法
public User userlogin(String userId, String userPwd) {
User user = null;
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME,
new String[]{COLUMN_USERID, COLUMN_USERPWD},
COLUMN_USERID + "=? and " + COLUMN_USERPWD + "=?",
new String[]{userId, userPwd},
null,
null,
null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
user = new User();
user.setUserId(cursor.getString(cursor.getColumnIndex(COLUMN_USERID)));
user.setUserPwd(cursor.getString(cursor.getColumnIndex(COLUMN_USERPWD)));
}
return user;
}
//注冊方法
public long registerUser(User user) {
SQLiteDatabase db = getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COLUMN_USERID, user.getUserId());
contentValues.put(COLUMN_USERPWD, user.getUserPwd());
return db.insert(TABLE_NAME, null, contentValues);
}
}
(2)MainActivity類
MainActivity 類是用戶登錄頁面的Activity,主要撰寫用戶登錄頁面的代碼邏輯,具體代碼實作如下:
package com.financial.management;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.ArrayList;
//登錄頁面邏輯
public class MainActivity extends AppCompatActivity {
EditText edt_id,edt_pwd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edt_id = findViewById(R.id.edt_uid);
edt_pwd =findViewById(R.id.edt_upwd);
Button btn_login = findViewById(R.id.btn_login);
//登錄按鍵
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String userId=edt_id.getText().toString();
String userPwd=edt_pwd.getText().toString();
DBHelper dbuserHelper=new DBHelper(getApplicationContext());
User user = dbuserHelper.userlogin(userId,userPwd);
//登錄成功跳轉對應型別界面
if(user!=null) {
Toast.makeText(getApplicationContext(), user.getUserId() + "登錄成功", Toast.LENGTH_SHORT).show();
Intent intent;
ArrayList<User> list = new ArrayList<>();
list.add(user);
intent = new Intent(getApplicationContext(), UserCenterActivity.class);
intent.putParcelableArrayListExtra("LoginUser", list);
startActivity(intent);
}else{
Toast.makeText(getApplicationContext(),"登錄失敗,密碼錯誤或賬號不存在!",Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"資料庫例外",Toast.LENGTH_SHORT).show();
}
}
});
//注冊按鍵
Button btn_register=findViewById(R.id.btn_register);
btn_register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(getApplicationContext(),RegisterActivity.class);
startActivity(intent);
}
});
}
}
(3)RegisterActivity類
RegisterActivity 類是用戶注冊頁面的Activity,主要撰寫用戶注冊頁面的業務邏輯,具體代碼實作如下:
package com.financial.management;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.ArrayList;
//注冊頁面邏輯
public class RegisterActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
final EditText edt_rid =findViewById(R.id.edt_rid);
final EditText edt_rpwd =findViewById(R.id.edt_rpwd);
//注冊按鍵
Button btn_registerf=findViewById(R.id.btn_registeruser);
btn_registerf.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
User user = new User();
user.setUserId(edt_rid.getText().toString());
user.setUserPwd(edt_rpwd.getText().toString());
DBHelper dbUserHelper = new DBHelper(getApplicationContext());
if (dbUserHelper.registerUser(user) > 0) {
Toast.makeText(getApplicationContext(), "注冊成功", Toast.LENGTH_SHORT).show();
Intent intent;
ArrayList<User> list = new ArrayList<>();
list.add(user);
intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
}else{
Toast.makeText(getApplicationContext(), "您已經注冊過此賬戶,請回傳登錄", Toast.LENGTH_SHORT).show();
}
}
});
}
}
(4)UserCenterActivity類
UserCenterActivity 類是個人中心頁面的Activity,主要撰寫個人中心各種按鈕跳轉的業務邏輯,具體代碼實作如下:
package com.financial.management;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
//用戶個人中心頁面邏輯
public class UserCenterActivity extends AppCompatActivity {
ArrayList<User> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_center);
Intent intent=getIntent();
list =intent.getParcelableArrayListExtra("LoginUser");
User user=list.get(0);
final String username=user.getUserId();
TextView tv_welcome=findViewById(R.id.tv_welcome);
tv_welcome.setText("歡迎您 ,用戶"+username);
//收支管理
ImageView btn_recordmanage =findViewById(R.id.btn_recordmanage);
btn_recordmanage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent1=new Intent(getApplicationContext(), ManageActivity.class);
startActivity(intent1);
}
});
//收支查詢
ImageView btn_searchrecord=findViewById(R.id.btn_searchrecord);
btn_searchrecord.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent2=new Intent(getApplicationContext(),SearchRecordActivity.class);
startActivity(intent2);
}
});
//收支統計
ImageView btn_calcmoney=findViewById(R.id.btn_calcmoney);
btn_calcmoney.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent3=new Intent(getApplicationContext(),SearchRecordActivity.class);
startActivity(intent3);
}
});
//退出按鍵
ImageView btn_exit=findViewById(R.id.btn_exit);
btn_exit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog dialog = new AlertDialog.Builder(UserCenterActivity.this).setTitle("退出操作")
.setMessage("確定退出,不繼續玩玩?")
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
}
}).setNegativeButton("繼續留下!", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).create();
dialog.show();
}
});
}
}
(5)SearchRecordActivity類
SearchRecordActivity 類是搜索記錄頁面的Activity,主要撰寫我的收支頁面的業務邏輯,具體代碼實作如下:
package com.financial.management;
import androidx.appcompat.app.AppCompatActivity;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
//收支記錄頁面業務邏輯
public class SearchRecordActivity extends AppCompatActivity {
//定義spinner中的資料
private String[] date_data= {"", "202101", "202102", "202103", "202104", "202105","202106","202107","202108","202109","202110","202111","202112"};
private String[] type_data = {"", "收入", "支出"};
Spinner spin_date, spin_type;
ListView listView;
TextView tv_show;
float sum=0;
//資料庫
private String selectDate, selectType;
private static final String DATABASE_NAME = "Test.db";
private static final String TABLE_NAME = "record";
private static final String COLUMN_ID = "id";
private static final String COLUMN_DATE = "date";
private static final String COLUMN_TYPE = "type";
private static final String COLUMN_MONEY = "money";
private static final String COLUMN_STATE = "state";
private SQLiteDatabase sqLiteDatabase = null;
private void selectSumMoney() {
//自定義查詢的sql陳述句
String sql;
//如果查詢時間和查詢型別都為空,則查詢整個表
if (TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
sql = "select * from " + TABLE_NAME;
//如果有查詢時間,沒有查詢型別,查詢指定內容
} else if (!TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "'";
//如果沒有查詢時間,有查詢型別,查詢指定內容
} else if (TextUtils.isEmpty(selectDate) && !TextUtils.isEmpty(selectType)) {//如果沒有查詢時間,有查詢型別
sql = "select * from " + TABLE_NAME + " where type='" + selectType+"'";
} else {//否則,查詢條件都不為空,查詢指定內容
sql ="select * from " + TABLE_NAME + " where date='" + selectDate + "' and type='" + selectType+"'";
}
Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
while (cursor.moveToNext()) {
float money = cursor.getFloat(cursor.getColumnIndex(COLUMN_MONEY));
sum=sum+money;
//list.add(map);
}
String money2=String.valueOf(sum);
tv_show.setText(money2);
sum=0;
}
//選擇資料
private void selectData() {
//自定義查詢的sql陳述句
String sql;
//如果查詢時間和查詢型別都為空,則查詢整個表
if (TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
sql = "select * from " + TABLE_NAME;
//如果有查詢時間,沒有查詢型別,查詢指定內容
} else if (!TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "'";
//如果沒有查詢時間,有查詢型別,查詢指定內容
} else if (TextUtils.isEmpty(selectDate) && !TextUtils.isEmpty(selectType)) {//如果沒有查詢時間,有查詢型別
sql = "select * from " + TABLE_NAME + " where type='" + selectType+"'";
} else {//否則,查詢條件都不為空,查詢指定內容
sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "' and type='" + selectType+"'";
}
//將查詢到的資料封裝到Cursor
Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
if (cursor.getCount() == 0) {
//查無資料則怒不顯示串列
// listView.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), "無資料", Toast.LENGTH_SHORT).show();
} else {
//查有資料則顯示串列
listView.setVisibility(View.VISIBLE);
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex(COLUMN_ID));
String date = cursor.getString(cursor.getColumnIndex(COLUMN_DATE));
String type = cursor.getString(cursor.getColumnIndex(COLUMN_TYPE));
float money = cursor.getFloat(cursor.getColumnIndex(COLUMN_MONEY));
String state = cursor.getString(cursor.getColumnIndex(COLUMN_STATE));
Map<String, String> map = new HashMap<String, String>();
map.put("id", String.valueOf(id));
map.put("date", date);
map.put("type", type);
map.put("money", String.valueOf(money));
map.put("state", state);
list.add(map);
}
//創建SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(getApplicationContext(),
list,
R.layout.record_item_layout,
new String[]{"id", "date", "type", "money", "state"},
new int[]{R.id.list_id, R.id.list_date, R.id.list_type, R.id.list_money, R.id.list_state});
listView.setAdapter(simpleAdapter);
}
}
//時間和類別spinner點擊事件
private void initClick() {
//時間事件
spin_date.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectDate = date_data[position];
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//類別事件
spin_type.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectType = type_data[position];
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
findViewById(R.id.btn_search).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectData();
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_record);
tv_show=findViewById(R.id.tv_show);
try {
//打開資料庫,如果是第一次會創建該資料庫,模式為MODE_PRIVATE
sqLiteDatabase = openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
//執行創建表的sql陳述句,雖然每次都呼叫,但只有首次才創建表
//執行查詢
listView = findViewById(R.id.searchlistview);//系結串列
selectData();
} catch (SQLException e) {
Toast.makeText(this, "資料庫例外!", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
ArrayAdapter<String> adapter = new
ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, date_data);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin_date = findViewById(R.id.spin_date);
spin_date.setAdapter(adapter);
ArrayAdapter<String> adapter1 = new
ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, type_data);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin_type = findViewById(R.id.spin_type);
spin_type.setAdapter(adapter1);
initClick();
Button btn_calc=findViewById(R.id.btn_calc);
btn_calc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectSumMoney();
}
});
}
}
(6)ManageActivity類
ManageActivity 類是收支管理頁面的Activity,主要撰寫用戶的收入和支出的業務邏輯,實作收支的增刪改查,具體代碼實作如下:
package com.financial.management;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ManageActivity extends AppCompatActivity {
private SQLiteDatabase sqLiteDatabase = null;
private int selectId = -1;
EditText edt_date, edt_type, edt_money, edt_state;
TextView tv_test;
private static final String DATABASE_NAME = "Test.db";
private static final String TABLE_NAME = "record";
private static final String COLUMN_ID = "id";
private static final String COLUMN_DATE = "date";
private static final String COLUMN_TYPE = "type";
private static final String COLUMN_MONEY = "money";
private static final String COLUMN_STATE = "state";
//創建表
private static final String CREATE_TABLE = "create table if not exists " + TABLE_NAME
+ "(" + COLUMN_ID + " integer primary key autoincrement," + COLUMN_DATE + " text," + COLUMN_TYPE
+ " text," + COLUMN_MONEY + " float," + COLUMN_STATE + " text)";
//自定義的查詢方法
private void selectData() {
//遍歷整個表
String sql = "select * from " + TABLE_NAME ;
//把查詢資料封裝到Cursor
Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
//用while回圈遍歷Cursor,再把它分別放到map中,最后統一存入list中,便于呼叫
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex(COLUMN_ID));
String date = cursor.getString(cursor.getColumnIndex(COLUMN_DATE));
String type = cursor.getString(cursor.getColumnIndex(COLUMN_TYPE));
float money = cursor.getFloat(cursor.getColumnIndex(COLUMN_MONEY));
String state = cursor.getString(cursor.getColumnIndex(COLUMN_STATE));
Map<String, String> map = new HashMap<String, String>();
map.put("id", String.valueOf(id));
map.put("date", date);
map.put("type", type);
map.put("money", String.valueOf(money));
map.put("state", state);
list.add(map);
}
//創建SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(getApplicationContext(),
list,
R.layout.record_item_layout,
new String[]{"id", "date", "type", "money", "state"},
new int[]{R.id.list_id, R.id.list_date, R.id.list_type, R.id.list_money, R.id.list_state});
final ListView listView = findViewById(R.id.recordlistview);
//系結配接器
listView.setAdapter(simpleAdapter);
//設定ListView單擊事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ListView tempList = (ListView) parent;
View mView = tempList.getChildAt(position);
TextView list_id = mView.findViewById(R.id.list_id);
TextView list_date = mView.findViewById(R.id.list_date);
TextView list_type = mView.findViewById(R.id.list_type);
TextView list_money = mView.findViewById(R.id.list_money);
TextView list_state = mView.findViewById(R.id.list_state);
String rid = list_id.getText().toString();
String date = list_date.getText().toString();
String type = list_type.getText().toString();
String money = list_money.getText().toString();
String state = list_state.getText().toString();
tv_test.setText(rid);
edt_date.setText(date);
edt_type.setText(type);
edt_money.setText(money);
edt_state.setText(state);
selectId = Integer.parseInt(rid);
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage);
try {
sqLiteDatabase = openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
sqLiteDatabase.execSQL(CREATE_TABLE);
//執行查詢
selectData();
} catch (SQLException e) {
Toast.makeText(this, "資料庫例外!", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
tv_test = findViewById(R.id.tv_test);
edt_date = findViewById(R.id.edt_date);
edt_type = findViewById(R.id.edt_type);
edt_money = findViewById(R.id.edt_money);
edt_state = findViewById(R.id.edt_state);
//新增按鍵
Button btn_add = findViewById(R.id.btn_add);
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (edt_date.getText().toString().equals("") | edt_type.getText().toString().equals("") | edt_money.getText().toString().equals("") | edt_state.getText().toString().equals("")) {
Toast.makeText(ManageActivity.this, "資料不能為空!", Toast.LENGTH_LONG).show();
return;
}
String date = edt_date.getText().toString();
String type = edt_type.getText().toString();
String money = edt_money.getText().toString();
String state = edt_state.getText().toString();
//定義添加資料的sql陳述句
String sql = "insert into " + TABLE_NAME + "(" + COLUMN_DATE + "," + COLUMN_TYPE + "," + COLUMN_MONEY + "," + COLUMN_STATE + ") " +
"values('" + date + "','" + type + "','" + money + "','" + state + "')";
//執行sql陳述句
sqLiteDatabase.execSQL(sql);
Toast.makeText(getApplicationContext(), "新增資料成功!", Toast.LENGTH_LONG).show();
//重繪顯示串列
selectData();
//消除資料
tv_test.setText("");
edt_date.setText("");
edt_type.setText("");
edt_money.setText("");
edt_state.setText("");
}
});
//修改按鍵
Button btn_update = findViewById(R.id.btn_update);
btn_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//無選擇提示
if (selectId == -1) {
Toast.makeText(getApplicationContext(), "請選擇要修改的行!", Toast.LENGTH_LONG).show();
return;
}
//判斷是否有空資料
if (edt_date.getText().toString().equals("") | edt_type.getText().toString().equals("") | edt_money.getText().toString().equals("") | edt_state.getText().toString().equals("")) {
Toast.makeText(getApplicationContext(), "資料不能為空!", Toast.LENGTH_LONG).show();
return;
}
String date = edt_date.getText().toString();
String type = edt_type.getText().toString();
String money = edt_money.getText().toString();
String state = edt_state.getText().toString();
//定義修改資料的sql陳述句
String sql = "update " + TABLE_NAME + " set " + COLUMN_DATE + "='" + date + "',type='" + type + "',money='" + money + "',state='" + state + "' where id=" + selectId;
//執行sql陳述句
sqLiteDatabase.execSQL(sql);
Toast.makeText(getApplicationContext(), "修改資料成功!", Toast.LENGTH_LONG).show();
//重繪顯示串列
selectData();
selectId = -1;
//消除資料
tv_test.setText("");
edt_date.setText("");
edt_type.setText("");
edt_money.setText("");
edt_state.setText("");
}
});
//洗掉按鍵
Button btn_delete = findViewById(R.id.btn_delete);
btn_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//無選擇提示
if (selectId == -1) {
Toast.makeText(ManageActivity.this, "請選擇要洗掉的行!", Toast.LENGTH_LONG).show();
return;
}
//定義洗掉對話框
AlertDialog dialog = new AlertDialog.Builder(ManageActivity.this).setTitle("洗掉操作")
.setMessage("確定洗掉?此操作不可逆,請慎重選擇!")
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//定義洗掉的sql陳述句
String sql = "delete from " + TABLE_NAME + " where id=" + selectId;
//執行sql陳述句
sqLiteDatabase.execSQL(sql);
//重繪顯示串列
Toast.makeText(getApplicationContext(), "洗掉資料成功!", Toast.LENGTH_LONG).show();
selectData();
selectId = -1;
//清除資料
tv_test.setText("");
edt_date.setText("");
edt_type.setText("");
edt_money.setText("");
edt_state.setText("");
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).create();
dialog.show();
}
});
}
}
(7)User類
User 類是用戶類Activity,用于獲取用戶ID以及密碼,具體代碼實作如下:
package com.financial.management;
import android.os.Parcel;
import android.os.Parcelable;
public class User implements Parcelable {
private String userId="";
private String userPwd="";
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.userId);
dest.writeString(this.userPwd);
}
public User() {
}
protected User(Parcel in) {
this.userId = in.readString();
this.userPwd = in.readString();
}
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
🎵三、運行結果Result
到這里,整個系統的設計就差不多要結束啦!現在我們用一段視頻來演示整個系統的運行效果🌈
📈四、結束語
在拿到這個課題呢,周一首先對課題進行了系統結構設計,結構設計完成之后就到了編碼階段,編碼階段分為兩部分進行,先是進行靜態頁面的楷模,而后到了業務邏輯的撰寫,
講到這里,整個系統從設計階段到編碼階段的整個程序講解就結束啦!這也算是我學習Android的第一個小作品,作品不完美之處較多,后續還將會繼續改進~
本文代碼已上傳至github,戳此鏈接可下載代碼~
🐣彩蛋 One More Thing
(:不合理設計
- 年月份資料寫的太固定了,沒有可擴展性
- 日期應該用日期選擇器來做,而不應該是以文本的形式
- 收入和支出應該以單選框來進行選擇,而不應該是文本的形式
- ……
(:番外篇
- 關注公眾號星期一研究室,第一時間關注學習干貨,更多精選專欄待你解鎖~
- 如果這篇文章對你有用,記得留個腳印jio再走哦~
- 以上就是本文的全部內容!我們下期見!👋👋👋
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/289331.html
標籤:其他
上一篇:Flutter Android 工程結構及應用層編譯原始碼深入分析
下一篇:今天干了兩件大事!
