├── .gitignore ├── .idea ├── .name ├── codeStyles │ └── Project.xml ├── compiler.xml ├── encodings.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── jiangqi │ │ └── booking │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── 项目介绍.txt │ ├── java │ │ └── com │ │ │ └── jiangqi │ │ │ └── booking │ │ │ ├── AboutActivity.java │ │ │ ├── HistoryActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── ModifyPwdActivity.java │ │ │ ├── MonthChartActivity.java │ │ │ ├── RecordActivity.java │ │ │ ├── RegisterActivity.java │ │ │ ├── SearchActivity.java │ │ │ ├── SettingActivity.java │ │ │ ├── UniteApp.java │ │ │ ├── adapter │ │ │ ├── AccountAdapter.java │ │ │ ├── CalendarAdapter.java │ │ │ ├── ChartItemAdapter.java │ │ │ ├── ChartVPAdapter.java │ │ │ └── RecordPagerAdapter.java │ │ │ ├── db │ │ │ ├── DBManager.java │ │ │ └── DBOpenHelper.java │ │ │ ├── frag_chart │ │ │ ├── BaseChartFragment.java │ │ │ ├── IncomChartFragment.java │ │ │ └── OutcomChartFragment.java │ │ │ ├── frag_record │ │ │ ├── BaseRecordFragment.java │ │ │ ├── IncomeFragment.java │ │ │ ├── OutcomeFragment.java │ │ │ └── TypeBaseAdapter.java │ │ │ ├── model │ │ │ ├── AccountBean.java │ │ │ ├── BarChartItemBean.java │ │ │ ├── ChartItemBean.java │ │ │ └── TypeBean.java │ │ │ └── utils │ │ │ ├── AnalysisUtils.java │ │ │ ├── BeiZhuDialog.java │ │ │ ├── BudgetDialog.java │ │ │ ├── CalendarDialog.java │ │ │ ├── FloatUtils.java │ │ │ ├── KeyBoardUtils.java │ │ │ ├── MD5Utils.java │ │ │ ├── MoreDialog.java │ │ │ └── SelectTimeDialog.java │ └── res │ │ ├── drawable-v24 │ │ ├── a1003.png │ │ ├── back_1.png │ │ ├── back_2.png │ │ ├── go_back_selector.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── iv_right_arrow.png │ │ ├── register_button_hei.png │ │ ├── register_button_lan.png │ │ ├── register_selector.xml │ │ └── shape_wihte_frame.xml │ │ ├── drawable │ │ ├── dialog_btn_bg.xml │ │ ├── ic_launcher_background.xml │ │ ├── main_morebtn_bg.xml │ │ ├── main_recordbtn_bg.xml │ │ └── search.png │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_history.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_modify_pwd.xml │ │ ├── activity_month_chart.xml │ │ ├── activity_record.xml │ │ ├── activity_register.xml │ │ ├── activity_search.xml │ │ ├── activity_setting.xml │ │ ├── dialog_beizhu.xml │ │ ├── dialog_budget.xml │ │ ├── dialog_calendar.xml │ │ ├── dialog_more.xml │ │ ├── dialog_time.xml │ │ ├── fragment_incom_chart.xml │ │ ├── fragment_outcome.xml │ │ ├── item_chartfrag_lv.xml │ │ ├── item_chartfrag_top.xml │ │ ├── item_dialogcal_gv.xml │ │ ├── item_dialogcal_hsv.xml │ │ ├── item_mainlv.xml │ │ ├── item_mainlv_top.xml │ │ ├── item_recordfrag_gv.xml │ │ └── main_title_bar.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ ├── ic_launcher_round.xml │ │ ├── in_me.png │ │ └── in_me1.png │ │ ├── mipmap-hdpi │ │ ├── edit.png │ │ ├── ic_icon1.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ih_biaoge.png │ │ ├── ih_error.png │ │ ├── ih_hide.png │ │ ├── ih_show.png │ │ ├── it_searchtext.png │ │ └── more.png │ │ ├── mipmap-mdpi │ │ ├── ic_canyin.png │ │ ├── ic_canyin_fs.png │ │ ├── ic_fushi.png │ │ ├── ic_fushi_fs.png │ │ ├── ic_gouwu.png │ │ ├── ic_gouwu_fs.png │ │ ├── ic_jiaotong.png │ │ ├── ic_jiaotong_fs.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_lingshi.png │ │ ├── ic_lingshi_fs.png │ │ ├── ic_qita.png │ │ ├── ic_qita_fs.png │ │ ├── ic_renqingwanglai.png │ │ ├── ic_renqingwanglai_fs.png │ │ ├── ic_riyongpin.png │ │ ├── ic_riyongpin_fs.png │ │ ├── ic_shicai.png │ │ ├── ic_shicai_fs.png │ │ ├── ic_shuidianfei.png │ │ ├── ic_shuidianfei_fs.png │ │ ├── ic_tongxun.png │ │ ├── ic_tongxun_fs.png │ │ ├── ic_xuexi.png │ │ ├── ic_xuexi_fs.png │ │ ├── ic_yanjiu.png │ │ ├── ic_yanjiu_fs.png │ │ ├── ic_yiliao.png │ │ ├── ic_yiliao_fs.png │ │ ├── ic_yule.png │ │ ├── ic_yule_fs.png │ │ ├── ic_zhufang.png │ │ ├── ic_zhufang_fs.png │ │ ├── in_ershoushebei.png │ │ ├── in_ershoushebei_fs.png │ │ ├── in_jiangjin.png │ │ ├── in_jiangjin_fs.png │ │ ├── in_jieru.png │ │ ├── in_jieru_fs.png │ │ ├── in_lixifuji.png │ │ ├── in_lixifuji_fs.png │ │ ├── in_qt.png │ │ ├── in_qt_fs.png │ │ ├── in_shezhi.png │ │ ├── in_shezhi_fs.png │ │ ├── in_shouzhai.png │ │ ├── in_shouzhai_fs.png │ │ ├── in_touzi.png │ │ ├── in_touzi_fs.png │ │ ├── in_xinzi.png │ │ ├── in_xinzi_fs.png │ │ ├── in_yiwai.png │ │ ├── in_yiwai_fs.png │ │ ├── it_back.png │ │ ├── it_guanyu.png │ │ ├── it_jilu.png │ │ ├── it_rili.png │ │ ├── it_shezhi.png │ │ └── it_xiqing.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── key.xml │ └── test │ └── java │ └── com │ └── jiangqi │ └── booking │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | booking -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android-course-design 2 | 基于安卓基础知识点开发家庭记账工具,其中包括记录当天收支情况,计算当天以及当月共收支总钱数,能查看历史账单,能对于每月收支情况进行图标分析,百分比分析, 能够搜索用户关于某种记录的全部收支情况等功能。基本上能够解决个人记账的所有问题,界面简约美观,滑动流畅。 3 | 4 | # 运行界面 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | defaultConfig { 7 | applicationId "com.jiangqi.booking" 8 | minSdkVersion 21 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation 'androidx.appcompat:appcompat:1.2.0' 25 | implementation 'androidx.constraintlayout:constraintlayout:2.0.2' 26 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 27 | testImplementation 'junit:junit:4.12' 28 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 29 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 30 | implementation 'com.google.android.material:material:1.2.0' 31 | implementation 'com.github.PhilJay:MPAndroidChart:v3.0.2' 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/jiangqi/booking/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.hui.booking", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/assets/项目介绍.txt: -------------------------------------------------------------------------------- 1 | 项目名称: 家庭简约记账 2 | 开发工具:Android Studio 3 | 项目描述:基于安卓基础知识点开发的个人记账工具,其中包括记录当天收支情况,计算当天以及当月共收支总钱数,能查看历史账单,能对于每月收支情况进行图标分析,百分比分析, 4 | 能够搜索用户关于某种记录的全部收支情况等功能。基本上能够解决个人记账的所有问题,界面简约美观,滑动流畅。 5 | 项目重要技术点: 6 | 1-绘制布局,掌握android基本view控件的属性和使用 7 | 2-熟练掌握Activity页面展示,跳转和传值 8 | 3-使用碎片加载界面,滑动视图切换页面 9 | 4-自定义对话框 10 | 5-自定义软键盘绘制和使用 11 | 6-列表视图以及网格视图的适配器使用和页面加载 12 | 7-使用Android自带数据库,熟练创建表,并进行增删改查 13 | 8-定义drawable文件,设定布局以及控件样式 14 | 9-使用MPAndroidChart第三方框架绘制柱状图 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.SharedPreferences; 7 | import android.content.pm.ActivityInfo; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | import android.view.View; 11 | import android.widget.ImageView; 12 | import android.widget.RelativeLayout; 13 | import android.widget.TextView; 14 | import android.widget.Toast; 15 | 16 | import com.jiangqi.booking.utils.AnalysisUtils; 17 | 18 | 19 | public class AboutActivity extends Activity { 20 | private TextView et_user_name;//标题 21 | private ImageView tv_back; 22 | private RelativeLayout rl_modify_psw,rl_exit_login; 23 | public static AboutActivity instance=null; 24 | private String username; 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_about); 29 | Context context=getApplicationContext(); 30 | username= AnalysisUtils.readLoginUserName(context); 31 | //设置此界面为竖屏 32 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 33 | instance = this; 34 | init(); 35 | } 36 | 37 | // 获取界面控件 38 | private void init() { 39 | // TODO Auto-generated method stub 40 | et_user_name = findViewById(R.id.et_user_name); 41 | et_user_name.setText(username); 42 | tv_back= findViewById(R.id.tv_back); 43 | rl_modify_psw=findViewById(R.id.rl_modify_pwd); 44 | rl_exit_login=findViewById(R.id.rl_exit_login); 45 | tv_back.setOnClickListener(new View.OnClickListener() { 46 | @Override 47 | public void onClick(View v) { 48 | AboutActivity.this.finish(); 49 | } 50 | }); 51 | 52 | //修改密码的点击事件 53 | rl_modify_psw.setOnClickListener(new View.OnClickListener() { 54 | @Override 55 | public void onClick(View v) { 56 | //跳转到修改密码的界面 57 | Intent intent=new Intent(AboutActivity.this, ModifyPwdActivity.class); 58 | startActivity(intent); 59 | 60 | } 61 | }); 62 | 63 | //退出登录的点击事件 64 | rl_exit_login.setOnClickListener(new View.OnClickListener() { 65 | @Override 66 | public void onClick(View v) { 67 | Toast.makeText(AboutActivity.this,"退出登录成功",Toast.LENGTH_SHORT).show(); 68 | clearLoginStatus();//清除登录状态和登录时的用户名 69 | //退出登录成功后把退出成功状态传递到MainActivity中 70 | Intent data = new Intent(); 71 | data.putExtra("isLogin",false); 72 | setResult(RESULT_OK,data); 73 | AboutActivity.this.finish(); 74 | Intent intent=new Intent(AboutActivity.this, LoginActivity.class); 75 | startActivity(intent); 76 | } 77 | 78 | }); 79 | } 80 | 81 | // 清除SharePrederences中的登录状态和登录时的登录名 82 | private void clearLoginStatus() { 83 | // TODO Auto-generated method stub 84 | SharedPreferences sp = getSharedPreferences("loginInfo",Context.MODE_PRIVATE); 85 | SharedPreferences.Editor editor =sp.edit(); //获取编辑器 86 | editor.putBoolean("isLogin",false); //清除登录状态 87 | editor.putString("loginUserName",""); //清除用户名 88 | editor.commit(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/HistoryActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.app.AlertDialog; 6 | import android.content.Context; 7 | import android.content.DialogInterface; 8 | import android.os.Bundle; 9 | import android.view.View; 10 | import android.widget.AdapterView; 11 | import android.widget.ListView; 12 | import android.widget.TextView; 13 | 14 | import com.jiangqi.booking.model.AccountBean; 15 | 16 | import com.jiangqi.booking.adapter.AccountAdapter; 17 | import com.jiangqi.booking.db.DBManager; 18 | import com.jiangqi.booking.utils.CalendarDialog; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Calendar; 22 | import java.util.List; 23 | 24 | public class HistoryActivity extends AppCompatActivity { 25 | ListView historyLv; 26 | TextView timeTv; 27 | 28 | ListmDatas; 29 | AccountAdapter adapter; 30 | int year,month; 31 | int dialogSelPos = -1; 32 | int dialogSelMonth = -1; 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_history); 37 | historyLv = findViewById(R.id.history_lv); 38 | timeTv = findViewById(R.id.history_tv_time); 39 | mDatas = new ArrayList<>(); 40 | // 设置适配器 41 | adapter = new AccountAdapter(this,mDatas); 42 | historyLv.setAdapter(adapter); 43 | initTime(); 44 | timeTv.setText(year+"年"+month+"月"); 45 | loadData(year,month); 46 | setLVClickListener(); 47 | } 48 | /*设置ListView每一个item的长按事件*/ 49 | private void setLVClickListener() { 50 | historyLv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 51 | @Override 52 | public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { 53 | AccountBean accountBean = mDatas.get(position); 54 | deleteItem(accountBean); 55 | return false; 56 | } 57 | }); 58 | } 59 | 60 | private void deleteItem(final AccountBean accountBean) { 61 | final int delId = accountBean.getId(); 62 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 63 | builder.setTitle("提示信息").setMessage("您确定要删除这条记录么?") 64 | .setNegativeButton("取消",null) 65 | .setPositiveButton("确定", new DialogInterface.OnClickListener() { 66 | @Override 67 | public void onClick(DialogInterface dialog, int which) { 68 | Context context=getApplicationContext(); 69 | DBManager.deleteItemFromAccounttbById(delId); 70 | mDatas.remove(accountBean); //实时刷新,从数据源删除 71 | adapter.notifyDataSetChanged(); 72 | } 73 | }); 74 | builder.create().show(); 75 | } 76 | 77 | /* 获取指定年份月份收支情况的列表*/ 78 | private void loadData(int year,int month) { 79 | List list = DBManager.getAccountListOneMonthFromAccounttb(year, month,LoginActivity.getmUsername()); 80 | mDatas.clear(); 81 | mDatas.addAll(list); 82 | adapter.notifyDataSetChanged(); 83 | } 84 | 85 | private void initTime() { 86 | Calendar calendar = Calendar.getInstance(); 87 | year = calendar.get(Calendar.YEAR); 88 | month = calendar.get(Calendar.MONTH)+1; 89 | } 90 | 91 | public void onClick(View view) { 92 | switch (view.getId()) { 93 | case R.id.history_iv_back: 94 | finish(); 95 | break; 96 | case R.id.history_iv_rili: 97 | CalendarDialog dialog = new CalendarDialog(this,dialogSelPos,dialogSelMonth); 98 | dialog.show(); 99 | dialog.setDialogSize(); 100 | dialog.setOnRefreshListener(new CalendarDialog.OnRefreshListener() { 101 | @Override 102 | public void onRefresh(int selPos, int year, int month) { 103 | timeTv.setText(year+"年"+month+"月"); 104 | loadData(year,month); 105 | dialogSelPos = selPos; 106 | dialogSelMonth = month; 107 | } 108 | }); 109 | break; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/ModifyPwdActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.content.pm.ActivityInfo; 7 | import android.graphics.Color; 8 | import android.os.Bundle; 9 | import android.text.TextUtils; 10 | import android.view.View; 11 | import android.widget.Button; 12 | import android.widget.EditText; 13 | import android.widget.RelativeLayout; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.jiangqi.booking.utils.AnalysisUtils; 18 | import com.jiangqi.booking.utils.MD5Utils; 19 | 20 | 21 | public class ModifyPwdActivity extends Activity { 22 | 23 | private TextView tv_main_title,tv_back; 24 | private EditText et_original_psw,et_new_psw,et_new_psw_again; 25 | private Button btn_save; 26 | private String originalPsw,newPsw,newPswAgain,userName; 27 | private RelativeLayout rl_title_bar;//标题布局 28 | 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_modify_pwd); 34 | //设置此界面为竖屏 35 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 36 | init(); 37 | userName= AnalysisUtils.readLoginUserName(this); 38 | } 39 | 40 | //获取界面控件并处理相关控件的点击事件 41 | private void init() { 42 | // TODO Auto-generated method stub 43 | tv_main_title=findViewById(R.id.tv_main_title); 44 | tv_main_title.setText("修改密码"); 45 | tv_main_title.setBackgroundColor(Color.parseColor("#78A4FA")); 46 | tv_back=findViewById(R.id.tv_back); 47 | et_original_psw= findViewById(R.id.et_originnal_pwd); 48 | et_new_psw= findViewById(R.id.et_new_pwd); 49 | et_new_psw_again= findViewById(R.id.et_new_pwd_again); 50 | btn_save= findViewById(R.id.btn_save); 51 | tv_back.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | ModifyPwdActivity.this.finish(); 55 | } 56 | }); 57 | //保存按钮的点击事件 58 | btn_save.setOnClickListener(new View.OnClickListener() { 59 | @Override 60 | public void onClick(View v) { 61 | getEditString(); 62 | if (TextUtils.isEmpty(originalPsw)) { 63 | Toast.makeText(ModifyPwdActivity.this, "请输入原始密码", Toast.LENGTH_SHORT).show(); 64 | return; 65 | //当点击“保存”按钮时需要验证保存密码是否正确 66 | } else if (!MD5Utils.MD5(originalPsw).equals(readPsw())) { 67 | Toast.makeText(ModifyPwdActivity.this, "输入的密码与原始密码不一致", Toast.LENGTH_SHORT).show(); 68 | return; 69 | } else if(MD5Utils.MD5(newPsw).equals(readPsw())){ 70 | Toast.makeText(ModifyPwdActivity.this, "输入的新密码与原始密码不能一致", Toast.LENGTH_SHORT).show(); 71 | return; 72 | } else if (TextUtils.isEmpty(newPsw)) { 73 | Toast.makeText(ModifyPwdActivity.this, "请输入新密码", Toast.LENGTH_SHORT).show(); 74 | return; 75 | } else if (TextUtils.isEmpty(newPswAgain)) { 76 | Toast.makeText(ModifyPwdActivity.this, "请再次输入新密码", Toast.LENGTH_SHORT).show(); 77 | return; 78 | //验证新输入的密码是否相同 79 | } else if (!newPsw.equals(newPswAgain)) { 80 | Toast.makeText(ModifyPwdActivity.this, "两次输入的新密码不一致", Toast.LENGTH_SHORT).show(); 81 | return; 82 | } else { 83 | Toast.makeText(ModifyPwdActivity.this, "新密码设置成功", Toast.LENGTH_SHORT).show(); 84 | //修改登录成功时保存在SharedPreferences中的密码 85 | modifyPsw(newPsw); 86 | Intent intent = new Intent(ModifyPwdActivity.this, LoginActivity.class); 87 | startActivity(intent); 88 | AboutActivity.instance.finish(); 89 | ModifyPwdActivity.this.finish(); 90 | } 91 | } 92 | }); 93 | } 94 | 95 | //获取控件上的字符串 96 | private void getEditString() { 97 | // TODO Auto-generated method stub 98 | originalPsw=et_original_psw.getText().toString().trim(); 99 | newPsw=et_new_psw.getText().toString().trim(); 100 | newPswAgain=et_new_psw_again.getText().toString().trim(); 101 | } 102 | 103 | //将SharedPreferences中的密码修改为密码 104 | private void modifyPsw(String newPsw) { 105 | // TODO Auto-generated method stub 106 | String md5Psw= MD5Utils.MD5(newPsw);//把密码用MD5加密 107 | SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE); 108 | SharedPreferences.Editor editor=sp.edit();//获取编辑器 109 | editor.putString(userName, md5Psw);//保存新密码 110 | editor.commit();//提交修改 111 | } 112 | 113 | //从SharedPreferences中读取原始密码 114 | private Object readPsw() { 115 | // TODO Auto-generated method stub 116 | SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE); 117 | String spPsw=sp.getString(userName, ""); 118 | return spPsw; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/MonthChartActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import androidx.fragment.app.Fragment; 5 | import androidx.viewpager.widget.ViewPager; 6 | 7 | import android.content.Context; 8 | import android.graphics.Color; 9 | import android.os.Bundle; 10 | import android.view.View; 11 | import android.widget.Button; 12 | import android.widget.TextView; 13 | 14 | import com.jiangqi.booking.adapter.ChartVPAdapter; 15 | import com.jiangqi.booking.db.DBManager; 16 | import com.jiangqi.booking.frag_chart.IncomChartFragment; 17 | import com.jiangqi.booking.frag_chart.OutcomChartFragment; 18 | import com.jiangqi.booking.utils.AnalysisUtils; 19 | import com.jiangqi.booking.utils.CalendarDialog; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Calendar; 23 | import java.util.List; 24 | 25 | public class MonthChartActivity extends AppCompatActivity { 26 | Button inBtn,outBtn; 27 | TextView dateTv,inTv,outTv; 28 | ViewPager chartVp; 29 | int year; 30 | int month; 31 | int selectPos = -1,selectMonth =-1; 32 | ListchartFragList; 33 | private IncomChartFragment incomChartFragment; 34 | private OutcomChartFragment outcomChartFragment; 35 | private ChartVPAdapter chartVPAdapter; 36 | String username; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_month_chart); 42 | initView(); 43 | initTime(); 44 | initStatistics(year,month); 45 | initFrag(); 46 | setVPSelectListener(); 47 | Context context=getApplicationContext(); 48 | username= AnalysisUtils.readLoginUserName(context); 49 | } 50 | 51 | private void setVPSelectListener() { 52 | chartVp.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){ 53 | @Override 54 | public void onPageSelected(int position) { 55 | setButtonStyle(position); 56 | } 57 | }); 58 | } 59 | 60 | private void initFrag() { 61 | chartFragList = new ArrayList<>(); 62 | // 添加Fragment的对象 63 | incomChartFragment = new IncomChartFragment(); 64 | outcomChartFragment = new OutcomChartFragment(); 65 | // 添加数据到Fragment当中 66 | Bundle bundle = new Bundle(); 67 | bundle.putInt("year",year); 68 | bundle.putInt("month",month); 69 | incomChartFragment.setArguments(bundle); 70 | outcomChartFragment.setArguments(bundle); 71 | // 将Fragment添加到数据源当中 72 | chartFragList.add(outcomChartFragment); 73 | chartFragList.add(incomChartFragment); 74 | // 使用适配器 75 | chartVPAdapter = new ChartVPAdapter(getSupportFragmentManager(), chartFragList); 76 | chartVp.setAdapter(chartVPAdapter); 77 | // 将Fragment加载到Acitivy当中 78 | } 79 | 80 | /* 统计某年某月的收支情况数据*/ 81 | private void initStatistics(int year, int month) { 82 | float inMoneyOneMonth = DBManager.getSumMoneyOneMonth(year, month, 1,username); //收入总钱数 83 | float outMoneyOneMonth = DBManager.getSumMoneyOneMonth(year, month, 0,username); //支出总钱数 84 | int incountItemOneMonth = DBManager.getCountItemOneMonth(year, month, 1,username); //收入多少笔 85 | int outcountItemOneMonth = DBManager.getCountItemOneMonth(year, month, 0,username); //支出多少笔 86 | dateTv.setText(year+"年"+month+"月账单"); 87 | inTv.setText("共"+incountItemOneMonth+"笔收入, ¥ "+inMoneyOneMonth); 88 | outTv.setText("共"+outcountItemOneMonth+"笔支出, ¥ "+outMoneyOneMonth); 89 | 90 | } 91 | 92 | /** 初始化时间的方法*/ 93 | private void initTime() { 94 | Calendar calendar = Calendar.getInstance(); 95 | year = calendar.get(Calendar.YEAR); 96 | month = calendar.get(Calendar.MONTH)+1; 97 | } 98 | 99 | /** 初始化控件*/ 100 | private void initView() { 101 | inBtn = findViewById(R.id.chart_btn_in); 102 | outBtn = findViewById(R.id.chart_btn_out); 103 | dateTv = findViewById(R.id.chart_tv_date); 104 | inTv = findViewById(R.id.chart_tv_in); 105 | outTv = findViewById(R.id.chart_tv_out); 106 | chartVp = findViewById(R.id.chart_vp); 107 | } 108 | 109 | public void onClick(View view) { 110 | switch (view.getId()) { 111 | case R.id.chart_iv_back: 112 | finish(); 113 | break; 114 | case R.id.chart_iv_rili: 115 | showCalendarDialog(); 116 | break; 117 | case R.id.chart_btn_in: 118 | setButtonStyle(1); 119 | chartVp.setCurrentItem(1); 120 | break; 121 | case R.id.chart_btn_out: 122 | setButtonStyle(0); 123 | chartVp.setCurrentItem(0); 124 | break; 125 | } 126 | } 127 | /* 显示日历对话框*/ 128 | private void showCalendarDialog() { 129 | CalendarDialog dialog = new CalendarDialog(this, selectPos, selectMonth); 130 | dialog.show(); 131 | dialog.setDialogSize(); 132 | dialog.setOnRefreshListener(new CalendarDialog.OnRefreshListener() { 133 | @Override 134 | public void onRefresh(int selPos, int year, int month) { 135 | MonthChartActivity.this.selectPos = selPos; 136 | MonthChartActivity.this.selectMonth = month; 137 | initStatistics(year,month); 138 | incomChartFragment.setDate(year,month); 139 | outcomChartFragment.setDate(year,month); 140 | } 141 | }); 142 | } 143 | 144 | /* 设置按钮样式的改变 支出-0 收入-1*/ 145 | private void setButtonStyle(int kind){ 146 | if (kind == 0) { 147 | outBtn.setBackgroundResource(R.drawable.main_recordbtn_bg); 148 | outBtn.setTextColor(Color.WHITE); 149 | inBtn.setBackgroundResource(R.drawable.dialog_btn_bg); 150 | inBtn.setTextColor(Color.BLACK); 151 | }else if (kind == 1){ 152 | inBtn.setBackgroundResource(R.drawable.main_recordbtn_bg); 153 | inBtn.setTextColor(Color.WHITE); 154 | outBtn.setBackgroundResource(R.drawable.dialog_btn_bg); 155 | outBtn.setTextColor(Color.BLACK); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/RecordActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import androidx.fragment.app.Fragment; 5 | import androidx.viewpager.widget.ViewPager; 6 | 7 | import android.os.Bundle; 8 | import android.view.View; 9 | 10 | import com.google.android.material.tabs.TabLayout; 11 | import com.jiangqi.booking.R; 12 | import com.jiangqi.booking.adapter.RecordPagerAdapter; 13 | import com.jiangqi.booking.frag_record.IncomeFragment; 14 | import com.jiangqi.booking.frag_record.OutcomeFragment; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | public class RecordActivity extends AppCompatActivity { 20 | TabLayout tabLayout; 21 | ViewPager viewPager; 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_record); 26 | //1.查找控件 27 | tabLayout = findViewById(R.id.record_tabs); 28 | viewPager = findViewById(R.id.record_vp); 29 | //2.设置ViewPager加载页面 30 | initPager(); 31 | } 32 | 33 | private void initPager() { 34 | // 初始化ViewPager页面的集合 35 | ListfragmentList = new ArrayList<>(); 36 | // 创建收入和支出页面,放置在Fragment当中 37 | OutcomeFragment outFrag = new OutcomeFragment(); //支出 38 | IncomeFragment inFrag = new IncomeFragment(); //收入 39 | fragmentList.add(outFrag); 40 | fragmentList.add(inFrag); 41 | 42 | // 创建适配器 43 | RecordPagerAdapter pagerAdapter = new RecordPagerAdapter(getSupportFragmentManager(), fragmentList); 44 | // 设置适配器 45 | viewPager.setAdapter(pagerAdapter); 46 | //将TabLayout和ViwePager进行关联 47 | tabLayout.setupWithViewPager(viewPager); 48 | } 49 | 50 | /* 点击事件*/ 51 | public void onClick(View view) { 52 | switch (view.getId()) { 53 | case R.id.record_iv_back: 54 | finish(); 55 | break; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/RegisterActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Intent; 6 | import android.content.SharedPreferences; 7 | import android.graphics.Color; 8 | import android.os.Bundle; 9 | import android.text.TextUtils; 10 | import android.view.View; 11 | import android.widget.Button; 12 | import android.widget.EditText; 13 | import android.widget.RelativeLayout; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import com.jiangqi.booking.utils.MD5Utils; 18 | 19 | public class RegisterActivity extends AppCompatActivity { 20 | private TextView tv_main_title;//标题 21 | private TextView tv_back; //返回按钮 22 | private RelativeLayout rl_title_bar;//标题布局 23 | private Button btn_register; //注册按钮 24 | private EditText et_user_name, et_pwd, et_pwd_again;//用户名、密码、再次输入的密码的控件 25 | private String username, pwd, pwd_again;//用户名、密码、再次输入的密码的控件的获取值 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | // TODO Auto-generated method stub 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_register); 32 | init(); 33 | } 34 | 35 | private void init() { 36 | // TODO Auto-generated method stub 37 | //从main_title_bar.xml页面布局中获取对应的UI控件 38 | //抽取成员变量ctrl+alt+F 39 | tv_main_title = findViewById(R.id.tv_main_title); 40 | tv_main_title.setText("注册"); 41 | tv_back = findViewById(R.id.tv_back); 42 | rl_title_bar = findViewById(R.id.title_bar); 43 | rl_title_bar.setBackgroundColor(Color.TRANSPARENT); 44 | 45 | //从activity_register.xml页面布局中获取对应的UI控件 46 | btn_register = findViewById(R.id.btn_register); 47 | et_user_name = findViewById(R.id.et_user_name); 48 | et_pwd = findViewById(R.id.et_pwd); 49 | et_pwd_again = findViewById(R.id.et_pwd_again); 50 | tv_back.setOnClickListener(new View.OnClickListener() { 51 | @Override//关闭页面的点击事件 52 | public void onClick(View view) {//设置按钮可以关闭当前页面 53 | RegisterActivity.this.finish(); 54 | } 55 | }); 56 | //注册按钮点击事件 57 | btn_register.setOnClickListener(new View.OnClickListener() { 58 | @Override 59 | public void onClick(View view) { 60 | //点击后获取输入在响应控件中的字符串 61 | getEditstring(); 62 | //判断字符串是否为空 63 | if (TextUtils.isEmpty(username)) { 64 | Toast.makeText(RegisterActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show(); 65 | return; 66 | } else if (TextUtils.isEmpty(pwd)) { 67 | Toast.makeText(RegisterActivity.this, "请输入密码", Toast.LENGTH_SHORT).show(); 68 | return; 69 | } else if (TextUtils.isEmpty(pwd_again)) { 70 | Toast.makeText(RegisterActivity.this, "请再次输入密码", Toast.LENGTH_SHORT).show(); 71 | return; 72 | } else if (!pwd.equals(pwd_again)) { 73 | Toast.makeText(RegisterActivity.this, "两次输入的密码不一样", Toast.LENGTH_SHORT).show(); 74 | return; 75 | } else if (isExistUserName(username)) { 76 | Toast.makeText(RegisterActivity.this, "此用户已经存在", Toast.LENGTH_SHORT).show(); 77 | return; 78 | } else { 79 | Toast.makeText(RegisterActivity.this, "注册成功", Toast.LENGTH_SHORT).show(); 80 | //把用户名和密码保存到SharedPreferences里面 81 | saveRegisterInfo(username, pwd); 82 | //注册成功后通过Intent把用户名传递到LoginActivity.java中 83 | Intent data = new Intent(); 84 | data.putExtra("username", username); 85 | setResult(RESULT_OK, data);//setResult为OK,关闭当前页面 86 | RegisterActivity.this.finish();//在登录的时候,如果用户还没有注册则注册。注册成功后把注册成功后的用户名返回给前一个页面 87 | } 88 | } 89 | }); 90 | } 91 | 92 | private void saveRegisterInfo(String username, String pwd) { 93 | String md5Pwd = MD5Utils.MD5(pwd);//把密码用MD5加密 94 | //loginInfo是sp的文件名 95 | SharedPreferences sp = getSharedPreferences("loginInfo", MODE_PRIVATE);//通过getSharedPreferences传入loginInfo注册登录相关的信息 96 | SharedPreferences.Editor editor = sp.edit();//通过sp.edit()获取到sp的编辑器对象 97 | //username作为key,密码作为value 98 | editor.putString(username, md5Pwd); 99 | editor.commit();//提交修改 100 | } 101 | 102 | /** 103 | * 从SharedPreferences中读取输入的用户名,判断SharedPreferences中是否有用户名 104 | */ 105 | private boolean isExistUserName(String username) { 106 | boolean has_userName = false;//表示是否有用户名 107 | SharedPreferences sp = getSharedPreferences("loginInfo", MODE_PRIVATE); 108 | String spPwd = sp.getString(username, ""); //通过sp.getString传值用户名获取到密码 109 | if (!TextUtils.isEmpty(spPwd)) { //判断这个密码是否为空 110 | has_userName = true;//该用户是否保存了这一个密码 111 | } 112 | return has_userName; 113 | } 114 | 115 | /** 116 | * 获取控件中的字符串 117 | */ 118 | private void getEditstring() { 119 | username = et_user_name.getText().toString().trim(); 120 | pwd = et_pwd.getText().toString(); 121 | pwd_again = et_pwd_again.getText().toString().trim(); 122 | } 123 | } 124 | 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/SearchActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Context; 6 | import android.os.Bundle; 7 | import android.text.TextUtils; 8 | import android.view.View; 9 | import android.widget.EditText; 10 | import android.widget.ListView; 11 | import android.widget.TextView; 12 | import android.widget.Toast; 13 | 14 | import com.jiangqi.booking.model.AccountBean; 15 | import com.jiangqi.booking.adapter.AccountAdapter; 16 | import com.jiangqi.booking.db.DBManager; 17 | import com.jiangqi.booking.utils.AnalysisUtils; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class SearchActivity extends AppCompatActivity { 23 | ListView searchLv; 24 | EditText searchEt; 25 | TextView emptyTv; 26 | ListmDatas; //数据源 27 | AccountAdapter adapter; //适配器对象 28 | String username; 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_search); 33 | initView(); 34 | mDatas = new ArrayList<>(); 35 | adapter = new AccountAdapter(this,mDatas); 36 | searchLv.setAdapter(adapter); 37 | searchLv.setEmptyView(emptyTv); //设置无数局时,显示的控件 38 | Context context=getApplicationContext(); 39 | username= AnalysisUtils.readLoginUserName(context); 40 | } 41 | 42 | private void initView() { 43 | searchEt = findViewById(R.id.search_et); 44 | searchLv = findViewById(R.id.search_lv); 45 | emptyTv = findViewById(R.id.search_tv_empty); 46 | } 47 | 48 | public void onClick(View view) { 49 | switch (view.getId()) { 50 | case R.id.search_iv_back: 51 | finish(); 52 | break; 53 | case R.id.search_iv_sh: //执行搜索的操作 54 | String msg = searchEt.getText().toString().trim(); 55 | // 判断输入内容是否为空,如果为空,就提示不能搜索 56 | if (TextUtils.isEmpty(msg)) { 57 | Toast.makeText(this,"输入内容不能为空!",Toast.LENGTH_SHORT).show(); 58 | return; 59 | } 60 | //开始搜索 61 | List list = DBManager.getAccountListByRemarkFromAccounttb(msg,username); 62 | mDatas.clear(); 63 | mDatas.addAll(list); 64 | adapter.notifyDataSetChanged(); 65 | break; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/SettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.app.AlertDialog; 6 | import android.content.Context; 7 | import android.content.DialogInterface; 8 | import android.content.Intent; 9 | import android.os.Bundle; 10 | import android.view.View; 11 | import android.widget.Toast; 12 | 13 | import com.jiangqi.booking.db.DBManager; 14 | import com.jiangqi.booking.utils.AnalysisUtils; 15 | 16 | public class SettingActivity extends AppCompatActivity { 17 | String username; 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_setting); 22 | Context context=getApplicationContext(); 23 | username = AnalysisUtils.readLoginUserName(context); 24 | } 25 | 26 | public void onClick(View view) { 27 | switch (view.getId()) { 28 | case R.id.setting_iv_back: 29 | finish(); 30 | break; 31 | case R.id.setting_tv_clear: 32 | showDeleteDialog(); 33 | break; 34 | } 35 | } 36 | 37 | private void showDeleteDialog() { 38 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 39 | builder.setTitle("删除提示") 40 | .setMessage("您确定要删除所有记录么?\n注意:删除后无法恢复,请慎重选择!") 41 | .setPositiveButton("取消",null) 42 | .setNegativeButton("确定", new DialogInterface.OnClickListener() { 43 | @Override 44 | public void onClick(DialogInterface dialog, int which) { 45 | DBManager.deleteAllAccount(username); 46 | Toast.makeText(SettingActivity.this,"删除成功!",Toast.LENGTH_SHORT).show(); 47 | } 48 | }); 49 | builder.create().show(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/UniteApp.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking; 2 | 3 | import android.app.Application; 4 | 5 | import com.jiangqi.booking.db.DBManager; 6 | 7 | /* 表示全局应用的类*/ 8 | public class UniteApp extends Application { 9 | @Override 10 | public void onCreate() { 11 | super.onCreate(); 12 | // 初始化数据库 13 | DBManager.initDB(getApplicationContext()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/adapter/AccountAdapter.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.jiangqi.booking.model.AccountBean; 12 | import com.jiangqi.booking.R; 13 | 14 | import java.util.Calendar; 15 | import java.util.List; 16 | 17 | public class AccountAdapter extends BaseAdapter { 18 | Context context; 19 | List mDatas; 20 | LayoutInflater inflater; 21 | int year,month,day; 22 | public AccountAdapter(Context context, List mDatas) { 23 | this.context = context; 24 | this.mDatas = mDatas; 25 | inflater = LayoutInflater.from(context); 26 | Calendar calendar = Calendar.getInstance(); 27 | year = calendar.get(Calendar.YEAR); 28 | month = calendar.get(Calendar.MONTH)+1; 29 | day = calendar.get(Calendar.DAY_OF_MONTH); 30 | } 31 | 32 | @Override 33 | public int getCount() { 34 | return mDatas.size(); 35 | } 36 | 37 | @Override 38 | public Object getItem(int position) { 39 | return mDatas.get(position); 40 | } 41 | 42 | @Override 43 | public long getItemId(int position) { 44 | return position; 45 | } 46 | 47 | @Override 48 | public View getView(int position, View convertView, ViewGroup parent) { 49 | ViewHolder holder = null; 50 | if (convertView == null) { 51 | convertView = inflater.inflate(R.layout.item_mainlv,parent,false); 52 | holder = new ViewHolder(convertView); 53 | convertView.setTag(holder); 54 | }else{ 55 | holder = (ViewHolder) convertView.getTag(); 56 | } 57 | AccountBean bean = mDatas.get(position); 58 | holder.typeIv.setImageResource(bean.getsImageId()); 59 | holder.typeTv.setText(bean.getTypename()); 60 | holder.beizhuTv.setText(bean.getBeizhu()); 61 | holder.moneyTv.setText("¥ "+bean.getMoney()); 62 | if (bean.getYear()==year&&bean.getMonth()==month&&bean.getDay()==day) { 63 | String time = bean.getTime().split(" ")[1]; 64 | holder.timeTv.setText("今天 "+time); 65 | }else { 66 | holder.timeTv.setText(bean.getTime()); 67 | } 68 | return convertView; 69 | } 70 | 71 | class ViewHolder{ 72 | ImageView typeIv; 73 | TextView typeTv,beizhuTv,timeTv,moneyTv; 74 | public ViewHolder(View view){ 75 | typeIv = view.findViewById(R.id.item_mainlv_iv); 76 | typeTv = view.findViewById(R.id.item_mainlv_tv_title); 77 | timeTv = view.findViewById(R.id.item_mainlv_tv_time); 78 | beizhuTv = view.findViewById(R.id.item_mainlv_tv_beizhu); 79 | moneyTv = view.findViewById(R.id.item_mainlv_tv_money); 80 | 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/adapter/CalendarAdapter.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.adapter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.BaseAdapter; 9 | import android.widget.TextView; 10 | 11 | import com.jiangqi.booking.R; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /* 17 | * 历史账单界面,点击日历表,弹出对话框,当中的GridView对应的适配器 18 | * */ 19 | public class CalendarAdapter extends BaseAdapter { 20 | Context context; 21 | ListmDatas; 22 | public int year; 23 | public int selPos = -1; 24 | 25 | public void setYear(int year) { 26 | this.year = year; 27 | mDatas.clear(); 28 | loadDatas(year); 29 | notifyDataSetChanged(); 30 | } 31 | 32 | public CalendarAdapter(Context context, int year) { 33 | this.context = context; 34 | this.year = year; 35 | mDatas = new ArrayList<>(); 36 | loadDatas(year); 37 | } 38 | 39 | private void loadDatas(int year) { 40 | for (int i = 1; i < 13; i++) { 41 | String data = year+"/"+i; 42 | mDatas.add(data); 43 | } 44 | } 45 | 46 | @Override 47 | public int getCount() { 48 | return mDatas.size(); 49 | } 50 | 51 | @Override 52 | public Object getItem(int position) { 53 | return mDatas.get(position); 54 | } 55 | 56 | @Override 57 | public long getItemId(int position) { 58 | return position; 59 | } 60 | 61 | @Override 62 | public View getView(int position, View convertView, ViewGroup parent) { 63 | convertView = LayoutInflater.from(context).inflate(R.layout.item_dialogcal_gv,parent,false); 64 | TextView tv = convertView.findViewById(R.id.item_dialogcal_gv_tv); 65 | tv.setText(mDatas.get(position)); 66 | tv.setBackgroundResource(R.color.grey_f3f3f3); 67 | tv.setTextColor(Color.BLACK); 68 | if (position == selPos) { 69 | tv.setBackgroundResource(R.color.green_006400); 70 | tv.setTextColor(Color.WHITE); 71 | } 72 | return convertView; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/adapter/ChartItemAdapter.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.jiangqi.booking.R; 12 | import com.jiangqi.booking.model.ChartItemBean; 13 | import com.jiangqi.booking.utils.FloatUtils; 14 | 15 | import java.util.List; 16 | 17 | /* 18 | * 账单详情页面,listview的适配器 19 | * */ 20 | public class ChartItemAdapter extends BaseAdapter { 21 | Context context; 22 | List mDatas; 23 | LayoutInflater inflater; 24 | 25 | public ChartItemAdapter(Context context, List mDatas) { 26 | this.context = context; 27 | this.mDatas = mDatas; 28 | inflater = LayoutInflater.from(context); 29 | } 30 | 31 | @Override 32 | public int getCount() { 33 | return mDatas.size(); 34 | } 35 | 36 | @Override 37 | public Object getItem(int position) { 38 | return mDatas.get(position); 39 | } 40 | 41 | @Override 42 | public long getItemId(int position) { 43 | return position; 44 | } 45 | 46 | @Override 47 | public View getView(int position, View convertView, ViewGroup parent) { 48 | ViewHolder holder = null; 49 | if (convertView == null) { 50 | convertView = inflater.inflate(R.layout.item_chartfrag_lv,parent,false); 51 | holder = new ViewHolder(convertView); 52 | convertView.setTag(holder); 53 | }else{ 54 | holder = (ViewHolder) convertView.getTag(); 55 | } 56 | // 获取显示内容 57 | ChartItemBean bean = mDatas.get(position); 58 | holder.iv.setImageResource(bean.getsImageId()); 59 | holder.typeTv.setText(bean.getType()); 60 | float ratio = bean.getRatio(); 61 | String pert = FloatUtils.ratioToPercent(ratio); 62 | holder.ratioTv.setText(pert); 63 | 64 | holder.totalTv.setText("¥ "+bean.getTotalMoney()); 65 | return convertView; 66 | } 67 | 68 | class ViewHolder{ 69 | TextView typeTv,ratioTv,totalTv; 70 | ImageView iv; 71 | public ViewHolder(View view){ 72 | typeTv = view.findViewById(R.id.item_chartfrag_tv_type); 73 | ratioTv = view.findViewById(R.id.item_chartfrag_tv_pert); 74 | totalTv = view.findViewById(R.id.item_chartfrag_tv_sum); 75 | iv = view.findViewById(R.id.item_chartfrag_iv); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/adapter/ChartVPAdapter.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.adapter; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.fragment.app.Fragment; 5 | import androidx.fragment.app.FragmentManager; 6 | import androidx.fragment.app.FragmentPagerAdapter; 7 | 8 | import java.util.List; 9 | 10 | public class ChartVPAdapter extends FragmentPagerAdapter { 11 | ListfragmentList; 12 | public ChartVPAdapter(@NonNull FragmentManager fm, ListfragmentList) { 13 | super(fm); 14 | this.fragmentList = fragmentList; 15 | } 16 | 17 | @NonNull 18 | @Override 19 | public Fragment getItem(int position) { 20 | return fragmentList.get(position); 21 | } 22 | 23 | @Override 24 | public int getCount() { 25 | return fragmentList.size(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/adapter/RecordPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.adapter; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | import androidx.fragment.app.Fragment; 6 | import androidx.fragment.app.FragmentManager; 7 | import androidx.fragment.app.FragmentPagerAdapter; 8 | 9 | import java.util.List; 10 | 11 | public class RecordPagerAdapter extends FragmentPagerAdapter { 12 | ListfragmentList; 13 | String[]titles = {"支出","收入"}; 14 | public RecordPagerAdapter(@NonNull FragmentManager fm,ListfragmentList) { 15 | super(fm); 16 | this.fragmentList = fragmentList; 17 | } 18 | 19 | @NonNull 20 | @Override 21 | public Fragment getItem(int position) { 22 | return fragmentList.get(position); 23 | } 24 | 25 | @Override 26 | public int getCount() { 27 | return fragmentList.size(); 28 | } 29 | 30 | @Nullable 31 | @Override 32 | public CharSequence getPageTitle(int position) { 33 | return titles[position]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/db/DBOpenHelper.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.db; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteOpenHelper; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | import com.jiangqi.booking.R; 10 | 11 | public class DBOpenHelper extends SQLiteOpenHelper { 12 | public DBOpenHelper(@Nullable Context context) { 13 | super(context,"booking.db" , null, 1); 14 | } 15 | 16 | // 创建数据库的方法,只有项目第一次运行时,会被调用 17 | @Override 18 | public void onCreate(SQLiteDatabase db) { 19 | // 创建表示类型的表 20 | String sql = "create table typetb(id integer primary key autoincrement,typename varchar(10),imageId integer,sImageId integer,kind integer)"; 21 | db.execSQL(sql); 22 | insertType(db); 23 | //创建记账表 24 | sql = "create table accounttb(id integer primary key autoincrement,typename varchar(10),sImageId integer,beizhu varchar(80),money float," + 25 | "time varchar(60),year integer,month integer,day integer,kind integer,username varchar(255))"; 26 | db.execSQL(sql); 27 | //创建预算表 28 | sql = "create table budgettb(id integer primary key autoincrement,money float,username varchar(255))"; 29 | db.execSQL(sql); 30 | } 31 | 32 | private void insertType(SQLiteDatabase db) { 33 | // 向typetb表当中插入元素 34 | String sql = "insert into typetb (typename,imageId, sImageId ,kind) values (?,?,?,?)"; 35 | db.execSQL(sql,new Object[]{"其他", R.mipmap.ic_qita,R.mipmap.ic_qita_fs,0}); 36 | db.execSQL(sql,new Object[]{"餐饮", R.mipmap.ic_canyin,R.mipmap.ic_canyin_fs,0}); 37 | db.execSQL(sql,new Object[]{"交通", R.mipmap.ic_jiaotong,R.mipmap.ic_jiaotong_fs,0}); 38 | db.execSQL(sql,new Object[]{"购物", R.mipmap.ic_gouwu,R.mipmap.ic_gouwu_fs,0}); 39 | db.execSQL(sql,new Object[]{"服饰", R.mipmap.ic_fushi,R.mipmap.ic_fushi_fs,0}); 40 | db.execSQL(sql,new Object[]{"日用品", R.mipmap.ic_riyongpin,R.mipmap.ic_riyongpin_fs,0}); 41 | db.execSQL(sql,new Object[]{"娱乐", R.mipmap.ic_yule,R.mipmap.ic_yule_fs,0}); 42 | db.execSQL(sql,new Object[]{"零食", R.mipmap.ic_lingshi,R.mipmap.ic_lingshi_fs,0}); 43 | db.execSQL(sql,new Object[]{"烟酒茶", R.mipmap.ic_yanjiu,R.mipmap.ic_yanjiu_fs,0}); 44 | db.execSQL(sql,new Object[]{"学习", R.mipmap.ic_xuexi,R.mipmap.ic_xuexi_fs,0}); 45 | db.execSQL(sql,new Object[]{"医疗", R.mipmap.ic_yiliao,R.mipmap.ic_yiliao_fs,0}); 46 | db.execSQL(sql,new Object[]{"住宅", R.mipmap.ic_zhufang,R.mipmap.ic_zhufang_fs,0}); 47 | db.execSQL(sql,new Object[]{"水电煤", R.mipmap.ic_shuidianfei,R.mipmap.ic_shuidianfei_fs,0}); 48 | db.execSQL(sql,new Object[]{"通讯", R.mipmap.ic_tongxun,R.mipmap.ic_tongxun_fs,0}); 49 | db.execSQL(sql,new Object[]{"人情往来", R.mipmap.ic_renqingwanglai,R.mipmap.ic_renqingwanglai_fs,0}); 50 | 51 | db.execSQL(sql,new Object[]{"其他", R.mipmap.in_qt,R.mipmap.in_qt_fs,1}); 52 | db.execSQL(sql,new Object[]{"薪资", R.mipmap.in_xinzi,R.mipmap.in_xinzi_fs,1}); 53 | db.execSQL(sql,new Object[]{"奖金", R.mipmap.in_jiangjin,R.mipmap.in_jiangjin_fs,1}); 54 | db.execSQL(sql,new Object[]{"借入", R.mipmap.in_jieru,R.mipmap.in_jieru_fs,1}); 55 | db.execSQL(sql,new Object[]{"收债", R.mipmap.in_shouzhai,R.mipmap.in_shouzhai_fs,1}); 56 | db.execSQL(sql,new Object[]{"利息收入", R.mipmap.in_lixifuji,R.mipmap.in_lixifuji_fs,1}); 57 | db.execSQL(sql,new Object[]{"投资回报", R.mipmap.in_touzi,R.mipmap.in_touzi_fs,1}); 58 | db.execSQL(sql,new Object[]{"二手交易", R.mipmap.in_ershoushebei,R.mipmap.in_ershoushebei_fs,1}); 59 | db.execSQL(sql,new Object[]{"意外所得", R.mipmap.in_yiwai,R.mipmap.in_yiwai_fs,1}); 60 | } 61 | // 数据库版本在更新时发生改变,会调用此方法 62 | @Override 63 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/frag_chart/BaseChartFragment.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.frag_chart; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ListView; 9 | import android.widget.TextView; 10 | 11 | import androidx.fragment.app.Fragment; 12 | 13 | import com.github.mikephil.charting.charts.BarChart; 14 | import com.github.mikephil.charting.components.AxisBase; 15 | import com.github.mikephil.charting.components.XAxis; 16 | import com.github.mikephil.charting.formatter.IAxisValueFormatter; 17 | import com.jiangqi.booking.LoginActivity; 18 | import com.jiangqi.booking.R; 19 | import com.jiangqi.booking.adapter.ChartItemAdapter; 20 | import com.jiangqi.booking.model.ChartItemBean; 21 | import com.jiangqi.booking.db.DBManager; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | /** 27 | * A simple {@link Fragment} subclass. 28 | */ 29 | abstract public class BaseChartFragment extends Fragment { 30 | ListView chartLv; 31 | int year; 32 | int month; 33 | List mDatas; //数据源 34 | private ChartItemAdapter itemAdapter; 35 | BarChart barChart; //代表柱状图的控件 36 | TextView chartTv; //如果没有收支情况,显示的TextView 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 39 | Bundle savedInstanceState) { 40 | 41 | View view = inflater.inflate(R.layout.fragment_incom_chart, container, false); 42 | chartLv = view.findViewById(R.id.frag_chart_lv); 43 | //获取Activity传递的数据 44 | Bundle bundle = getArguments(); 45 | year = bundle.getInt("year"); 46 | month = bundle.getInt("month"); 47 | //设置数据源 48 | mDatas = new ArrayList<>(); 49 | // 设置适配器 50 | itemAdapter = new ChartItemAdapter(getContext(), mDatas); 51 | chartLv.setAdapter(itemAdapter); 52 | // 添加头布局 53 | addLVHeaderView(); 54 | return view; 55 | } 56 | 57 | protected void addLVHeaderView(){ 58 | // 将布局转换成View对象 59 | View headerView = getLayoutInflater().inflate(R.layout.item_chartfrag_top,null); 60 | // 将View添加到ListView的头布局上 61 | chartLv.addHeaderView(headerView); 62 | // 查找头布局当中包含的控件 63 | barChart = headerView.findViewById(R.id.item_chartfrag_chart); 64 | chartTv = headerView.findViewById(R.id.item_chartfrag_top_tv); 65 | // 设定柱状图不显示描述 66 | barChart.getDescription().setEnabled(false); 67 | // 设置柱状图的内边距 68 | barChart.setExtraOffsets(20, 20, 20, 20); 69 | setAxis(year,month); // 设置坐标轴 70 | // 设置坐标轴显示的数据 71 | setAxisData(year,month); 72 | } 73 | /** 设置坐标轴显示的数据*/ 74 | protected abstract void setAxisData(int year, int month); 75 | 76 | /** 设置柱状图坐标轴的显示 方法必须重新*/ 77 | protected void setAxis(int year, final int month){ 78 | // 设置X轴 79 | XAxis xAxis = barChart.getXAxis(); 80 | xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //设置x轴显示在下方 81 | xAxis.setDrawGridLines(true); //设置绘制该轴的网格线 82 | // 设置x轴标签的个数 83 | xAxis.setLabelCount(31); 84 | xAxis.setTextSize(12f); //x轴标签的大小 85 | // 设置X轴显示的值的格式 86 | xAxis.setValueFormatter(new IAxisValueFormatter() { 87 | @Override 88 | public String getFormattedValue(float value, AxisBase axis) { 89 | int val = (int) value; 90 | if (val == 0) { 91 | return month+"-1"; 92 | } 93 | if (val==14) { 94 | return month+"-15"; 95 | } 96 | // 根据不同的月份,显示最后一天的位置 97 | if (month==2) { 98 | if (val == 27) { 99 | return month+"-28"; 100 | } 101 | }else if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){ 102 | if (val == 30) { 103 | return month+"-31"; 104 | } 105 | }else if(month==4||month==6||month==9||month==11){ 106 | if (val==29) { 107 | return month+"-30"; 108 | } 109 | } 110 | return ""; 111 | } 112 | }); 113 | xAxis.setYOffset(10); // 设置标签对x轴的偏移量,垂直方向 114 | 115 | // y轴在子类的设置 116 | setYAxis(year,month); 117 | } 118 | 119 | /* 设置y轴,因为最高的坐标不确定,所以在子类当中设置*/ 120 | protected abstract void setYAxis(int year,int month); 121 | 122 | public void setDate(int year,int month){ 123 | this.year = year; 124 | this.month = month; 125 | // 清空柱状图当中的数据 126 | barChart.clear(); 127 | barChart.invalidate(); //重新绘制柱状图 128 | setAxis(year,month); 129 | setAxisData(year,month); 130 | } 131 | 132 | public void loadData(int year,int month,int kind) { 133 | List list = DBManager.getChartListFromAccounttb(year, month, kind, LoginActivity.getmUsername()); 134 | mDatas.clear(); 135 | mDatas.addAll(list); 136 | itemAdapter.notifyDataSetChanged(); 137 | } 138 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/frag_chart/IncomChartFragment.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.frag_chart; 2 | 3 | 4 | import android.graphics.Color; 5 | 6 | import androidx.fragment.app.Fragment; 7 | 8 | import android.view.View; 9 | 10 | import com.github.mikephil.charting.components.Legend; 11 | import com.github.mikephil.charting.components.YAxis; 12 | import com.github.mikephil.charting.data.BarData; 13 | import com.github.mikephil.charting.data.BarDataSet; 14 | import com.github.mikephil.charting.data.BarEntry; 15 | import com.github.mikephil.charting.data.Entry; 16 | import com.github.mikephil.charting.formatter.IValueFormatter; 17 | import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; 18 | import com.github.mikephil.charting.utils.ViewPortHandler; 19 | import com.jiangqi.booking.LoginActivity; 20 | import com.jiangqi.booking.model.BarChartItemBean; 21 | import com.jiangqi.booking.db.DBManager; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | /** 27 | * A simple {@link Fragment} subclass. 28 | */ 29 | public class IncomChartFragment extends BaseChartFragment { 30 | int kind = 1; 31 | @Override 32 | public void onResume() { 33 | super.onResume(); 34 | loadData(year,month,kind); 35 | } 36 | @Override 37 | protected void setAxisData(int year, int month) { 38 | List sets = new ArrayList<>(); 39 | // 获取这个月每天的支出总金额, 40 | List list = DBManager.getSumMoneyOneDayInMonth(year, month, kind, LoginActivity.getmUsername()); 41 | if (list.size() == 0) { 42 | barChart.setVisibility(View.GONE); 43 | chartTv.setVisibility(View.VISIBLE); 44 | }else{ 45 | barChart.setVisibility(View.VISIBLE); 46 | chartTv.setVisibility(View.GONE); 47 | // 设置有多少根柱子 48 | List barEntries1 = new ArrayList<>(); 49 | for (int i = 0; i < 31; i++) { 50 | // 初始化每一根柱子,添加到柱状图当中 51 | BarEntry entry = new BarEntry(i, 0.0f); 52 | barEntries1.add(entry); 53 | } 54 | for (int i = 0; i < list.size(); i++) { 55 | BarChartItemBean itemBean = list.get(i); 56 | int day = itemBean.getDay(); //获取日期 57 | // 根据天数,获取x轴的位置 58 | int xIndex = day-1; 59 | BarEntry barEntry = barEntries1.get(xIndex); 60 | barEntry.setY(itemBean.getSummoney()); 61 | } 62 | BarDataSet barDataSet1 = new BarDataSet(barEntries1, ""); 63 | barDataSet1.setValueTextColor(Color.BLACK); // 值的颜色 64 | barDataSet1.setValueTextSize(8f); // 值的大小 65 | barDataSet1.setColor(Color.parseColor("#006400")); // 柱子的颜色 66 | 67 | // 设置柱子上数据显示的格式 68 | barDataSet1.setValueFormatter(new IValueFormatter() { 69 | @Override 70 | public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { 71 | // 此处的value默认保存一位小数 72 | if (value==0) { 73 | return ""; 74 | } 75 | return value + ""; 76 | } 77 | }); 78 | sets.add(barDataSet1); 79 | 80 | BarData barData = new BarData(sets); 81 | barData.setBarWidth(0.2f); // 设置柱子的宽度 82 | barChart.setData(barData); 83 | } 84 | } 85 | 86 | @Override 87 | protected void setYAxis(int year, int month) { 88 | // 获取本月收入最高的一天为多少,将他设定为y轴的最大值 89 | float maxMoney = DBManager.getMaxMoneyOneDayInMonth(year, month, kind,LoginActivity.getmUsername()); 90 | float max = (float) Math.ceil(maxMoney); // 将最大金额向上取整 91 | // 设置y轴 92 | YAxis yAxis_right = barChart.getAxisRight(); 93 | yAxis_right.setAxisMaximum(max); // 设置y轴的最大值 94 | yAxis_right.setAxisMinimum(0f); // 设置y轴的最小值 95 | yAxis_right.setEnabled(false); // 不显示右边的y轴 96 | 97 | YAxis yAxis_left = barChart.getAxisLeft(); 98 | yAxis_left.setAxisMaximum(max); 99 | yAxis_left.setAxisMinimum(0f); 100 | yAxis_left.setEnabled(false); 101 | 102 | // 设置不显示图例 103 | Legend legend = barChart.getLegend(); 104 | legend.setEnabled(false); 105 | } 106 | 107 | 108 | @Override 109 | public void setDate(int year, int month) { 110 | super.setDate(year, month); 111 | loadData(year,month,kind); 112 | } 113 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/frag_chart/OutcomChartFragment.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.frag_chart; 2 | 3 | 4 | import android.graphics.Color; 5 | import android.view.View; 6 | 7 | import androidx.fragment.app.Fragment; 8 | 9 | import com.github.mikephil.charting.components.Legend; 10 | import com.github.mikephil.charting.components.YAxis; 11 | import com.github.mikephil.charting.data.BarData; 12 | import com.github.mikephil.charting.data.BarDataSet; 13 | import com.github.mikephil.charting.data.BarEntry; 14 | import com.github.mikephil.charting.data.Entry; 15 | import com.github.mikephil.charting.formatter.IValueFormatter; 16 | import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; 17 | import com.github.mikephil.charting.utils.ViewPortHandler; 18 | import com.jiangqi.booking.LoginActivity; 19 | import com.jiangqi.booking.model.BarChartItemBean; 20 | import com.jiangqi.booking.db.DBManager; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | * A simple {@link Fragment} subclass. 27 | */ 28 | public class OutcomChartFragment extends BaseChartFragment { 29 | int kind = 0; 30 | @Override 31 | public void onResume() { 32 | super.onResume(); 33 | loadData(year,month,kind); 34 | } 35 | 36 | @Override 37 | protected void setAxisData(int year, int month) { 38 | List sets = new ArrayList<>(); 39 | // 获取这个月每天的支出总金额, 40 | List list = DBManager.getSumMoneyOneDayInMonth(year, month, kind, LoginActivity.getmUsername()); 41 | if (list.size() == 0) { 42 | barChart.setVisibility(View.GONE); 43 | chartTv.setVisibility(View.VISIBLE); 44 | }else{ 45 | barChart.setVisibility(View.VISIBLE); 46 | chartTv.setVisibility(View.GONE); 47 | // 设置有多少根柱子 48 | List barEntries1 = new ArrayList<>(); 49 | for (int i = 0; i < 31; i++) { 50 | // 初始化每一根柱子,添加到柱状图当中 51 | BarEntry entry = new BarEntry(i, 0.0f); 52 | barEntries1.add(entry); 53 | } 54 | for (int i = 0; i < list.size(); i++) { 55 | BarChartItemBean itemBean = list.get(i); 56 | int day = itemBean.getDay(); //获取日期 57 | // 根据天数,获取x轴的位置 58 | int xIndex = day-1; 59 | BarEntry barEntry = barEntries1.get(xIndex); 60 | barEntry.setY(itemBean.getSummoney()); 61 | } 62 | BarDataSet barDataSet1 = new BarDataSet(barEntries1, ""); 63 | barDataSet1.setValueTextColor(Color.BLACK); // 值的颜色 64 | barDataSet1.setValueTextSize(8f); // 值的大小 65 | barDataSet1.setColor(Color.RED); // 柱子的颜色 66 | 67 | // 设置柱子上数据显示的格式 68 | barDataSet1.setValueFormatter(new IValueFormatter() { 69 | @Override 70 | public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { 71 | // 此处的value默认保存一位小数 72 | if (value==0) { 73 | return ""; 74 | } 75 | return value + ""; 76 | } 77 | }); 78 | sets.add(barDataSet1); 79 | 80 | BarData barData = new BarData(sets); 81 | barData.setBarWidth(0.2f); // 设置柱子的宽度 82 | barChart.setData(barData); 83 | } 84 | } 85 | 86 | @Override 87 | protected void setYAxis(int year, int month) { 88 | // 获取本月收入最高的一天为多少,将他设定为y轴的最大值 89 | float maxMoney = DBManager.getMaxMoneyOneDayInMonth(year, month, kind,LoginActivity.getmUsername()); 90 | float max = (float) Math.ceil(maxMoney); // 将最大金额向上取整 91 | // 设置y轴 92 | YAxis yAxis_right = barChart.getAxisRight(); 93 | yAxis_right.setAxisMaximum(max); // 设置y轴的最大值 94 | yAxis_right.setAxisMinimum(0f); // 设置y轴的最小值 95 | yAxis_right.setEnabled(false); // 不显示右边的y轴 96 | 97 | YAxis yAxis_left = barChart.getAxisLeft(); 98 | yAxis_left.setAxisMaximum(max); 99 | yAxis_left.setAxisMinimum(0f); 100 | yAxis_left.setEnabled(false); 101 | 102 | // 设置不显示图例 103 | Legend legend = barChart.getLegend(); 104 | legend.setEnabled(false); 105 | } 106 | 107 | @Override 108 | public void setDate(int year, int month) { 109 | super.setDate(year, month); 110 | loadData(year,month,kind); 111 | } 112 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/frag_record/IncomeFragment.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.frag_record; 2 | import com.jiangqi.booking.LoginActivity; 3 | import com.jiangqi.booking.model.TypeBean; 4 | import com.jiangqi.booking.R; 5 | import com.jiangqi.booking.db.DBManager; 6 | 7 | import java.util.List; 8 | /** 9 | * 收入记录页面 10 | */ 11 | public class IncomeFragment extends BaseRecordFragment { 12 | @Override 13 | public void loadDataToGV() { 14 | super.loadDataToGV(); 15 | //获取数据库当中的数据源 16 | List inlist = DBManager.getTypeList(1); 17 | typeList.addAll(inlist); 18 | adapter.notifyDataSetChanged(); 19 | typeTv.setText("其他"); 20 | typeIv.setImageResource(R.mipmap.in_qt_fs); 21 | } 22 | 23 | @Override 24 | public void saveAccountToDB() { 25 | accountBean.setKind(1); 26 | DBManager.insertItemToAccounttb(accountBean, LoginActivity.getmUsername()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/frag_record/OutcomeFragment.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.frag_record; 2 | 3 | import androidx.fragment.app.Fragment; 4 | 5 | import com.jiangqi.booking.LoginActivity; 6 | import com.jiangqi.booking.R; 7 | import com.jiangqi.booking.db.DBManager; 8 | import com.jiangqi.booking.model.TypeBean; 9 | 10 | import java.util.List; 11 | /** 12 | * A simple {@link Fragment} subclass. 13 | */ 14 | public class OutcomeFragment extends BaseRecordFragment { 15 | // 重写 16 | @Override 17 | public void loadDataToGV() { 18 | super.loadDataToGV(); 19 | //获取数据库当中的数据源 20 | List outlist = DBManager.getTypeList(0); 21 | typeList.addAll(outlist); 22 | adapter.notifyDataSetChanged(); 23 | typeTv.setText("其他"); 24 | typeIv.setImageResource(R.mipmap.ic_qita_fs); 25 | } 26 | 27 | @Override 28 | public void saveAccountToDB() { 29 | accountBean.setKind(0); 30 | DBManager.insertItemToAccounttb(accountBean, LoginActivity.getmUsername()); 31 | } 32 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/frag_record/TypeBaseAdapter.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.frag_record; 2 | import android.content.Context; 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.BaseAdapter; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import com.jiangqi.booking.model.TypeBean; 11 | import com.jiangqi.booking.R; 12 | 13 | import java.util.List; 14 | 15 | public class TypeBaseAdapter extends BaseAdapter { 16 | Context context; 17 | ListmDatas; 18 | int selectPos = 0; //选中位置 19 | public TypeBaseAdapter(Context context, List mDatas) { 20 | this.context = context; 21 | this.mDatas = mDatas; 22 | } 23 | @Override 24 | public int getCount() { 25 | return mDatas.size(); 26 | } 27 | 28 | @Override 29 | public Object getItem(int position) { 30 | return mDatas.get(position); 31 | } 32 | 33 | @Override 34 | public long getItemId(int position) { 35 | return position; 36 | } 37 | // 此适配器不考虑复用问题,因为所有的item都显示在界面上,不会因为滑动就消失,所有没有剩余的convertView,所以不用复写 38 | @Override 39 | public View getView(int position, View convertView, ViewGroup parent) { 40 | convertView = LayoutInflater.from(context).inflate(R.layout.item_recordfrag_gv,parent,false); 41 | //查找布局当中的控件 42 | ImageView iv = convertView.findViewById(R.id.item_recordfrag_iv); 43 | TextView tv = convertView.findViewById(R.id.item_recordfrag_tv); 44 | //获取指定位置的数据源 45 | TypeBean typeBean = mDatas.get(position); 46 | tv.setText(typeBean.getTypename()); 47 | // 判断当前位置是否为选中位置,如果是选中位置,就设置为带颜色的图片,否则为灰色图片 48 | if (selectPos == position) { 49 | iv.setImageResource(typeBean.getSimageId()); 50 | }else{ 51 | iv.setImageResource(typeBean.getImageId()); 52 | } 53 | return convertView; 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/model/AccountBean.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.model; 2 | /** 描述记录一条数据的相关内容类*/ 3 | public class AccountBean { 4 | int id; 5 | String typename; //类型 6 | int sImageId; //被选中类型图片 7 | String beizhu; //备注 8 | float money; //价格 9 | String time ; //保存时间字符串 10 | int year; 11 | int month; 12 | int day; 13 | int kind; //类型 收入---1 支出---0 14 | 15 | public int getId() { 16 | return id; 17 | } 18 | 19 | public void setId(int id) { 20 | this.id = id; 21 | } 22 | 23 | public String getTypename() { 24 | return typename; 25 | } 26 | 27 | public void setTypename(String typename) { 28 | this.typename = typename; 29 | } 30 | 31 | public int getsImageId() { 32 | return sImageId; 33 | } 34 | 35 | public void setsImageId(int sImageId) { 36 | this.sImageId = sImageId; 37 | } 38 | 39 | public String getBeizhu() { 40 | return beizhu; 41 | } 42 | 43 | public void setBeizhu(String beizhu) { 44 | this.beizhu = beizhu; 45 | } 46 | 47 | public float getMoney() { 48 | return money; 49 | } 50 | 51 | public void setMoney(float money) { 52 | this.money = money; 53 | } 54 | 55 | public String getTime() { 56 | return time; 57 | } 58 | 59 | public void setTime(String time) { 60 | this.time = time; 61 | } 62 | 63 | public int getYear() { 64 | return year; 65 | } 66 | 67 | public void setYear(int year) { 68 | this.year = year; 69 | } 70 | 71 | public int getMonth() { 72 | return month; 73 | } 74 | 75 | public void setMonth(int month) { 76 | this.month = month; 77 | } 78 | 79 | public int getDay() { 80 | return day; 81 | } 82 | 83 | public void setDay(int day) { 84 | this.day = day; 85 | } 86 | 87 | public int getKind() { 88 | return kind; 89 | } 90 | 91 | public void setKind(int kind) { 92 | this.kind = kind; 93 | } 94 | 95 | public AccountBean() { 96 | } 97 | 98 | public AccountBean(int id, String typename, int sImageId, String beizhu, float money, String time, int year, int month, int day, int kind) { 99 | this.id = id; 100 | this.typename = typename; 101 | this.sImageId = sImageId; 102 | this.beizhu = beizhu; 103 | this.money = money; 104 | this.time = time; 105 | this.year = year; 106 | this.month = month; 107 | this.day = day; 108 | this.kind = kind; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/model/BarChartItemBean.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.model; 2 | /* 用于描述绘制柱状图时,每一个柱子表示的对象*/ 3 | public class BarChartItemBean { 4 | int year; 5 | int month; 6 | int day; 7 | float summoney; 8 | 9 | public BarChartItemBean() { 10 | } 11 | 12 | public int getYear() { 13 | return year; 14 | } 15 | 16 | public void setYear(int year) { 17 | this.year = year; 18 | } 19 | 20 | public int getMonth() { 21 | return month; 22 | } 23 | 24 | public void setMonth(int month) { 25 | this.month = month; 26 | } 27 | 28 | public int getDay() { 29 | return day; 30 | } 31 | 32 | public void setDay(int day) { 33 | this.day = day; 34 | } 35 | 36 | public float getSummoney() { 37 | return summoney; 38 | } 39 | 40 | public void setSummoney(float summoney) { 41 | this.summoney = summoney; 42 | } 43 | 44 | public BarChartItemBean(int year, int month, int day, float summoney) { 45 | this.year = year; 46 | this.month = month; 47 | this.day = day; 48 | this.summoney = summoney; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/model/ChartItemBean.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.model; 2 | 3 | public class ChartItemBean { 4 | int sImageId; 5 | String type; 6 | float ratio; //所占比例 7 | float totalMoney; //此项的总钱数 8 | 9 | public ChartItemBean() { 10 | } 11 | 12 | public void setsImageId(int sImageId) { 13 | this.sImageId = sImageId; 14 | } 15 | 16 | public void setType(String type) { 17 | this.type = type; 18 | } 19 | 20 | public void setRatio(float ratio) { 21 | this.ratio = ratio; 22 | } 23 | 24 | public void setTotalMoney(float totalMoney) { 25 | this.totalMoney = totalMoney; 26 | } 27 | 28 | public int getsImageId() { 29 | return sImageId; 30 | } 31 | 32 | public String getType() { 33 | return type; 34 | } 35 | 36 | public float getRatio() { 37 | return ratio; 38 | } 39 | 40 | public float getTotalMoney() { 41 | return totalMoney; 42 | } 43 | 44 | public ChartItemBean(int sImageId, String type, float ratio, float totalMoney) { 45 | this.sImageId = sImageId; 46 | this.type = type; 47 | this.ratio = ratio; 48 | this.totalMoney = totalMoney; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/model/TypeBean.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.model; 2 | /* 3 | * 表示收入或者支出具体类型的类 4 | * */ 5 | public class TypeBean { 6 | int id; 7 | String typename; //类型名称 8 | int imageId; //未被选中图片id 9 | int simageId; //被选中图片id 10 | int kind; //收入-1 支出-0 11 | 12 | public int getId() { 13 | return id; 14 | } 15 | 16 | public void setId(int id) { 17 | this.id = id; 18 | } 19 | 20 | public String getTypename() { 21 | return typename; 22 | } 23 | 24 | public void setTypename(String typename) { 25 | this.typename = typename; 26 | } 27 | 28 | public int getImageId() { 29 | return imageId; 30 | } 31 | 32 | public void setImageId(int imageId) { 33 | this.imageId = imageId; 34 | } 35 | 36 | public int getSimageId() { 37 | return simageId; 38 | } 39 | 40 | public void setSimageId(int simageId) { 41 | this.simageId = simageId; 42 | } 43 | 44 | public int getKind() { 45 | return kind; 46 | } 47 | 48 | public void setKind(int kind) { 49 | this.kind = kind; 50 | } 51 | 52 | public TypeBean() { 53 | } 54 | public TypeBean(int id, String typename, int imageId, int simageId, int kind) { 55 | this.id = id; 56 | this.typename = typename; 57 | this.imageId = imageId; 58 | this.simageId = simageId; 59 | this.kind = kind; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/AnalysisUtils.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | public class AnalysisUtils { 7 | //从SharedPreferences中读取登录用户名 8 | public static String readLoginUserName(Context context) { 9 | 10 | SharedPreferences sp = context.getSharedPreferences("loginInfo", Context.MODE_PRIVATE); 11 | String userName = sp.getString("loginUserName", ""); 12 | return userName; 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/BeiZhuDialog.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.os.Message; 8 | import android.view.Display; 9 | import android.view.Gravity; 10 | import android.view.View; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | import android.view.inputmethod.InputMethodManager; 14 | import android.widget.Button; 15 | import android.widget.EditText; 16 | 17 | import androidx.annotation.NonNull; 18 | 19 | import com.jiangqi.booking.R; 20 | 21 | public class BeiZhuDialog extends Dialog implements View.OnClickListener { 22 | EditText et; 23 | Button cancelBtn,ensureBtn; 24 | OnEnsureListener onEnsureListener; 25 | // 设定回调接口的方法 26 | public void setOnEnsureListener(OnEnsureListener onEnsureListener) { 27 | this.onEnsureListener = onEnsureListener; 28 | } 29 | 30 | public BeiZhuDialog(@NonNull Context context) { 31 | super(context); 32 | } 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.dialog_beizhu);//设置对话框显示布局 38 | et = findViewById(R.id.dialog_beizhu_et); 39 | cancelBtn = findViewById(R.id.dialog_beizhu_btn_cancel); 40 | ensureBtn = findViewById(R.id.dialog_beizhu_btn_ensure); 41 | cancelBtn.setOnClickListener(this); 42 | ensureBtn.setOnClickListener(this); 43 | } 44 | public interface OnEnsureListener{ 45 | public void onEnsure(); 46 | } 47 | 48 | @Override 49 | public void onClick(View v) { 50 | switch (v.getId()) { 51 | case R.id.dialog_beizhu_btn_cancel: 52 | cancel(); 53 | break; 54 | case R.id.dialog_beizhu_btn_ensure: 55 | if (onEnsureListener!=null) { 56 | onEnsureListener.onEnsure(); 57 | } 58 | break; 59 | } 60 | } 61 | 62 | // 获取输入数据的方法 63 | public String getEditText(){ 64 | return et.getText().toString().trim(); 65 | } 66 | /* 设置Dialog的尺寸和屏幕尺寸一致*/ 67 | public void setDialogSize(){ 68 | // 获取当前窗口对象 69 | Window window = getWindow(); 70 | // 获取窗口对象的参数 71 | WindowManager.LayoutParams wlp = window.getAttributes(); 72 | // 获取屏幕宽度 73 | Display d = window.getWindowManager().getDefaultDisplay(); 74 | wlp.width = (int)(d.getWidth()); //对话框窗口为屏幕窗口 75 | wlp.gravity = Gravity.BOTTOM; 76 | window.setBackgroundDrawableResource(android.R.color.transparent); 77 | window.setAttributes(wlp); 78 | handler.sendEmptyMessageDelayed(1,100); 79 | } 80 | 81 | Handler handler = new Handler(){ 82 | @Override 83 | public void handleMessage(@NonNull Message msg) { 84 | //自动弹出软键盘的方法 85 | InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 86 | inputMethodManager.toggleSoftInput(0,InputMethodManager.HIDE_NOT_ALWAYS); 87 | } 88 | }; 89 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/BudgetDialog.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.os.Message; 8 | import android.text.TextUtils; 9 | import android.view.Display; 10 | import android.view.Gravity; 11 | import android.view.View; 12 | import android.view.Window; 13 | import android.view.WindowManager; 14 | import android.view.inputmethod.InputMethodManager; 15 | import android.widget.Button; 16 | import android.widget.EditText; 17 | import android.widget.ImageView; 18 | import android.widget.Toast; 19 | 20 | import androidx.annotation.NonNull; 21 | 22 | import com.jiangqi.booking.LoginActivity; 23 | import com.jiangqi.booking.R; 24 | import com.jiangqi.booking.db.DBManager; 25 | 26 | public class BudgetDialog extends Dialog implements View.OnClickListener { 27 | ImageView cancelIv; 28 | Button ensureBtn; 29 | EditText moneyEt; 30 | public interface OnEnsureListener{ 31 | public void onEnsure(float money); 32 | } 33 | OnEnsureListener onEnsureListener; 34 | 35 | public void setOnEnsureListener(OnEnsureListener onEnsureListener) { 36 | this.onEnsureListener = onEnsureListener; 37 | } 38 | 39 | public BudgetDialog(@NonNull Context context) { 40 | super(context); 41 | } 42 | 43 | @Override 44 | protected void onCreate(Bundle savedInstanceState) { 45 | super.onCreate(savedInstanceState); 46 | setContentView(R.layout.dialog_budget); 47 | cancelIv = findViewById(R.id.dialog_budget_iv_error); 48 | ensureBtn = findViewById(R.id.dialog_budget_btn_ensure); 49 | moneyEt = findViewById(R.id.dialog_budget_et); 50 | cancelIv.setOnClickListener(this); 51 | ensureBtn.setOnClickListener(this); 52 | } 53 | 54 | @Override 55 | public void onClick(View v) { 56 | switch (v.getId()) { 57 | case R.id.dialog_budget_iv_error: 58 | cancel(); //取消对话框 59 | break; 60 | case R.id.dialog_budget_btn_ensure: 61 | //获取输入数据数值 62 | String data = moneyEt.getText().toString(); 63 | if (TextUtils.isEmpty(data)) { 64 | Toast.makeText(getContext(),"输入数据不能为空!",Toast.LENGTH_SHORT).show(); 65 | return; 66 | } 67 | float money = Float.parseFloat(data); 68 | if (money<=0) { 69 | Toast.makeText(getContext(),"预算金额必须大于0",Toast.LENGTH_SHORT).show(); 70 | return; 71 | } 72 | if (DBManager.getBudgettbMoney(LoginActivity.getmUsername())==0){ 73 | DBManager.insertItemToBudgettb(money,LoginActivity.getmUsername()); 74 | } 75 | 76 | if (onEnsureListener!=null) { 77 | onEnsureListener.onEnsure(money); 78 | } 79 | cancel(); 80 | break; 81 | } 82 | } 83 | 84 | /* 设置Dialog的尺寸和屏幕尺寸一致*/ 85 | public void setDialogSize(){ 86 | // 获取当前窗口对象 87 | Window window = getWindow(); 88 | // 获取窗口对象的参数 89 | WindowManager.LayoutParams wlp = window.getAttributes(); 90 | // 获取屏幕宽度 91 | Display d = window.getWindowManager().getDefaultDisplay(); 92 | wlp.width = (int)(d.getWidth()); //对话框窗口为屏幕窗口 93 | wlp.gravity = Gravity.BOTTOM; 94 | window.setBackgroundDrawableResource(android.R.color.transparent); 95 | window.setAttributes(wlp); 96 | handler.sendEmptyMessageDelayed(1,100); 97 | } 98 | 99 | Handler handler = new Handler(){ 100 | @Override 101 | public void handleMessage(@NonNull Message msg) { 102 | //自动弹出软键盘的方法 103 | InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 104 | inputMethodManager.toggleSoftInput(0,InputMethodManager.HIDE_NOT_ALWAYS); 105 | } 106 | }; 107 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/FloatUtils.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | 3 | import java.math.BigDecimal; 4 | 5 | public class FloatUtils { 6 | 7 | /* 进行除法运算,保留4位小数*/ 8 | public static float div(float v1,float v2){ 9 | float v3 = v1/v2; 10 | BigDecimal b1 = new BigDecimal(v3); 11 | float val = b1.setScale(4, 4).floatValue(); 12 | return val; 13 | } 14 | 15 | // 将浮点数类型,转换成百分比显示形式 16 | public static String ratioToPercent(float val){ 17 | float v = val*100; 18 | BigDecimal b1 = new BigDecimal(v); 19 | float v1 = b1.setScale(2, 4).floatValue(); 20 | String per = v1+"%"; 21 | return per; 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/KeyBoardUtils.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | 3 | import android.inputmethodservice.Keyboard; 4 | import android.inputmethodservice.KeyboardView; 5 | import android.text.Editable; 6 | import android.text.InputType; 7 | import android.view.View; 8 | import android.widget.EditText; 9 | 10 | import com.jiangqi.booking.R; 11 | 12 | public class KeyBoardUtils { 13 | private final Keyboard k1; //自定义键盘 14 | private KeyboardView keyboardView; 15 | private EditText editText; 16 | 17 | public interface OnEnsureListener{ 18 | public void onEnsure(); 19 | } 20 | OnEnsureListener onEnsureListener; 21 | 22 | public void setOnEnsureListener(OnEnsureListener onEnsureListener) { 23 | this.onEnsureListener = onEnsureListener; 24 | } 25 | 26 | public KeyBoardUtils(KeyboardView keyboardView, EditText editText) { 27 | this.keyboardView = keyboardView; 28 | this.editText = editText; 29 | this.editText.setInputType(InputType.TYPE_NULL); //取消弹出系统键盘 30 | k1 = new Keyboard(this.editText.getContext(), R.xml.key); 31 | 32 | this.keyboardView.setKeyboard(k1); //设置要显示键盘的样式 33 | this.keyboardView.setEnabled(true); 34 | this.keyboardView.setPreviewEnabled(false); 35 | this.keyboardView.setOnKeyboardActionListener(listener); //设置键盘按钮被点击了的监听 36 | } 37 | 38 | KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() { 39 | @Override 40 | public void onPress(int primaryCode) { 41 | } 42 | @Override 43 | public void onRelease(int primaryCode) { 44 | } 45 | @Override 46 | public void onKey(int primaryCode, int[] keyCodes) { 47 | Editable editable = editText.getText(); 48 | int start = editText.getSelectionStart(); 49 | switch (primaryCode) { 50 | case Keyboard.KEYCODE_DELETE: //点击了删除键 51 | if (editable!=null &&editable.length()>0) { 52 | if (start>0) { 53 | editable.delete(start-1,start); 54 | } 55 | } 56 | break; 57 | case Keyboard.KEYCODE_CANCEL: //点击了清零 58 | editable.clear(); 59 | break; 60 | case Keyboard.KEYCODE_DONE: //点击了完成 61 | onEnsureListener.onEnsure(); //通过接口回调的方法,当点击确定时,可以调用这个方法 62 | break; 63 | default: //其他数字直接插入 64 | editable.insert(start,Character.toString((char)primaryCode)); 65 | break; 66 | } 67 | } 68 | @Override 69 | public void onText(CharSequence text) { 70 | } 71 | @Override 72 | public void swipeLeft() { 73 | } 74 | @Override 75 | public void swipeRight() { 76 | } 77 | @Override 78 | public void swipeDown() { 79 | } 80 | @Override 81 | public void swipeUp() { 82 | } 83 | }; 84 | 85 | // 显示键盘 86 | public void showKeyboard(){ 87 | int visibility = keyboardView.getVisibility(); 88 | if (visibility == View.INVISIBLE ||visibility==View.GONE) { 89 | keyboardView.setVisibility(View.VISIBLE); 90 | } 91 | } 92 | 93 | // 隐藏键盘 94 | public void hideKeyboard(){ 95 | int visibility = keyboardView.getVisibility(); 96 | if (visibility== View.VISIBLE||visibility==View.INVISIBLE) { 97 | keyboardView.setVisibility(View.GONE); 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/MD5Utils.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | public class MD5Utils { 7 | /** 8 | * md5加密的算法 9 | * 10 | * @param text 11 | * @return 12 | */ 13 | public static String MD5(String text) { 14 | try { 15 | MessageDigest digest = MessageDigest.getInstance("md5"); 16 | byte[] result = digest.digest(text.getBytes()); 17 | StringBuffer sb = new StringBuffer(); 18 | for (byte b : result) { 19 | int number = b & 0xff; 20 | String hex = Integer.toHexString(number); 21 | if (hex.length() == 1) {//如果0xff为一个字节 22 | sb.append("0" + hex); 23 | } else { 24 | sb.append(hex); 25 | } 26 | } 27 | return sb.toString(); 28 | 29 | } catch (NoSuchAlgorithmException e) { 30 | e.printStackTrace(); 31 | return "";//如果发生异常 32 | } 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/MoreDialog.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | import android.app.Dialog; 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Gravity; 8 | import android.view.View; 9 | import android.view.Window; 10 | import android.view.WindowManager; 11 | import android.widget.Button; 12 | import android.widget.ImageView; 13 | import androidx.annotation.NonNull; 14 | 15 | import com.jiangqi.booking.AboutActivity; 16 | import com.jiangqi.booking.HistoryActivity; 17 | import com.jiangqi.booking.MonthChartActivity; 18 | import com.jiangqi.booking.SettingActivity; 19 | import com.jiangqi.booking.R; 20 | 21 | public class MoreDialog extends Dialog implements View.OnClickListener { 22 | Button meBtn,settingBtn,historyBtn,infoBtn; 23 | ImageView errorIv; 24 | public MoreDialog(@NonNull Context context) { 25 | super(context); 26 | } 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.dialog_more); 31 | meBtn = findViewById(R.id.dialog_more_btn_me); 32 | settingBtn = findViewById(R.id.dialog_more_btn_setting); 33 | historyBtn = findViewById(R.id.dialog_more_btn_record); 34 | infoBtn = findViewById(R.id.dialog_more_btn_info); 35 | errorIv = findViewById(R.id.dialog_more_iv); 36 | 37 | meBtn.setOnClickListener(this); 38 | settingBtn.setOnClickListener(this); 39 | historyBtn.setOnClickListener(this); 40 | infoBtn.setOnClickListener(this); 41 | errorIv.setOnClickListener(this); 42 | } 43 | 44 | @Override 45 | public void onClick(View v) { 46 | Intent intent = new Intent(); 47 | switch (v.getId()) { 48 | case R.id.dialog_more_btn_me: 49 | intent.setClass(getContext(), AboutActivity.class); 50 | getContext().startActivity(intent); 51 | break; 52 | case R.id.dialog_more_btn_setting: 53 | intent.setClass(getContext(), SettingActivity.class); 54 | getContext().startActivity(intent); 55 | break; 56 | case R.id.dialog_more_btn_record: 57 | intent.setClass(getContext(), HistoryActivity.class); 58 | getContext().startActivity(intent); 59 | break; 60 | case R.id.dialog_more_btn_info: 61 | intent.setClass(getContext(), MonthChartActivity.class); 62 | getContext().startActivity(intent); 63 | break; 64 | case R.id.dialog_more_iv: 65 | break; 66 | } 67 | cancel(); 68 | } 69 | 70 | /* 设置Dialog的尺寸和屏幕尺寸一致*/ 71 | public void setDialogSize(){ 72 | // 获取当前窗口对象 73 | Window window = getWindow(); 74 | // 获取窗口对象的参数 75 | WindowManager.LayoutParams wlp = window.getAttributes(); 76 | // 获取屏幕宽度 77 | Display d = window.getWindowManager().getDefaultDisplay(); 78 | wlp.width = (int)(d.getWidth()); //对话框窗口为屏幕窗口 79 | wlp.gravity = Gravity.BOTTOM; 80 | window.setBackgroundDrawableResource(android.R.color.transparent); 81 | window.setAttributes(wlp); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/jiangqi/booking/utils/SelectTimeDialog.java: -------------------------------------------------------------------------------- 1 | package com.jiangqi.booking.utils; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.text.TextUtils; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.Button; 10 | import android.widget.DatePicker; 11 | import android.widget.EditText; 12 | 13 | import androidx.annotation.NonNull; 14 | 15 | import com.jiangqi.booking.R; 16 | 17 | /* 18 | * 在记录页面弹出时间对话框 19 | * */ 20 | public class SelectTimeDialog extends Dialog implements View.OnClickListener { 21 | EditText hourEt,minuteEt; 22 | DatePicker datePicker; 23 | Button ensureBtn,cancelBtn; 24 | public interface OnEnsureListener{ 25 | public void onEnsure(String time,int year,int month,int day); 26 | } 27 | OnEnsureListener onEnsureListener; 28 | 29 | public void setOnEnsureListener(OnEnsureListener onEnsureListener) { 30 | this.onEnsureListener = onEnsureListener; 31 | } 32 | 33 | public SelectTimeDialog(@NonNull Context context) { 34 | super(context); 35 | } 36 | 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.dialog_time); 41 | hourEt = findViewById(R.id.dialog_time_et_hour); 42 | minuteEt = findViewById(R.id.dialog_time_et_minute); 43 | datePicker = findViewById(R.id.dialog_time_dp); 44 | ensureBtn = findViewById(R.id.dialog_time_btn_ensure); 45 | cancelBtn = findViewById(R.id.dialog_time_btn_cancel); 46 | ensureBtn.setOnClickListener(this); //添加点击监听事件 47 | cancelBtn.setOnClickListener(this); 48 | hideDatePickerHeader(); 49 | } 50 | 51 | @Override 52 | public void onClick(View v) { 53 | switch (v.getId()) { 54 | case R.id.dialog_time_btn_cancel: 55 | cancel(); 56 | break; 57 | case R.id.dialog_time_btn_ensure: 58 | int year = datePicker.getYear(); //选择年份 59 | int month = datePicker.getMonth()+1; 60 | int dayOfMonth = datePicker.getDayOfMonth(); 61 | String monthStr = String.valueOf(month); 62 | if (month<10){ 63 | monthStr = "0"+month; 64 | } 65 | String dayStr = String.valueOf(dayOfMonth); 66 | if (dayOfMonth<10){ 67 | dayStr="0"+dayOfMonth; 68 | } 69 | // 获取输入的小时和分钟 70 | String hourStr = hourEt.getText().toString(); 71 | String minuteStr = minuteEt.getText().toString(); 72 | int hour = 0; 73 | if (!TextUtils.isEmpty(hourStr)) { 74 | hour = Integer.parseInt(hourStr); 75 | hour=hour%24; 76 | } 77 | int minute = 0; 78 | if (!TextUtils.isEmpty(minuteStr)) { 79 | minute = Integer.parseInt(minuteStr); 80 | minute=minute%60; 81 | } 82 | 83 | hourStr=String.valueOf(hour); 84 | minuteStr=String.valueOf(minute); 85 | if (hour<10){ 86 | hourStr="0"+hour; 87 | } 88 | if (minute<10){ 89 | minuteStr="0"+minute; 90 | } 91 | String timeFormat = year+"年"+monthStr+"月"+dayStr+"日 "+hourStr+":"+minuteStr; 92 | if (onEnsureListener!=null) { 93 | onEnsureListener.onEnsure(timeFormat,year,month,dayOfMonth); 94 | } 95 | cancel(); 96 | break; 97 | } 98 | } 99 | 100 | //隐藏DatePicker头布局 101 | private void hideDatePickerHeader(){ 102 | ViewGroup rootView = (ViewGroup) datePicker.getChildAt(0); 103 | if (rootView == null) { 104 | return; 105 | } 106 | View headerView = rootView.getChildAt(0); 107 | if (headerView == null) { 108 | return; 109 | } 110 | //5.0+ 111 | int headerId = getContext().getResources().getIdentifier("day_picker_selector_layout", "id", "android"); 112 | if (headerId == headerView.getId()) { 113 | headerView.setVisibility(View.GONE); 114 | ViewGroup.LayoutParams layoutParamsRoot = rootView.getLayoutParams(); 115 | layoutParamsRoot.width = ViewGroup.LayoutParams.WRAP_CONTENT; 116 | rootView.setLayoutParams(layoutParamsRoot); 117 | 118 | ViewGroup animator = (ViewGroup) rootView.getChildAt(1); 119 | ViewGroup.LayoutParams layoutParamsAnimator = animator.getLayoutParams(); 120 | layoutParamsAnimator.width = ViewGroup.LayoutParams.WRAP_CONTENT; 121 | animator.setLayoutParams(layoutParamsAnimator); 122 | 123 | View child = animator.getChildAt(0); 124 | ViewGroup.LayoutParams layoutParamsChild = child.getLayoutParams(); 125 | layoutParamsChild.width = ViewGroup.LayoutParams.WRAP_CONTENT; 126 | child.setLayoutParams(layoutParamsChild); 127 | return; 128 | } 129 | 130 | // 6.0+ 131 | headerId = getContext().getResources().getIdentifier("date_picker_header","id","android"); 132 | if (headerId == headerView.getId()) { 133 | headerView.setVisibility(View.GONE); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/a1003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zswyl/Android-course-design/6d057b228e714d0719d629bda9f45be1e66aa112/app/src/main/res/drawable-v24/a1003.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/back_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zswyl/Android-course-design/6d057b228e714d0719d629bda9f45be1e66aa112/app/src/main/res/drawable-v24/back_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/back_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zswyl/Android-course-design/6d057b228e714d0719d629bda9f45be1e66aa112/app/src/main/res/drawable-v24/back_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/go_back_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/iv_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zswyl/Android-course-design/6d057b228e714d0719d629bda9f45be1e66aa112/app/src/main/res/drawable-v24/iv_right_arrow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/register_button_hei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zswyl/Android-course-design/6d057b228e714d0719d629bda9f45be1e66aa112/app/src/main/res/drawable-v24/register_button_hei.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/register_button_lan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zswyl/Android-course-design/6d057b228e714d0719d629bda9f45be1e66aa112/app/src/main/res/drawable-v24/register_button_lan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/register_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/shape_wihte_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/main_morebtn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/main_recordbtn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zswyl/Android-course-design/6d057b228e714d0719d629bda9f45be1e66aa112/app/src/main/res/drawable/search.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 18 | 26 | 27 | 28 | 33 | 34 | 42 | 43 | 51 | 52 | 60 | 61 | 62 | 63 | 67 | 72 | 73 | 81 | 82 | 90 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 17 | 24 | 32 | 33 | 37 | 42 | 49 | 50 | 57 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 37 | 38 | 55 | 56 | 63 | 64 |