文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android App开发实战之实现微信记账本(附源码 超详细必看)

2023-09-09 20:05

关注

需要源码或图片集请点赞关注收藏后评论区留言~~~

好用的记账本必须具备两项基本功能。一项时记录新帐单,另一项时查看账单列表,其中账单的记录操作要求用户输入账单的明细要素,包括账单的发生时间,账单的收支类型,账单的交易金额,账单的事由描述等等,账单通常分月展示,每页显示单个月份的账单数据,还要支持在不同月份之间切换,每月的账单数据按照时间从上往下排列,然后列表末尾展示当月的账单合计情况。

基本界面如下  用户可以自己输入类型,说明以及金额大小

 

除了文本视图,按钮,编辑框,单选按钮等简单控件之外,记账本还用到了下列控件以及相关的适配器  如果读者有疑问可以进我主页查看Android Studio专栏 里面有详细的讲解

Android App专栏

翻页视图

翻页标签栏

碎片适配器

碎片

列表视图

基本适配器

提醒对话框

日期选择对话框

下面列出了活动页面开始直到账单行的依赖嵌套关系(账单总体页面->每个月份的账单页->每月账单的明细列表->每行的账单信息) 

1:如何实现日期下拉框

填写账单时间的时候,输入界面默认展示当天日期,用户若想修改账单时间,就要点击日期文本,此时界面弹出日期选择对话框,等待用户选择完具体日期,再回到主界面展示选定日期的文本

2:如何编辑与删除账单项

因为账单明细位于列表视图当中,且列表视图允许同时设置列表项的点击监听器和长按监听器,所以可考虑将列表项的点击监听器映射到账单的编辑功能。

3:合并账单的添加与编辑功能

保存账单记录之时,也要先判断数据库中是否已经存在对应账单,如果有找到对应的账单记录,那么执行记录更新操作,否则执行记录添加操作。

选择时间页面框

 

查询账单页面框

翻页视图

 

java类代码

添加类代码

package com.example.chapter08;import android.app.DatePickerDialog;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.DatePicker;import android.widget.EditText;import android.widget.RadioButton;import android.widget.RadioGroup;import android.widget.TextView;import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.chapter08.bean.BillInfo;import com.example.chapter08.database.BillDBHelper;import com.example.chapter08.util.DateUtil;import com.example.chapter08.util.ViewUtil;import java.util.Calendar;import java.util.Date;import java.util.List;public class BillAddActivity extends AppCompatActivity implements        RadioGroup.OnCheckedChangeListener, View.OnClickListener, DatePickerDialog.OnDateSetListener {    private final static String TAG = "BillAddActivity";    private TextView tv_date;    private RadioButton rb_income;    private RadioButton rb_expand;    private EditText et_desc;    private EditText et_amount;    private int mBillType = 1; // 账单类型。0 收入;1 支出    private int xuhao; // 如果序号有值,说明已存在该账单    private Calendar calendar = Calendar.getInstance(); // 获取日历实例,里面包含了当前的年月日    private BillDBHelper mBillHelper; // 声明一个账单数据库的帮助器对象    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_bill_add);        TextView tv_title = findViewById(R.id.tv_title);        TextView tv_option = findViewById(R.id.tv_option);        tv_date = findViewById(R.id.tv_date);        RadioGroup rg_type = findViewById(R.id.rg_type);        rb_income = findViewById(R.id.rb_income);        rb_expand = findViewById(R.id.rb_expand);        et_desc = findViewById(R.id.et_desc);        et_amount = findViewById(R.id.et_amount);        tv_title.setText("请填写账单");        tv_option.setText("账单列表");        findViewById(R.id.iv_back).setOnClickListener(this);        tv_option.setOnClickListener(this);        tv_date.setOnClickListener(this);        findViewById(R.id.btn_save).setOnClickListener(this);        rg_type.setOnCheckedChangeListener(this);    }    @Override    protected void onResume() {        super.onResume();        xuhao = getIntent().getIntExtra("xuhao", -1);        mBillHelper = BillDBHelper.getInstance(this); // 获取账单数据库的帮助器对象        if (xuhao != -1) { // 序号有值,就展示数据库里的账单详情            List bill_list = (List) mBillHelper.queryById(xuhao);            if (bill_list.size() > 0) { // 已存在该账单                BillInfo bill = bill_list.get(0); // 获取账单信息                Date date = DateUtil.formatString(bill.date);                Log.d(TAG, "bill.date="+bill.date);                Log.d(TAG, "year="+date.getYear()+",month="+date.getMonth()+",day="+date.getDate());                calendar.set(Calendar.YEAR, date.getYear()+1900);                calendar.set(Calendar.MONTH, date.getMonth());                calendar.set(Calendar.DAY_OF_MONTH, date.getDate());                if (bill.type == 0) { // 收入                    rb_income.setChecked(true);                } else { // 支出                    rb_expand.setChecked(true);                }                et_desc.setText(bill.desc); // 设置账单的描述文本                et_amount.setText(""+bill.amount); // 设置账单的交易金额            }        }        tv_date.setText(DateUtil.getDate(calendar)); // 设置账单的发生时间    }    @Override    public void onClick(View v) {        if (v.getId() == R.id.iv_back) {            finish(); // 关闭当前页面        } else if (v.getId() == R.id.tv_option) {            Intent intent = new Intent(this, BillPagerActivity.class);            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志            startActivity(intent); // 跳到账单列表页面        } else if (v.getId() == R.id.tv_date) {            // 构建一个日期对话框,该对话框已经集成了日期选择器。            // DatePickerDialog的第二个构造参数指定了日期监听器            DatePickerDialog dialog = new DatePickerDialog(this, this,                    calendar.get(Calendar.YEAR), // 年份                    calendar.get(Calendar.MONTH), // 月份                    calendar.get(Calendar.DAY_OF_MONTH)); // 日子            dialog.show(); // 显示日期选择对话框        } else if (v.getId() == R.id.btn_save) {            saveBill(); // 保存账单        }    }    @Override    public void onCheckedChanged(RadioGroup group, int checkedId) {        mBillType = (checkedId==R.id.rb_expand) ? 1 : 0;    }    @Override    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {        calendar.set(Calendar.YEAR, year);        calendar.set(Calendar.MONTH, month);        calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);        tv_date.setText(DateUtil.getDate(calendar));    }    // 保存账单    private void saveBill() {        //ViewUtil.hideAllInputMethod(this); // 隐藏输入法软键盘        ViewUtil.hideOneInputMethod(this, et_amount); // 隐藏输入法软键盘        BillInfo bill = new BillInfo();        bill.xuhao = xuhao;        bill.date = tv_date.getText().toString();        bill.month = 100*calendar.get(Calendar.YEAR) + (calendar.get(Calendar.MONTH)+1);        bill.type = mBillType;        bill.desc = et_desc.getText().toString();        bill.amount = Double.parseDouble(et_amount.getText().toString());        mBillHelper.save(bill); // 把账单信息保存到数据库        Toast.makeText(this, "已添加账单", Toast.LENGTH_SHORT).show();        resetPage(); // 重置页面    }    // 重置页面    private void resetPage() {        calendar = Calendar.getInstance();        et_desc.setText("");        et_amount.setText("");        tv_date.setText(DateUtil.getDate(calendar));    }    }

查看类代码

package com.example.chapter08;import android.app.DatePickerDialog;import android.content.Intent;import android.os.Bundle;import android.util.TypedValue;import android.view.View;import android.widget.DatePicker;import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import androidx.viewpager.widget.PagerTabStrip;import androidx.viewpager.widget.ViewPager;import com.example.chapter08.adapter.BillPagerAdpater;import com.example.chapter08.util.DateUtil;import java.util.Calendar;public class BillPagerActivity extends AppCompatActivity implements        View.OnClickListener, DatePickerDialog.OnDateSetListener, ViewPager.OnPageChangeListener {    private TextView tv_month;    private ViewPager vp_bill; // 声明一个翻页视图对象    private Calendar calendar = Calendar.getInstance(); // 获取日历实例,里面包含了当前的年月日    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_bill_pager);        TextView tv_title = findViewById(R.id.tv_title);        TextView tv_option = findViewById(R.id.tv_option);        tv_month = findViewById(R.id.tv_month);        tv_title.setText("账单列表");        tv_option.setText("添加账单");        findViewById(R.id.iv_back).setOnClickListener(this);        tv_option.setOnClickListener(this);        tv_month.setOnClickListener(this);        tv_month.setText(DateUtil.getMonth(calendar));        // 从布局视图中获取名叫vp_bill的翻页视图        vp_bill = findViewById(R.id.vp_bill);        initViewPager(); // 初始化翻页视图    }    @Override    public void onClick(View v) {        if (v.getId() == R.id.iv_back) {            finish(); // 关闭当前页面        } else if (v.getId() == R.id.tv_option) {            Intent intent = new Intent(this, BillAddActivity.class);            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志            startActivity(intent); // 跳到账单填写页面        } else if (v.getId() == R.id.tv_month) {            // 构建一个日期对话框,该对话框已经集成了日期选择器。            // DatePickerDialog的第二个构造参数指定了日期监听器            DatePickerDialog dialog = new DatePickerDialog(this, this,                    calendar.get(Calendar.YEAR), // 年份                    calendar.get(Calendar.MONTH), // 月份                    calendar.get(Calendar.DAY_OF_MONTH)); // 日子            dialog.show(); // 显示日期选择对话框        }    }    @Override    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {        calendar.set(Calendar.YEAR, year);        calendar.set(Calendar.MONTH, month);        calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);        tv_month.setText(DateUtil.getMonth(calendar));        vp_bill.setCurrentItem(month); // 设置翻页视图显示第几页    }    // 初始化翻页视图    private void initViewPager() {        // 从布局视图中获取名叫pts_bill的翻页标签栏        PagerTabStrip pts_bill = findViewById(R.id.pts_bill);        // 设置翻页标签栏的文本大小        pts_bill.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);        // 构建一个商品图片的翻页适配器        BillPagerAdpater adapter = new BillPagerAdpater(getSupportFragmentManager(), calendar.get(Calendar.YEAR));        vp_bill.setAdapter(adapter); // 设置翻页视图的适配器        vp_bill.setCurrentItem(calendar.get(Calendar.MONTH)); // 设置翻页视图显示第几页        vp_bill.addOnPageChangeListener(this); // 给翻页视图添加页面变更监听器    }    // 翻页状态改变时触发    public void onPageScrollStateChanged(int state) {}    // 在翻页过程中触发    public void onPageScrolled(int position, float ratio, int offset) {}    // 在翻页结束后触发    public void onPageSelected(int position) {        calendar.set(Calendar.MONTH, position);        tv_month.setText(DateUtil.getMonth(calendar));    }}

适配器代码

package com.example.chapter08.adapter;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.TextView;import com.example.chapter08.BillAddActivity;import com.example.chapter08.R;import com.example.chapter08.bean.BillInfo;import com.example.chapter08.database.BillDBHelper;import java.util.ArrayList;import java.util.List;public class BillListAdapter extends BaseAdapter implements AdapterView.OnItemClickListener,        AdapterView.OnItemLongClickListener{    private static final String TAG = "BillListAdapter";    private Context mContext; // 声明一个上下文对象    private List mBillList = new ArrayList(); // 账单信息列表    public BillListAdapter(Context context, List billList) {        mContext = context;        mBillList = billList;    }    @Override    public int getCount() {        return mBillList.size();    }    @Override    public Object getItem(int position) {        return mBillList.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        ViewHolder holder;        if (convertView == null) {            holder = new ViewHolder();            // 根据布局文件item_bill.xml生成转换视图对象            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_bill, null);            holder.tv_date = convertView.findViewById(R.id.tv_date);            holder.tv_desc = convertView.findViewById(R.id.tv_desc);            holder.tv_amount = convertView.findViewById(R.id.tv_amount);            convertView.setTag(holder);        } else {            holder = (ViewHolder) convertView.getTag();        }        BillInfo bill = mBillList.get(position);        holder.tv_date.setText(bill.date);        holder.tv_desc.setText(bill.desc);        if (bill.date.equals("合计")) {            holder.tv_amount.setText(bill.remark);        } else {            holder.tv_amount.setText(String.format("%s%d元", bill.type==0?"收入":"支出", (int) bill.amount));        }        return convertView;    }    @Override    public void onItemClick(AdapterView parent, View view, int position, long id) {        if (position >= mBillList.size()-1) { // 合计行不响应点击事件            return;        }        Log.d(TAG, "onItemClick position=" + position);        BillInfo bill = mBillList.get(position);        // 以下跳转到账单填写页面        Intent intent = new Intent(mContext, BillAddActivity.class);        intent.putExtra("xuhao", bill.xuhao); // 携带账单序号,表示已存在该账单        mContext.startActivity(intent); // 因为已存在该账单,所以跳过去实际会编辑账单    }    @Override    public boolean onItemLongClick(AdapterView parent, View view, final int position, long id) {        if (position >= mBillList.size()-1) { // 合计行不响应长按事件            return true;        }        Log.d(TAG, "onItemLongClick position=" + position);        BillInfo bill = mBillList.get(position); // 获得当前位置的账单信息        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);        String desc = String.format("是否删除以下账单?\n%s %s%d %s", bill.date,                bill.type==0?"收入":"支出", (int) bill.amount, bill.desc);        builder.setMessage(desc); // 设置提醒对话框的消息文本        builder.setPositiveButton("是", new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                deleteBill(position); // 删除该账单            }        });        builder.setNegativeButton("否", null);        builder.create().show(); // 显示提醒对话框        return true;    }    // 删除该账单    private void deleteBill(int position) {        BillInfo bill = mBillList.get(position);        mBillList.remove(position);        notifyDataSetChanged(); // 通知适配器发生了数据变化        // 获得数据库帮助器的实例        BillDBHelper helper = BillDBHelper.getInstance(mContext);        helper.delete(bill.xuhao); // 从数据库删除指定序号的账单    }    public final class ViewHolder {        public TextView tv_date;        public TextView tv_desc;        public TextView tv_amount;    }}

XML文件

添加

                                                                                                                

查看

                                                                                

创作不易 觉得有帮助请点赞关注收藏~~~

来源地址:https://blog.csdn.net/jiebaoshayebuhui/article/details/127776523

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯