温馨提示:这篇文章已超过367天没有更新,请注意相关的内容是否还可用!
摘要:Android Studio成功实现了一款多功能且简单易用的小熊记账本。该应用具备记账、预算管理、账单查询与分析等核心功能,操作简便直观,适合各类用户群体使用。其设计理念在于为用户提供便捷、高效的记账体验,帮助用户轻松管理财务,实现财务自由。
🍅文章末尾有获取完整项目源码方式🍅
目录
前言
一、运行演示
二、开发环境
三、完成步骤
步骤 1:创建项目
步骤 2:创建包名
步骤 3:实现启动页
步骤 5:实现用户注册
步骤 6:实现用户登录
步骤 7:实现主页面编写
步骤 8:记账页面编写
步骤 9:历史记录页面编写
步骤10:我的页面的编写
步骤11:账单搜索页面的编写
步骤12:统计页面的编写
四、获取源码
前言
本次实现的Android Studio 小熊记账本 (功能多,简单)项目,核心功能是可以记录收支情况,可以给收支选择各种分类选项,比如“餐饮”、“零食”、“购物”等等,还可以添加备注和修改日期。然后会在首页展示你的本月支持和收入信息,还可以选择隐藏信息保护隐私。通过【账单记录】可以查看自己的所有账单记录,通过【账单详情】可以看到用柱状图显示的账单情况,在设置里面可以清空所有数据,长按可以删除单条数据,功能非常全面丰富。
一、运行演示
我们先来看下运行演示效果
Android Studio 实现小熊记账本App
二、开发环境
我的开发环境如下,大家的AS版本不需要和我相同,只要是近两年从官网下载的版本,都是比4.0.0 (2020)高的,是可以满足运行和开发要求的。
三、完成步骤
步骤 1:创建项目
打开 Android studio 开发工具后,进行项目创建,左上角 File—>New Project、填写后点击 Finish 完成创建!
步骤 2:创建包名
选中com.example.note包 名 右 键 New — >package 并按需求依次 activity(存放各类 Activity)、adapter(存放各类适配器) 等包名,后续代码将按对应包名去创建,并将 MainActivity.java 移动到 activity包 下
步骤 3:实现启动页
在 activity包上右键创建 New—>Activity—>Empty Activity 选项创建 Activity 后弹 出对话框,输入相关信息,即可创建 Activity.
启动页页面布局背景放置一张自己喜欢的logo即可
这里我们直接看java部分代码:
package com.example.tallybook.Activity; import android.content.Intent; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; import androidx.appcompat.app.AppCompatActivity; import com.example.tallybook.R; public class StartActivity extends AppCompatActivity { private Handler handler = new Handler(); private Runnable runnable = new Runnable() { @Override public void run() { tomainActive(); } }; // 进入主页面 private void tomainActive() { startActivity(new Intent(this, LoginActivity.class)); // 跳转完成后注销 finish(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_start); } }
步骤 5:实现用户注册
在 activity包上右键创建 New—>Activity—>Empty Activity 选项创建 Activity 后弹 出对话框,输入相关信息,即可创建 Activity.
用户注册页面布局代码如下所示:
编写 RegisterActivity.java 的代码为:
package com.example.tallybook.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.example.tallybook.Data.DatabaseHelper; import com.example.tallybook.R; public class RegisterActivity extends AppCompatActivity { private EditText mUserNameEditText; private EditText mPasswordEditText,mRePasswordEditText; private TextView tvLogin; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); mUserNameEditText = findViewById(R.id.username_edittext); mPasswordEditText = findViewById(R.id.password_edittext); mRePasswordEditText = findViewById(R.id.repassword_edittext); tvLogin = findViewById(R.id.tv_login); // 跳转登陆页面 tvLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(RegisterActivity.this, LoginActivity.class); startActivity(intent); finish(); } }); Button registerButton = findViewById(R.id.register_button); registerButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 获取输入的账号密码 String username = mUserNameEditText.getText().toString().trim(); String password = mPasswordEditText.getText().toString().trim(); String repassword = mRePasswordEditText.getText().toString().trim(); if (username.isEmpty() || password.isEmpty()) { Toast.makeText(getApplicationContext(), "请输入账号或密码", Toast.LENGTH_SHORT).show(); return; } if (!password.equals(repassword)) { Toast.makeText(getApplicationContext(), "密码不一致,请重新输入", Toast.LENGTH_SHORT).show(); return; } boolean result = mDatabaseHelper.insertData(username, password); if (result) { Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(RegisterActivity.this, LoginActivity.class); startActivity(intent); finish(); } else { Toast.makeText(getApplicationContext(), "注册失败", Toast.LENGTH_SHORT).show(); } } }); } }
步骤 6:实现用户登录
在 activity包上右键创建 New—>Activity—>Empty Activity 选项的对话框下输入 LoginActivity 创建,同时会在 res-layout 生成 activity_login.xml 文件.
activity_login.xml页面代码如下所示L:
对应的Java页面代码如下所示:
package com.example.tallybook.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.example.tallybook.Data.DatabaseHelper; import com.example.tallybook.R; public class LoginActivity extends AppCompatActivity { private EditText mUserNameEditText; private EditText mPasswordEditText; private Button mLoginButton; private TextView rEgisterButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); mUserNameEditText = findViewById(R.id.username_edittext); mPasswordEditText = findViewById(R.id.password_edittext); mLoginButton = findViewById(R.id.login_button); rEgisterButton = findViewById(R.id.register_button); // 跳转注册页面 rEgisterButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(LoginActivity.this, RegisterActivity.class); startActivity(intent); finish(); } }); // 登陆验证并跳转主页面 mLoginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 获取输入的账号密码 String username = mUserNameEditText.getText().toString().trim(); String password = mPasswordEditText.getText().toString().trim(); if (username.isEmpty() || password.isEmpty()) { Toast.makeText(getApplicationContext(), "请输入账号或密码", Toast.LENGTH_SHORT).show(); return; } boolean result = mDatabaseHelper.checkUser(username, password); if (result) { Toast.makeText(getApplicationContext(), "登陆成功", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(LoginActivity.this, MainActivity.class); startActivity(intent); finish(); } else { Toast.makeText(getApplicationContext(), "账号或密码错误", Toast.LENGTH_SHORT).show(); } } }); } }
编译代码启动 App,在登录页面(LoginActivity)的注册按钮中点击跳转注册 页面(RegisterActivity)进行注册,注册成功后自动返回登录页面进行登录 操作,登录成功之后正常跳转主页面(MainActivity)。
步骤 7:实现主页面编写
我们先来看activity_main.xml代码,详情布局代码如下所示:
接下来我们看逻辑代码,这里我们实现的是页面跳转功能,详情代码如下所示:
package com.example.tallybook.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import com.example.tallybook.R; public class MainActivity extends AppCompatActivity { private ImageView imgHome; private ImageView imgRecords; private ImageView imgBill; private ImageView imgMine; private TextView tvHome; private TextView tvRecords; private TextView tvBill; private TextView tvMine; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); Navigation(); imgHome.callOnClick();//进入页面默认点击首页 } // 点击控件进行页面转换 private void Navigation() { // 首页 imgHome.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); // 记账页面 imgRecords.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); // 历史账单页面 imgBill.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); // 我的页面 imgMine.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); } } private void initView() { imgHome = findViewById(R.id.img_home); imgRecords = findViewById(R.id.img_records); imgBill = findViewById(R.id.img_bill); imgMine = findViewById(R.id.img_mine); tvHome = findViewById(R.id.tv_home); tvRecords = findViewById(R.id.tv_records); tvBill = findViewById(R.id.tv_bill); tvMine = findViewById(R.id.tv_mine); } }
步骤 8:记账页面编写
我们先来看布局代码,这里我们用到了ViewPAge列表来显示,详情代码如下所示:
然后我们进行逻辑代码的编写,实现显示添加支出收入记录功能
package com.example.tallybook.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.viewpager.widget.ViewPager; import com.example.tallybook.Adapter.RecordPagerAdapter; import com.google.android.material.tabs.TabLayout; import com.example.tallybook.R; import java.util.ArrayList; import java.util.List; public class RecordsFragment extends Fragment { private TabLayout tabLayout; private ViewPager viewPager; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_records, container, false); //1.查找控件 tabLayout = view.findViewById(R.id.record_tabs); viewPager = view.findViewById(R.id.record_vp); //2.设置ViewPager加载页面 initPager(); return view; } private void initPager() { // 创建适配器 RecordPagerAdapter pagerAdapter = new RecordPagerAdapter(getChildFragmentManager(), fragmentList); // 设置适配器 viewPager.setAdapter(pagerAdapter); //将TabLayout和ViwePager进行关联 tabLayout.setupWithViewPager(viewPager); } }
步骤 9:历史记录页面编写
这里直使用listview列表显示内容:
然后对应的逻辑代码如下所示:
package com.example.tallybook.Fragment; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.example.tallybook.R; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.example.tallybook.Adapter.AccountAdapter; import com.example.tallybook.Bean.AccountBean; import com.example.tallybook.Data.DBManager; import com.example.tallybook.utils.CalendarDialog; import java.util.ArrayList; import java.util.Calendar; import java.util.List; public class BillFragment extends Fragment { ListView historyLv; TextView timeTv; private ImageView riliIv; List mDatas; AccountAdapter adapter; int year, month; int dialogSelPos = -1; int dialogSelMonth = -1; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_bill, container, false); historyLv = view.findViewById(R.id.history_lv); timeTv = view.findViewById(R.id.history_tv_time); riliIv = view.findViewById(R.id.history_iv_rili); mDatas = new ArrayList(); // 设置适配器 adapter = new AccountAdapter(getActivity(), mDatas); historyLv.setAdapter(adapter); initTime(); timeTv.setText(year + "年" + month + "月"); loadData(year, month); setLVClickListener(); return view; } /*设置ListView每一个item的长按事件*/ private void setLVClickListener() { historyLv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { AccountBean accountBean = mDatas.get(position); deleteItem(accountBean); return false; } }); } /* 获取指定年份月份收支情况的列表*/ private void loadData(int year, int month) { List list = DBManager.getAccountListOneMonthFromAccounttb(year, month); mDatas.clear(); mDatas.addAll(list); adapter.notifyDataSetChanged(); } private void initTime() { Calendar calendar = Calendar.getInstance(); year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH) + 1; } }
步骤10:我的页面的编写
页面布局代码如下所示:
MineFragment是一个用于显示用户个人信息和提供个人设置功能的Android Fragment类。它包含了清空账单、搜索账单、账单统计、设置预算、修改密码和退出软件等功能。
通过点击不同的按钮,用户可以执行相应的操作,例如删除所有记录、跳转到搜索账单界面、跳转到账单统计界面、设置预算金额、修改密码和退出软件。此外,MineFragment还使用了DatabaseHelper类和SharedPreferences类来进行数据库操作和存储预算金额。
package com.example.tallybook.Fragment; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.Toast; import androidx.fragment.app.Fragment; import com.example.tallybook.Activity.LoginActivity; import com.example.tallybook.Activity.SearchActivity; import com.example.tallybook.Activity.StatisticsActivity; import com.example.tallybook.Data.DBManager; import com.example.tallybook.Data.DatabaseHelper; import com.example.tallybook.R; import com.example.tallybook.utils.BudgetDialog; public class MineFragment extends Fragment { private LinearLayout llEdit, llChangePassword, llStatistics, llClear, llSs, llBudget; private DatabaseHelper mDatabaseHelper; SharedPreferences preferences; int year,month,day; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_mine, container, false); initView(view); clear(); ss(); statistics(); budget(); changePassword(); edit(); mDatabaseHelper = new DatabaseHelper(getContext()); preferences = getActivity().getSharedPreferences("budget", Context.MODE_PRIVATE); return view; } // 清空账单 private void clear() { llClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle("清空提示:") .setMessage("您确定要删除所有记录么?\n* 删除后无法恢复,请慎重选择!") .setPositiveButton("取消", null) .setNegativeButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { DBManager.deleteAllAccount(); preferences.edit().clear().apply(); Toast.makeText(getActivity(), "删除成功!", Toast.LENGTH_SHORT).show(); } }); builder.create().show(); } }); } // 搜索账单 private void ss() { llSs.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent it = new Intent(getActivity(), SearchActivity.class); //跳转界面 startActivity(it); } }); } // 账单统计 private void statistics() { llStatistics.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getActivity(), StatisticsActivity.class); startActivity(intent); } }); } private void initView(View view) { llClear = view.findViewById(R.id.ll_clear); llStatistics = view.findViewById(R.id.ll_statistics); llChangePassword = view.findViewById(R.id.ll_changePassword); llEdit = view.findViewById(R.id.ll_edit); llSs = view.findViewById(R.id.ll_ss); llBudget = view.findViewById(R.id.ll_budget); } }
步骤11:账单搜索页面的编写
这个页面比较简单,使用listview列表和数据库查询显示完成,我们先来看布局文件代码
通过用户输入关键词进行搜索,并将搜索结果显示在ListView中。该类使用了DBManager类来进行数据库操作,并使用了AccountAdapter类来显示搜索结果。通过点击不同的按钮,用户可以执行返回和搜索操作。
package com.example.tallybook.Activity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.example.tallybook.Adapter.AccountAdapter; import com.example.tallybook.Bean.AccountBean; import com.example.tallybook.Data.DBManager; import com.example.tallybook.R; import java.util.ArrayList; import java.util.List; public class SearchActivity extends AppCompatActivity { ListView searchLv; EditText searchEt; TextView emptyTv; List mDatas; //数据源 AccountAdapter adapter; //适配器对象 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search); initView(); searchLv.setEmptyView(emptyTv); //设置无数局时,显示的控件 } private void initView() { searchEt = findViewById(R.id.search_et); searchLv = findViewById(R.id.search_lv); emptyTv = findViewById(R.id.search_tv_empty); } }
步骤12:统计页面的编写
这里我们还是先进行页面布局对的编写
该活动包含了收入和支出的按钮、日期显示、统计数据显示以及ViewPager等控件。通过点击不同的按钮,用户可以切换显示收入或支出的统计数据。该活动还包含了初始化控件、初始化时间、初始化Fragment、统计数据的初始化和显示、返回按钮的点击事件、显示日历对话框等方法。通过使用DBManager类进行数据库操作,获取收入和支出的统计数据,并使用ChartVPAdapter适配器类将Fragment添加到ViewPager中进行显示。用户可以通过点击日历图标选择不同的日期进行统计。
package com.example.tallybook.Activity; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.viewpager.widget.ViewPager; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import com.example.tallybook.Adapter.ChartVPAdapter; import com.example.tallybook.Data.DBManager; import com.example.tallybook.Fragment.IncomChartFragment; import com.example.tallybook.Fragment.OutcomChartFragment; import com.example.tallybook.R; import com.example.tallybook.utils.CalendarDialog; import java.util.ArrayList; import java.util.Calendar; import java.util.List; public class StatisticsActivity extends AppCompatActivity { Button inBtn, outBtn; TextView dateTv, inTv, outTv; ViewPager chartVp; int year; int month; int selectPos = -1, selectMonth = -1; List chartFragList; private IncomChartFragment incomChartFragment; private OutcomChartFragment outcomChartFragment; private ChartVPAdapter chartVPAdapter; private ImageView chartIV, chartBack; private float inMoneyOneMonth, outMoneyOneMonth; private int incountItemOneMonth, outcountItemOneMonth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_statistics); initView(); initTime(); } // 显示日历 private void rili() { chartIV.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showCalendarDialog(); } }); } // 返回 private void back() { chartBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } private void setVPSelectListener() { chartVp.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { setButtonStyle(position); } }); } /* 统计某年某月的收支情况数据*/ private void initStatistics(int year, int month) { inMoneyOneMonth = DBManager.getSumMoneyOneMonth(year, month, 1); //收入总钱数 outMoneyOneMonth = DBManager.getSumMoneyOneMonth(year, month, 0); //支出总钱数 incountItemOneMonth = DBManager.getCountItemOneMonth(year, month, 1); //收入多少笔 outcountItemOneMonth = DBManager.getCountItemOneMonth(year, month, 0); //支出多少笔 dateTv.setText(year + "年" + month + "月账单统计"); // 收入 inBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setButtonStyle(1); chartVp.setCurrentItem(1); outTv.setText("共收入" + incountItemOneMonth + "笔,合计"); inTv.setText(String.valueOf(inMoneyOneMonth)); } }); // 支出 outBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setButtonStyle(0); chartVp.setCurrentItem(0); outTv.setText("共支出" + outcountItemOneMonth + "笔支出,合计"); inTv.setText(String.valueOf(outMoneyOneMonth)); } }); } /** * 初始化时间的方法 */ private void initTime() { Calendar calendar = Calendar.getInstance(); year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH) + 1; } /** * 初始化控件 */ private void initView() { inBtn = findViewById(R.id.chart_btn_in); outBtn = findViewById(R.id.chart_btn_out); dateTv = findViewById(R.id.chart_tv_date); inTv = findViewById(R.id.chart_tv_in); outTv = findViewById(R.id.chart_tv_out); chartVp = findViewById(R.id.chart_vp); chartIV = findViewById(R.id.chart_iv_rili); chartBack = findViewById(R.id.chart_iv_back); } /* 设置按钮样式的改变 支出-0 收入-1*/ private void setButtonStyle(int kind) { if (kind == 0) { outBtn.setBackgroundResource(R.drawable.main_recordbtn_bg); outBtn.setTextColor(Color.WHITE); inBtn.setBackgroundResource(R.drawable.dialog_btn_bg); inBtn.setTextColor(Color.BLACK); } else if (kind == 1) { inBtn.setBackgroundResource(R.drawable.main_recordbtn_bg); inBtn.setTextColor(Color.WHITE); outBtn.setBackgroundResource(R.drawable.dialog_btn_bg); outBtn.setTextColor(Color.BLACK); } } }
至此,完整的小熊记账本项目就创建完成了。
四、获取源码
关注公众号《编程乐学》,后台回复:24010601
👇🏻👇🏻👇🏻快捷获取方式👇🏻👇🏻👇🏻
还没有评论,来说两句吧...