『江鸟中原』——鸿蒙记账本

wx657594e1db1d7
发布于 2023-12-11 15:23
浏览
2收藏

我是中原工学院的何紫莹,这是我的鸿蒙结课大作业,以下是我的作业报告。
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();
        }
    }
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.

并改变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();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.

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();
        }
    };
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.

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;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.

8.引导页效果展示
『江鸟中原』——鸿蒙记账本-鸿蒙开发者社区
『江鸟中原』——鸿蒙记账本-鸿蒙开发者社区
『江鸟中原』——鸿蒙记账本-鸿蒙开发者社区
『江鸟中原』——鸿蒙记账本-鸿蒙开发者社区
9.总结
一个项目的开发,开发过程中搭建框架是非常重要的,框架搭建的越好,后期的功能开发越来越轻松

标签
收藏 2
回复
举报
2


回复
    相关推荐