目录
一、项目测试视频
网络资源模板--基于Android Studio 简约记账本
二、项目简介
记账本项目,核心功能是可以记录收支情况,可以给收支选择各种分类选项,比如“餐饮"、“零食”、“购物"等等,还可以添加备注和修改日期。然后会在首页展示你的本月支持和收入信息,还可以选择隐藏信息保护隐私。通过【账单记录】可以查看自己的所有账单记录,通过【账单详情】可以看到用 柱状图Q 显示的账单情况,在设置里面可以清空所有数据,长按可以删除单条数据,功能非常全面丰富。
三、项目测试环境
四、项目详情设计
1.首页
1、运行项目,进入主页,我们可以看到这里有本月支持的金额,和本月收入的金额,下面还有今日支出和收入信息,右下角是记账的入口,和一个菜单选项,右上角是搜索按钮。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey_f3f3f3">
<RelativeLayout
android:id="@+id/main_top_layout"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:text="@string/app_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:padding="10dp"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="@color/black"/>
<ImageView
android:id="@+id/main_iv_search"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@mipmap/search"
android:layout_alignParentRight="true"
android:padding="10dp"/>
</RelativeLayout>
<ListView
android:id="@+id/main_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/main_top_layout"
android:padding="10dp"
android:divider="@null"
android:dividerHeight="6dp"
android:scrollbars="none"
android:background="@color/grey_f3f3f3"/>
<ImageButton
android:id="@+id/main_btn_more"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/more"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:background="@drawable/main_morebtn_bg"/>
<Button
android:id="@+id/main_btn_edit"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_alignBottom="@id/main_btn_more"
android:background="@drawable/main_recordbtn_bg"
android:layout_toLeftOf="@id/main_btn_more"
android:text="@string/editone"
android:textStyle="bold"
android:textColor="@color/white"
android:drawableLeft="@mipmap/edit"
android:gravity="center_vertical"/>
</RelativeLayout>
package com.hui.tally;
import androidx.appcompat.app.AppCompatActivity;
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.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.hui.tally.adapter.AccountAdapter;
import com.hui.tally.db.AccountBean;
import com.hui.tally.db.DBManager;
import com.hui.tally.utils.BudgetDialog;
import com.hui.tally.utils.MoreDialog;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Set;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ListView todayLv; //展示今日收支情况的ListView
ImageView searchIv;
Button editBtn;
ImageButton moreBtn;
//声明数据源
List<AccountBean>mDatas;
AccountAdapter adapter;
int year,month,day;
//头布局相关控件
View headerView;
TextView topOutTv,topInTv,topbudgetTv,topConTv;
ImageView topShowIv;
SharedPreferences preferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTime();
initView();
preferences = getSharedPreferences("budget", Context.MODE_PRIVATE);
//添加ListView的头布局
addLVHeaderView();
mDatas = new ArrayList<>();
//设置适配器:加载每一行数据到列表当中
adapter = new AccountAdapter(this, mDatas);
todayLv.setAdapter(adapter);
}
/** 初始化自带的View的方法*/
private void initView() {
todayLv = findViewById(R.id.main_lv);
editBtn = findViewById(R.id.main_btn_edit);
moreBtn = findViewById(R.id.main_btn_more);
searchIv = findViewById(R.id.main_iv_search);
editBtn.setOnClickListener(this);
moreBtn.setOnClickListener(this);
searchIv.setOnClickListener(this);
setLVLongClickListener();
}
/** 设置ListView的长按事件*/
private void setLVLongClickListener() {
todayLv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) { //点击了头布局
return false;
}
int pos = position-1;
AccountBean clickBean = mDatas.get(pos); //获取正在被点击的这条信息
//弹出提示用户是否删除的对话框
showDeleteItemDialog(clickBean);
return false;
}
});
}
/* 弹出是否删除某一条记录的对话框*/
private void showDeleteItemDialog(final AccountBean clickBean) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("提示信息").setMessage("您确定要删除这条记录么?")
.setNegativeButton("取消",null)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int click_id = clickBean.getId();
//执行删除的操作
DBManager.deleteItemFromAccounttbById(click_id);
mDatas.remove(clickBean); //实时刷新,移除集合当中的对象
adapter.notifyDataSetChanged(); //提示适配器更新数据
setTopTvShow(); //改变头布局TextView显示的内容
}
});
builder.create().show(); //显示对话框
}
/** 给ListView添加头布局的方法*/
private void addLVHeaderView() {
//将布局转换成View对象
headerView = getLayoutInflater().inflate(R.layout.item_mainlv_top, null);
todayLv.addHeaderView(headerView);
//查找头布局可用控件
topOutTv = headerView.findViewById(R.id.item_mainlv_top_tv_out);
topInTv = headerView.findViewById(R.id.item_mainlv_top_tv_in);
topbudgetTv = headerView.findViewById(R.id.item_mainlv_top_tv_budget);
topConTv = headerView.findViewById(R.id.item_mainlv_top_tv_day);
topShowIv = headerView.findViewById(R.id.item_mainlv_top_iv_hide);
topbudgetTv.setOnClickListener(this);
headerView.setOnClickListener(this);
topShowIv.setOnClickListener(this);
}
/* 获取今日的具体时间*/
private void initTime() {
Calendar calendar = Calendar.getInstance();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH)+1;
day = calendar.get(Calendar.DAY_OF_MONTH);
}
// 当activity获取焦点时,会调用的方法
@Override
protected void onResume() {
super.onResume();
loadDBData();
setTopTvShow();
}
/* 设置头布局当中文本内容的显示*/
private void setTopTvShow() {
//获取今日支出和收入总金额,显示在view当中
float incomeOneDay = DBManager.getSumMoneyOneDay(year, month, day, 1);
float outcomeOneDay = DBManager.getSumMoneyOneDay(year, month, day, 0);
String infoOneDay = "今日支出 ¥"+outcomeOneDay+" 收入 ¥"+incomeOneDay;
topConTv.setText(infoOneDay);
// 获取本月收入和支出总金额
float incomeOneMonth = DBManager.getSumMoneyOneMonth(year, month, 1);
float outcomeOneMonth = DBManager.getSumMoneyOneMonth(year, month, 0);
topInTv.setText("¥"+incomeOneMonth);
topOutTv.setText("¥"+outcomeOneMonth);
// 设置显示运算剩余
float bmoney = preferences.getFloat("bmoney", 0);//预算
if (bmoney == 0) {
topbudgetTv.setText("¥ 0");
}else{
float syMoney = bmoney-outcomeOneMonth;
topbudgetTv.setText("¥"+syMoney);
}
}
// 加载数据库数据
private void loadDBData() {
List<AccountBean> list = DBManager.getAccountListOneDayFromAccounttb(year, month, day);
mDatas.clear();
mDatas.addAll(list);
adapter.notifyDataSetChanged();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.main_iv_search:
Intent it = new Intent(this, SearchActivity.class); //跳转界面
startActivity(it);
break;
case R.id.main_btn_edit:
Intent it1 = new Intent(this, RecordActivity.class); //跳转界面
startActivity(it1);
break;
case R.id.main_btn_more:
MoreDialog moreDialog = new MoreDialog(this);
moreDialog.show();
moreDialog.setDialogSize();
break;
case R.id.item_mainlv_top_tv_budget:
showBudgetDialog();
break;
case R.id.item_mainlv_top_iv_hide:
// 切换TextView明文和密文
toggleShow();
break;
}
if (v == headerView) {
//头布局被点击了
Intent intent = new Intent();
intent.setClass(this, MonthChartActivity.class);
startActivity(intent);
}
}
/** 显示运算设置对话框*/
private void showBudgetDialog() {
BudgetDialog dialog = new BudgetDialog(this);
dialog.show();
dialog.setDialogSize();
dialog.setOnEnsureListener(new BudgetDialog.OnEnsureListener() {
@Override
public void onEnsure(float money) {
//将预算金额写入到共享参数当中,进行存储
SharedPreferences.Editor editor = preferences.edit();
editor.putFloat("bmoney",money);
editor.commit();
//计算剩余金额
float outcomeOneMonth = DBManager.getSumMoneyOneMonth(year, month, 0);
float syMoney = money-outcomeOneMonth;//预算剩余 = 预算-支出
topbudgetTv.setText("¥"+syMoney);
}
});
}
boolean isShow = true;
/**
* 点击头布局眼睛时,如果原来是明文,就加密,如果是密文,就显示出来
* */
private void toggleShow() {
if (isShow) { //明文====》密文
PasswordTransformationMethod passwordMethod = PasswordTransformationMethod.getInstance();
topInTv.setTransformationMethod(passwordMethod); //设置隐藏
topOutTv.setTransformationMethod(passwordMethod); //设置隐藏
topbudgetTv.setTransformationMethod(passwordMethod); //设置隐藏
topShowIv.setImageResource(R.mipmap.ih_hide);
isShow = false; //设置标志位为隐藏状态
}else{ //密文---》明文
HideReturnsTransformationMethod hideMethod = HideReturnsTransformationMethod.getInstance();
topInTv.setTransformationMethod(hideMethod); //设置隐藏
topOutTv.setTransformationMethod(hideMethod); //设置隐藏
topbudgetTv.setTransformationMethod(hideMethod); //设置隐藏
topShowIv.setImageResource(R.mipmap.ih_show);
isShow = true; //设置标志位为隐藏状态
}
}
}
2.账单详情
3.搜索账单
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/grey_f3f3f3">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/search_iv_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:onClick="onClick"
android:layout_marginLeft="10dp"
android:src="@mipmap/it_back"/>
<EditText
android:id="@+id/search_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/search_iv_back"
android:background="@drawable/dialog_btn_bg"
android:layout_centerVertical="true"
android:textSize="16sp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:layout_marginLeft="10dp"
android:hint="@string/please_search_info">
<requestFocus/>
</EditText>
<ImageView
android:id="@+id/search_iv_sh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/search"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="20dp"
android:onClick="onClick"/>
</RelativeLayout>
<ListView
android:id="@+id/search_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="6dp"
android:divider="@color/grey_f3f3f3"
/>
<TextView
android:id="@+id/search_tv_empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/date_empty"
android:gravity="center"
android:textSize="20sp"
android:drawableTop="@mipmap/it_searchtext"
android:layout_marginTop="250dp"/>
</LinearLayout>
package com.hui.tally;
import androidx.appcompat.app.AppCompatActivity;
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 com.hui.tally.adapter.AccountAdapter;
import com.hui.tally.db.AccountBean;
import com.hui.tally.db.DBManager;
import java.util.ArrayList;
import java.util.List;
public class SearchActivity extends AppCompatActivity {
ListView searchLv;
EditText searchEt;
TextView emptyTv;
List<AccountBean>mDatas; //数据源
AccountAdapter adapter; //适配器对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
initView();
mDatas = new ArrayList<>();
adapter = new AccountAdapter(this,mDatas);
searchLv.setAdapter(adapter);
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);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.search_iv_back:
finish();
break;
case R.id.search_iv_sh: //执行搜索的操作
String msg = searchEt.getText().toString().trim();
// 判断输入内容是否为空,如果为空,就提示不能搜索
if (TextUtils.isEmpty(msg)) {
Toast.makeText(this,"输入内容不能为空!",Toast.LENGTH_SHORT).show();
return;
}
//开始搜索
List<AccountBean> list = DBManager.getAccountListByRemarkFromAccounttb(msg);
mDatas.clear();
mDatas.addAll(list);
adapter.notifyDataSetChanged();
break;
}
}
}
4.设置页面
5.记账页面
package com.hui.tally;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
import android.view.View;
import com.google.android.material.tabs.TabLayout;
import com.hui.tally.adapter.RecordPagerAdapter;
import com.hui.tally.frag_record.IncomeFragment;
import com.hui.tally.frag_record.BaseRecordFragment;
import com.hui.tally.frag_record.OutcomeFragment;
import java.util.ArrayList;
import java.util.List;
public class RecordActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record);
//1.查找控件
tabLayout = findViewById(R.id.record_tabs);
viewPager = findViewById(R.id.record_vp);
//2.设置ViewPager加载页面
initPager();
}
private void initPager() {
// 初始化ViewPager页面的集合
List<Fragment>fragmentList = new ArrayList<>();
// 创建收入和支出页面,放置在Fragment当中
OutcomeFragment outFrag = new OutcomeFragment(); //支出
IncomeFragment inFrag = new IncomeFragment(); //收入
fragmentList.add(outFrag);
fragmentList.add(inFrag);
// 创建适配器
RecordPagerAdapter pagerAdapter = new RecordPagerAdapter(getSupportFragmentManager(), fragmentList);
// 设置适配器
viewPager.setAdapter(pagerAdapter);
//将TabLayout和ViwePager进行关联
tabLayout.setupWithViewPager(viewPager);
}
/* 点击事件*/
public void onClick(View view) {
switch (view.getId()) {
case R.id.record_iv_back:
finish();
break;
}
}
}
Get 项目模板源码
👇👇👇快捷获取方式👇👇👇