我开发了一个可以自动记账的app 取名为simpleBill
记录一下开发过程中遇到的一些知识点
在开发的过程中发现是java加上ui的xml界面,所以很快就上手了

首先是Addrecord页面

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".ui.addRecord.AddRecordActivity">
        <!--<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"-->
        <!--    android:layout_width="match_parent"-->
        <!--    android:layout_height="match_parent">-->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="添加新账单"
            android:textSize="40dp"
            android:layout_gravity="center"
            />
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp"
            >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="金额:"
                android:textSize="20dp"
                android:layout_marginRight="20dp"
                android:layout_marginTop="3dp"
                />
            <EditText
                android:id="@+id/count"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:hint="请输入金额"
                android:inputType="numberDecimal"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp"
            >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="20dp"
                android:text="描述:"
                android:textSize="20dp" />
            <EditText
                android:id="@+id/description"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:hint="请输入描述"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="20dp"
                android:text="类别:"
                android:textSize="20dp" />

            <EditText
                android:id="@+id/leibie"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:hint="请输入描述" />


        </LinearLayout>
        <LinearLayout
            android:layout_width="278dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:layout_marginRight="20dp"
                android:text="来源:"
                android:textSize="20dp" />

            <Spinner
                android:id="@+id/source"
                style="@style/Base.Widget.AppCompat.Spinner.Underlined"
                android:layout_width="143dp"
                android:layout_height="50dp"
                android:layout_weight="1"/>
        </LinearLayout>


        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp"
            >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="时间:"
                android:textSize="20dp"
                android:layout_marginRight="20dp"

                />
            <EditText
                android:id="@+id/createDate"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                />
        </LinearLayout>

        <LinearLayout
            android:layout_width="278dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:layout_marginRight="20dp"
                android:text="收支:"
                android:textSize="20dp" />

            <Spinner
                android:id="@+id/shouzhi"
                style="@style/Base.Widget.AppCompat.Spinner.Underlined"
                android:layout_width="143dp"
                android:layout_height="50dp"
                android:layout_weight="1"
                android:entries="@array/spinner_shouzhi" />
        </LinearLayout>

        <Button
            android:id="@+id/add_record_btn"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="40dp"
            android:text="添加"
            android:textSize="20dp" />
        <Button
            android:id="@+id/goback"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="40dp"
            android:text="主页"
            android:textSize="20dp" />
        <Button
            android:id="@+id/leibie_manage"
            android:layout_width="215dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="40dp"
            android:text="类别管理"
            android:textSize="20dp" />
    </LinearLayout>
</ScrollView>

首先设计了记录的字段,我设计的账单记录字段包括金额,描述,类别,来源,日期,收支。

  1. 金额可以手动填写 或者无障碍服务识别特定页面自动填写。
  2. 描述可以手动填写 或者无障碍服务识别特定页面自动填写。
  3. 类别需要选择,此处设计了弹窗进行选择。

首先我在程序内部存储生成了一个leibie.txt

      File dir = AddRecordActivity.this.getFilesDir();
            // 创建文件对象
            File file = new File(dir, "leibie.txt");
            // 如果文件不存在,则创建它
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            ArrayList<String> leibieArraylist = readFile("leibie.txt",AddRecordActivity.this);
            if (leibieArraylist.size() <= 1){
                writeToFile("添加...","leibie.txt",AddRecordActivity.this,false);
            }

然后在点击类别时用popupwindow进行弹窗(收支用spinner,感觉spinner效果不太好,所以用了popupwindow)

  leibieEdit.setOnClickListener(this);
            leibieEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        try {
                            showPopupLeibieList(v,leibieEdit,leibieListView);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            });

弹出pupupwindow的代码

  private void showPopupLeibieList(View anchorView, EditText editText, ListView listView) throws IOException {
        // 初始化ListView和适配器(这里使用ArrayAdapter作为示例)

         leibieItems = readFile("leibie.txt",AddRecordActivity.this);
        listView = new ListView(this);
           ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, leibieItems);//弹窗固定写法 具体原理没研究

        listView.setAdapter(adapter);


        // 设置ListView的高度(可选,根据你的需要)
        int height = getResources().getDimensionPixelSize(R.dimen.list_popup_height);
        ListView.LayoutParams params = new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, height);
        listView.setLayoutParams(params);
        // 初始化PopupWindow,并设置宽高和焦点等属性
        popupWindow = new PopupWindow(listView, editText.getWidth() , height, true);
        Drawable drawable = getResources().getDrawable(R.drawable.popupwindow_border);
        popupWindow.setBackgroundDrawable(drawable);
        popupWindow.showAsDropDown(anchorView);//在锚点的正下方显示
        // 设置ListView的点击监听器
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // 处理点击事件,例如更新输入框的值并关闭PopupWindow
                if (position == leibieItems.size() -1 ){
                    showPopupAddLeibie();
                    popupWindow.dismiss();
                }else{
                    editText.setText(leibieItems.get(position));
                }

                popupWindow.dismiss();
            }
        });
        // 设置PopupWindow的触摸监听器(可选)
   
    }
  1. 来源很简单,用spinner
ArrayList<String> laiyuanNames = (ArrayList<String>) accountHelper.getAllNames();
            ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, laiyuanNames);
            // 将适配器设置给Spinner
            laiyuan.setAdapter(adapter);
  1. 时间用了日期选择器
private EditText dateEdit;
  SimpleDateFormat customFormat = new SimpleDateFormat("yyyy-MM-dd");
            String formattedDate = customFormat.format(new Date());

            dateEdit.setText(formattedDate);
            dateEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {

                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        CommonUtils.showDatePickDlg(AddRecordActivity.this,dateEdit,dateEdit.getText().toString());
                    }
                }
            });

日期选择器弹窗是多用的,因此提取出来至CommonUtils类

  public static void showDatePickDlg(Context context, EditText editText, String dateStr) {
        Calendar calendar = Calendar.getInstance();
        Date date = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            date = sdf.parse(dateStr);

        }catch (Exception e){}

        if (date!= null){
            calendar.setTime(date);
        }

        DatePickerDialog datePickerDialog = new DatePickerDialog(context, new DatePickerDialog.OnDateSetListener() {

            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                editText.setText(year + "-" +  String.format("%02d", monthOfYear+1) + "-" +  String.format("%02d", dayOfMonth));//最终那个edittext里显示的格式 可在这里调整,monthOfYear从0开始
            }
        }, calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH));
        datePickerDialog.show();

    }
  1. 来源用了spiiner
    spinner的数据来源区数据库中读取所有accountName
  ArrayList<String> laiyuanNames = (ArrayList<String>) accountHelper.getAllNames();
            ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, laiyuanNames);
            // 将适配器设置给Spinner
            laiyuan.setAdapter(adapter);
  1. 收支
    收支也用了spinner,选项只有“收入”“支出”,因此直接在xml中定义
<Spinner
                android:id="@+id/shouzhi"
                style="@style/Base.Widget.AppCompat.Spinner.Underlined"
                android:layout_width="143dp"
                android:layout_height="50dp"
                android:layout_weight="1"
                android:entries="@array/spinner_shouzhi" />

在values包中创建一个xml,名称随便 添加如下代码。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="spinner_shouzhi">
        <item>支出</item>
        <item>收入</item>
    </string-array>
</resources>
  1. 添加按钮
private void addRecord(){
		//获取所有的字符串
        String adesc = miaoshu.getText().toString();
        adesc = validateDesc(adesc);//校验是否有英文逗号,便于后期导出数据的处理。如果有英文逗号换成中文逗号。因为导出数据功能使用了英文逗号祚分隔符。
        String acount = jine.getText().toString();
        String adate = dateEdit.getText().toString();
        String ashouzhi = shouzhi.getSelectedItem().toString();
        String asource = laiyuan.getSelectedItem().toString();
        String aleibie = leibieEdit.getText().toString();

        if(acount.equals("")){
            Toast.makeText(this, "金额不能为空!", Toast.LENGTH_SHORT).show();
        } else if (adesc.equals("")) {
            Toast.makeText(this, "描述不能为空!", Toast.LENGTH_SHORT).show();
        } else if (adate.equals("")) {
            Toast.makeText(this, "日期不能为空!", Toast.LENGTH_SHORT).show();
        }else if(ashouzhi.equals("")){
            Toast.makeText(this, "收支不能为空!", Toast.LENGTH_SHORT).show();
        }
        else if(asource.equals("")){
            Toast.makeText(this, "来源不能为空!", Toast.LENGTH_SHORT).show();
        }
        else if(aleibie.equals("")){
            Toast.makeText(this, "类别不能为空!", Toast.LENGTH_SHORT).show();
        }
        else{
            if (ashouzhi.equals("支出")){
                acount = '-' + acount;
            }
            BillRecord record = new BillRecord();
            record.setSource(asource);
            record.setCount(acount);
            record.setDescription(adesc);
            record.setCreateDate(adate);
            record.setShouzhi(ashouzhi);
            record.setLeibie(aleibie);
            long res = billRecordHelper.addRecord(record);
            addButton.setEnabled(false);
            addButton.setTextColor(0xFFD0EFC6);
            if(res!=-1){
                Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();
                //如果是微信或支付宝跳转过来的 区分手动添加记录的情况
                if (isfrom("accessibility.alipay") || isfrom("accessibility.wechat")){
                    AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder
                            .setMessage("是否留在此地?")
                            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                        public void onClick(DialogInterface dialog, int id) {
                                            go(AddRecordActivity.this, MainActivity.class);//点击确定后去到app的主页。
                                            Intent intent = new Intent("REFRESH_ACTIVITY_ACTION");//发送这个action让主页刷新,否则主页不刷新。
                                            sendBroadcast(intent);
                                            finish();
                                        }
                                    }
                            )
                            .setNegativeButton("返回", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {

                                    Intent intent1 = new Intent("REFRESH_ACTIVITY_ACTION");
                                    sendBroadcast(intent1);
                                    // 处理确定按钮点击事件
                                    try{
                                        Intent intent = new Intent();
                                        if (isfrom("accessibility.wechat")){
                                            intent = new Intent(Intent.ACTION_VIEW, Uri.parse("weixin://"));
                                        }else if(isfrom("accessibility.alipay")){

                                            intent = new Intent(Intent.ACTION_VIEW, Uri.parse("alipayqr://"));
                                        }
                                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                        startActivity(intent);

                                        finish();
                                    }catch (Exception e){
                                        e.printStackTrace();
                                    }
                                }
                            });

                    AlertDialog dialog = builder.create();
                    dialog.show();


                }else {
                    Intent intent = new Intent("REFRESH_ACTIVITY_ACTION");
                    sendBroadcast(intent);
                     intent = new Intent(AddRecordActivity.this,MainActivity.class);
                    startActivity(intent);
                    finish();
                }


            }else{
                Toast.makeText(this, "添加失败!", Toast.LENGTH_SHORT).show();
            }
        }
    }

  1. 回到主页按钮
    没啥好说的,跳转至主页
Intent intent = new Intent(this,MainActivity.class);
          intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
          startActivity(intent);
  1. 类被管理按钮
    跳转至类别管理页面
Intent intent = new Intent(AddRecordActivity.this,LeibieManageActivity.class);
            intent.putExtra("FROM_ACTIVITY", "AddRecordActivity");
            startActivity(intent);

以上是手动添加记录的代码,如果是使用无障碍服务从微信/支付宝跳转过来的就直接读取数据
判断函数其实就是判断字符串相等

  private boolean isfrom(String action){
        if (formAction.equals(action)){
            return true;
        }
        return false;
    }
 if (isfrom("accessibility.wechat") || isfrom("accessibility.alipay")){
			//直接获取无障碍服务的Intent带过来的数据 StringExtra
            String tempMiaoshu = getIntent().getStringExtra("miaoshu");
            String tempJine = getIntent().getStringExtra("jine");
            tempJine = tempJine.replace(",","");
            String laiyuanStr = getIntent().getStringExtra("laiyuan");
            String shijian = getIntent().getStringExtra("shijian");
            String shouzhiStr = getIntent().getStringExtra("shouzhi");
            double jineNum = Double.valueOf(tempJine);
            jine.setText(String.valueOf(Math.abs(jineNum)));
            miaoshu.setText(tempMiaoshu);

            ArrayList<String> shouzhiItemList = new ArrayList<>();
            shouzhiItemList.add("收入");
            shouzhiItemList.add("支出");
            ArrayAdapter<String> adapter1 = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, shouzhiItemList);
            shouzhi.setAdapter(adapter1);
           shouzhi.setSelection(shouzhiItemList.indexOf(shouzhiStr));

            dateEdit.setText(shijian);
            dateEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {

                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        CommonUtils.showDatePickDlg(AddRecordActivity.this,dateEdit,dateEdit.getText().toString());
                    }
                }
            });

            File dir = AddRecordActivity.this.getFilesDir();
            // 创建文件对象
            File file = new File(dir, "leibie.txt");
                 // 如果文件不存在,则创建它
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            ArrayList<String> leibieArraylist = readFile("leibie.txt",AddRecordActivity.this);
            if (leibieArraylist.size() <= 1){
                writeToFile("添加...","leibie.txt",AddRecordActivity.this,false);
            }

       


            leibieEdit.setOnClickListener(this);
            leibieEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        try {
                            showPopupLeibieList(v,leibieEdit,leibieListView);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            });


            //来源

            ArrayList<String> laiyuanNames = (ArrayList<String>) accountHelper.getAllNames();
             if (laiyuanStr!=null && !laiyuanNames.contains(laiyuanStr)){
                showAlertAddAccount(laiyuanStr);

             }else {
                 laiyuanNames =(ArrayList<String>)  accountHelper.getAllNames();
                 ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, laiyuanNames);
                 // 设置下拉列表的显示样式
//        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                 // 将适配器设置给Spinner
                 laiyuan.setAdapter(adapter);
                 laiyuan.setSelection(laiyuanNames.indexOf(laiyuanStr));
             }


        }

今天先写到这里 后面慢慢更新

更多推荐