『江鸟中原』——鸿蒙记账本
我是中原工学院的何紫莹,这是我的鸿蒙结课大作业,以下是我的作业报告。
1. 介绍
《记账软件》是日常生活中每天都要使用的软件,通过软件来统计和规划每天的收入和支出情况,并根据日,周,月,年的数据进行生成图表,折线图,柱状图等等,并对消费情况进行分析给出合理的规划策略。
实现思路:
创建Java语言的项目,完成欢迎引导页滑动页面
创建登录页面,注册页面,找回密码页面
创建主界面,包含明细,图表,记账,发现,我的五大模块
明细模块:展示每天的收入支出情况,并可以根据月份统计本月,本日的收入支出的总和等功能
图表模块:根据收入支出情况生成日,周,月,年的折线图,饼状图,折线图等等,并对各种支出情况分类显示支出金额
记账模块:对消费的情况按不同分类进行记账,例如水果,公交,餐饮,工资等等
发现模块:这里接入web端的网站展示在移动端中
我的模块:对用户个人信息的设置和显示,头像,VIP设置,主题设置,提醒等等功能
2. 搭建HarmonyOS环境
首先需要完成HarmonyOS开发环境搭建
3. 搭建项目开发架构
在鸿蒙系统项目中,一个项目只会存在一个Application类作为管理整个软件的应用程序。代码如下:
package com.example.bookkeepproject;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.AbilityPackage;
import java.util.ArrayList;
import java.util.List;
/**
* 主应用程序类,一个应用只有一个应用程序类
*/
public class MyApplication extends AbilityPackage {
private static List<Ability> abilities;
@Override
public void onInitialize() {
super.onInitialize();
abilities=new ArrayList<>();
}
/**
* 将开启的界面添加至界面集合
* @param ability
*/
public void addAbility(Ability ability) {
if (!abilities.contains(ability)) {
abilities.add(ability);
}
}
/**
* 销毁所有的界面对象
*/
public void removeAllAbility() {
for (Ability activity : abilities) {
activity.terminateAbility();
}
}
}
4.创建Ability类的基类
为了更好的统一管理所有的ability,建立BaseAbility(基类)继承至Ability类,那么所有的Ability都继承至自己的基类,在基类中可以定义封装常用的方法,方便调用,减少耦合度,避免代码冗余。代码如下:
package com.example.bookkeepproject;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
/**
* 界面基类
*/
public class BaseAbility extends Ability {
MyApplication application;
BaseAbility context;
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
// 单例模式
if (application == null) {
application = (MyApplication) getAbilityPackage();
}
context = this;
addAbility();
}
@Override
protected void onStop() {
super.onStop();
}
public void addAbility() {
application.addAbility(context);
}
public void removeAllActivity() {
application.removeAllAbility();
}
}
并改变MainAbility类继承至BaseAbility类,完成统一所有Ability的管理,统一监听其生命周期过程。
5.创建AbilitySlice基类
package com.example.bookkeepproject.slice;
import com.example.bookkeepproject.MainAbility;
import com.example.bookkeepproject.utils.MyHelper;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.window.dialog.ToastDialog;
import ohos.data.rdb.RdbStore;
import java.text.SimpleDateFormat;
import java.util.Calendar;
/**
* 子界面的基类
*/
public class BaseAbilitySlice extends AbilitySlice {
MainAbility ability;
BaseAbilitySlice context;
RdbStore rs;
// Preferences preferences;
public Calendar calendar = null;
public int year=Calendar.getInstance().get(Calendar.YEAR);
public int month=Calendar.getInstance().get(Calendar.MONTH)+1;
public int day=Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
public String[] months = { "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月",
"9月", "10月", "11月", "12月" };
public String[] types={"支出","收入","转账","余额"};
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
// 单例模式
if (ability == null) {
ability = (MainAbility) getAbility();
}
context = this;
// addAbilitySlice();
if (calendar == null) {
calendar = Calendar.getInstance();
}
if (rs==null)
rs= MyHelper.getInstance(getContext(),"BookKeep");
// if (preferences==null)
// preferences= MyHelper.getInstance("BKInfo",getContext());
//
// // 向preferences实例注册观察者
// PreferencesObserverImpl observer = new PreferencesObserverImpl();
// preferences.registerObserver(observer);
}
// private class PreferencesObserverImpl implements Preferences.PreferencesObserver {
//
// @Override
// public void onChange(Preferences preferences, String key) {
// if ("intKey".equals(key)) {
// showToastDialogShort("添加了key重复了");
// }
// }
// }
/**
* 获得实时的年月日时分秒
* @return
*/
public static String getDate() {
Calendar ca = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
String date = sdf.format(ca.getTimeInMillis());
return date;
}
/**
* 获得实时的年月日
* @return
*/
public static String getDate1() {
Calendar ca = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = sdf.format(ca.getTimeInMillis());
return date;
}
public void addAbilitySlice() {
ability.addAbilitySlice(context);
}
public void removeAllAbilitySlice() {
ability.removeAllActivity();
}
@Override
protected void onStop() {
super.onStop();
}
public String getWeek() {
String info = null;
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
int count = calendar.get(Calendar.DAY_OF_WEEK) - 1;
if (count > 0) {
info = month + "_" + (day - count + 1) + "_" + month + "_"
+ (day + 7 - count);
}
return info;
}
public String getmonth() {
String info = null;
int month = calendar.get(Calendar.MONTH) + 1;
// 计算是当月的第几天
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
System.out.printf("输入的日期是当月的第%d天\n ", dayOfMonth);
// 计算当月的第一天
calendar.add(Calendar.DATE, 1 - dayOfMonth);
// 计算下月的第一天
calendar.add(Calendar.MONTH, 1);
// 计算当月的最后一天
calendar.add(Calendar.DATE, -1);
// 计算是当月一共几天
dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
System.out.printf("当月一共%d天\n ", dayOfMonth);
info = month + "月" + 1 + "日--" + month + "月" + dayOfMonth + "日";
return info;
}
public String getyear() {
String info = null;
int month = calendar.get(Calendar.MONTH) + 1;
// 计算是当月的第几天
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
System.out.printf("输入的日期是当月的第%d天\n ", dayOfMonth);
// 计算当月的第一天
calendar.add(Calendar.DATE, 1 - dayOfMonth);
// 计算下月的第一天
calendar.add(Calendar.MONTH, 1);
// 计算当月的最后一天
calendar.add(Calendar.DATE, -1);
// 计算是当月一共几天
dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
System.out.printf("当月一共%d天\n ", dayOfMonth);
info = "1月1日--" + month + "月" + dayOfMonth + "日";
return info;
}
/**
* 查看当前月份
* @param month
* @return
*/
public int select_month(int month) {
return (month == 13) ? 1 : (month);
}
/**
* 查看当前天数
* @param month
* @param day
* @return
*/
public String select_day(int month, int day) {
if (day >= 32) {
int months = select_month(month + 1);
return months + "-" + (day % 31);
} else {
return month + "-" + day;
}
}
public void showToastDialogShort(String info){
new ToastDialog(context).setText(info).setDuration(1000).show();
}
public void showToastDialogLong(String info){
new ToastDialog(context).setText(info).setDuration(2000).show();
}
}
6.创建欢迎引导页
在任何一款成熟的软件都具备引导页,完成四页的引导,在第四个引导页之后,进行跳入应用。代码如下:
package com.example.bookkeepproject.slice;
import com.example.bookkeepproject.ResourceTable;
import com.example.bookkeepproject.adapter.LoadingPageAdapter;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.PageSlider;
/**
* 引导页
*/
public class LoadingAbilitySlice extends BaseAbilitySlice {
private PageSlider page;
private LoadingPageAdapter adapter;
private int[] images = {ResourceTable.Media_load_1, ResourceTable.Media_load_2, ResourceTable.Media_load_3, ResourceTable.Media_load_4};
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
this.setUIContent(ResourceTable.Layout_ability_loading);
page = (PageSlider) this.findComponentById(ResourceTable.Id_page);
adapter = new LoadingPageAdapter(images, this);
page.setProvider(adapter);
page.addPageChangedListener(listener);
}
private PageSlider.PageChangedListener listener = new PageSlider.PageChangedListener() {
@Override
public void onPageSliding(int i, float v, int i1) {
}
@Override
public void onPageSlideStateChanged(int i) {
}
@Override
public void onPageChosen(int i) {
if (i == images.length - 1) {
page.setClickedListener(clickedListener);
}
}
};
private Component.ClickedListener clickedListener=new Component.ClickedListener() {
@Override
public void onClick(Component component) {
present(new LoginAbilitySlice(), new Intent());
terminate();
}
};
}
7.创建滑动加载适配器
创建一个adapter包,在包中新建一个LoadingPageAdapter类继承至PageSliderProvider类,并实现未实现的方法,加载图片和动态的创建子布局
package com.example.bookkeepproject.adapter;
import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.PageSliderProvider;
public class LoadingPageAdapter extends PageSliderProvider {
private int[] images;
private AbilitySlice context;
public LoadingPageAdapter(int[] images, AbilitySlice context) {
this.images = images;
this.context = context;
}
@Override
public int getCount() {
return images.length;
}
@Override
public Object createPageInContainer(ComponentContainer componentContainer, int i) {
Image image=new Image(context);
image.setScaleMode(Image.ScaleMode.STRETCH);
ComponentContainer.LayoutConfig config=new ComponentContainer
.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
ComponentContainer.LayoutConfig.MATCH_PARENT);
image.setLayoutConfig(config);
image.setPixelMap(images[i]);
componentContainer.addComponent(image);
return image;
}
@Override
public void destroyPageFromContainer(ComponentContainer componentContainer, int i, Object o) {
//滑出屏幕的组件进行移除
componentContainer.removeComponent((Component) o);
}
@Override
public boolean isPageMatchToObject(Component component, Object o) {
//判断滑页上的每一页的组件和内容是否保持一致
return true;
}
}
8.引导页效果展示
9.总结
一个项目的开发,开发过程中搭建框架是非常重要的,框架搭建的越好,后期的功能开发越来越轻松