一:app介绍

理财小助手是一款利用Android studio软件实现的APP,可以录入每天的消费项目以及消费金额,同时也可以查找消费记录、统计消费总额。我用到的Android studio版本如下:

android studio课程设计 android studio课程设计理财app_apache


二、模块设计

下面是我实现的一些模块:

1:进入理财小助手app时会有一个登陆界面,包括邮箱和密码,邮箱和密码都有限制,如邮箱必须带有@符号,而密码必须不少于特定位数。

android studio课程设计 android studio课程设计理财app_apache_02

2:如果没有登录的邮箱或者密码时选择注册账号:

android studio课程设计 android studio课程设计理财app_android_03


3:进入理财app先进入理财记录的首页:(此时还没有添加一条记录,首页显示为空)

android studio课程设计 android studio课程设计理财app_数据库_04


4:添加一条消费记录,消费主体是lunch,消费金额是12,消费感受是good

android studio课程设计 android studio课程设计理财app_数据库_05


5:点击左上方的箭头会默认自动保存此记录,如果点击右上方的X,就会删去这条记录,这样,在理财app的主页就会显示添加的消费记录:

android studio课程设计 android studio课程设计理财app_apache_06


6:也可以双击每一条记录,这样就会出现此记录的详细信息,比如我选择了第一条记录:

android studio课程设计 android studio课程设计理财app_android studio课程设计_07


7:查看第五个步骤可以发现第五个步骤的图像右上方有三个符号,第一个+符号是添加一条记录,第二个符号是查找消息记录,第三个符号是可以统计金钱总额也可以显示出所有的消费记录:

第一个符号:

android studio课程设计 android studio课程设计理财app_数据库_08


第二个符号查找记录:

android studio课程设计 android studio课程设计理财app_java_09


第三符号有两个功能:

android studio课程设计 android studio课程设计理财app_apache_10


(1):统计功能:

android studio课程设计 android studio课程设计理财app_android studio课程设计_11


比如统计今天记录:2022年1月15日

android studio课程设计 android studio课程设计理财app_android studio课程设计_12


(2)显示记录的条数:如下,显示了添加的两条记录

android studio课程设计 android studio课程设计理财app_apache_13


三、代码设计

此代码设计分为两个部分,一个为前端的局面分布,一个为后端的java编写。如下:

android studio课程设计 android studio课程设计理财app_apache_14

1:java文件夹里面包含的是后端的代码,其中包含了database和wengxiaoyang.personalfinanceassistant。其中包括的类如下图所示:

android studio课程设计 android studio课程设计理财app_apache_15


2:res文件夹里面包括的是图片和前端代码,包括button或者布局等,是安卓必须掌握的基础知识点。

android studio课程设计 android studio课程设计理财app_android_16

其中可可爱爱的蜡笔小新就来自与drawable,当然也可以换成其他的图片啦。在这里插入图片描述

android studio课程设计 android studio课程设计理财app_android_17


layout里面存放的就是整个app的布局:

android studio课程设计 android studio课程设计理财app_数据库_18


menu用来控制右上方的三个符号功能:

android studio课程设计 android studio课程设计理财app_数据库_19


values用来控制button按钮:

android studio课程设计 android studio课程设计理财app_android_20


注意:其他没有特别说明就是图片。

四、详细代码
1:先贴入java后端的代码
database中的ManageBaseHelp类

package database;
//数据库的继承类,并重写两种方法
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import database.ManageDbSchema.ManageTable;
import database.ManageDbSchema.ManageTable2;
//打开数据库
public class ManageBaseHelper extends SQLiteOpenHelper {
    private static final int VERSION = 1;
    private static final String DATABASE_NAME = "manageBase.db";
//在此构造方法中用super方法调用父类的构造方法。传入四个参数,上下文对象,数据库名称,null,数据库版本
    public ManageBaseHelper(Context context) {
        super(context, DATABASE_NAME, null, VERSION);
    }

//重写子类的onCreate方法
    @Override
    public void onCreate(SQLiteDatabase db) {
        // manage表,暴力名称,金钱,支付方式等
        db.execSQL("create table " + ManageTable.NAME + "(" +
                "_id integer primary key autoincrement, " +
                ManageTable.Cols.UUID + ", " +
                ManageTable.Cols.TITLE + ", " +
                ManageTable.Cols.MONEY + ", " +
                ManageTable.Cols.DATE + ", " +
                ManageTable.Cols.PAYMETHOD  + ", " +
                ManageTable.Cols.REMARK + ")"
        );
        // 账号密码表
        db.execSQL("create table " + ManageTable2.NAME2 + "(" +
                "_id integer primary key autoincrement, " +
                ManageTable2.Cols2.UUID + ", " +
                ManageTable2.Cols2.ACCOUNT + ", " +
                ManageTable2.Cols2.PASSWORD + ")"
        );
    }
    //重写子类的onUpgrade方法
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

ManageCursorWrapper类

package database;
//将用户信息和消费消息写入数据库
import android.database.Cursor;
import android.database.CursorWrapper;

import java.util.Date;
import java.util.UUID;

import database.ManageDbSchema.ManageTable;
import database.ManageDbSchema.ManageTable2;
import wengxiaoyang.personalfinanceassistant.Login;
import wengxiaoyang.personalfinanceassistant.Manage;
//获得manage和login表格填写时的信息,并把他们放入数据库里面
public class ManageCursorWrapper extends CursorWrapper {
    public ManageCursorWrapper(Cursor cursor) {
        super(cursor);
    }

    public Manage getManage() {
        // 获得manage信息
        String uuidString = getString(getColumnIndex(ManageTable.Cols.UUID));//得到相对应的列索引,并赋值给string对象
        String title = getString(getColumnIndex(ManageTable.Cols.TITLE));
        String money = getString(getColumnIndex(ManageTable.Cols.MONEY));
        Long date = getLong(getColumnIndex(ManageTable.Cols.DATE));
        int payMethod = getInt(getColumnIndex(ManageTable.Cols.PAYMETHOD));
        String remark = getString(getColumnIndex(ManageTable.Cols.REMARK));





        // 将数据写入数据库
        Manage manage = new Manage(UUID.fromString(uuidString));
        manage.setTitle(title);
        manage.setMoney(money);
        manage.setDate(new Date(date));
        manage.setPayMethod(payMethod);
        manage.setRemark(remark);

        return manage;
    }


    public Login getLogin() {
        // 获得登录信息
        String uuidString = getString(getColumnIndex(ManageTable2.Cols2.UUID));
        String account = getString(getColumnIndex(ManageTable2.Cols2.ACCOUNT));
        String password = getString(getColumnIndex(ManageTable2.Cols2.PASSWORD));
        // 将登录信息存入数据库
        Login login = new Login(UUID.fromString(uuidString));
        login.setAccount(account);
        login.setPassword(password);

        return login;
    }
}

ManageDbSchema类

package database;

public class ManageDbSchema {
    // Manage表,定义常量
    public static final class ManageTable {
        public static final String NAME = "manages";

        public static final class Cols {
            public static final String UUID = "uuid";
            public static final String TITLE = "title";
            public static final String MONEY = "money";
            public static final String DATE = "date";
            public static final String PAYMETHOD = "paymethod";
            public static final String REMARK = "remark";
        }
    }

    // 账号密码表
    public static final class ManageTable2 {
        public static final String NAME2 = "login";
        public static final class Cols2 {
            public static final String UUID = "uuid";
            public static final String ACCOUNT = "account";
            public static final String PASSWORD = "password";
        }
    }

}

然后开始编写wengxiaoyang.personalfinanceassistant部分
DatePickerFragment类

package wengxiaoyang.personalfinanceassistant;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
//记录花销的日期(年月日)
public class DatePickerFragment extends DialogFragment {

    public static final String EXTRA_DATE = "wengxiaoyang.hziee.criminalintent.date";

    private static final String ARG_DATE = "date";

    private DatePicker mDatePicker;

    public static DatePickerFragment newInstance(Date date) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_DATE, date);

        DatePickerFragment fragment = new DatePickerFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Date date = (Date) getArguments().getSerializable(ARG_DATE);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_date, null);

        mDatePicker = v.findViewById(R.id.dialog_date_picker);
        mDatePicker.init(year, month, day, null);

        return new AlertDialog.Builder(getActivity()).setView(v)
                .setTitle(R.string.date_picker_title)
                .setPositiveButton(android.R.string.ok,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        int year = mDatePicker.getYear();
                        int month = mDatePicker.getMonth();
                        int day = mDatePicker.getDayOfMonth();
                        Date date = new GregorianCalendar(year, month, day).getTime();
                        sendResult(Activity.RESULT_OK, date);
                    }
                })
                .create();
    }

    private void sendResult(int resultCode, Date date) {
        if (getTargetFragment() == null) {
            return;
        }
        Intent intent = new Intent();
        intent.putExtra(EXTRA_DATE, date);

        getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode,intent);
    }
}

Login

package wengxiaoyang.personalfinanceassistant;
import java.util.UUID;
public class Login {
    private UUID mId;
    private String mAccount;
    private String mPassword;

    public Login() {
        this(UUID.randomUUID());
    }

    public Login(UUID id) {
        mId = id;
    }

    public UUID getId() {
        return mId;
    }

    public String getAccount() {
        return mAccount;
    }

    public void setAccount(String account) {
        mAccount = account;
    }

    public String getPassword() {
        return mPassword;
    }

    public void setPassword(String password) {
        mPassword = password;
    }

}

LoginActivity

package wengxiaoyang.personalfinanceassistant;

import android.content.Context;
import android.content.Intent;
import android.support.v4.app.Fragment;

public class LoginActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new LoginFragment();
    }

    public static Intent newIntent(Context packageContext) {
        Intent intent = new Intent(packageContext, LoginActivity.class);
        return intent;
    }

}

LoginFragment

package wengxiaoyang.personalfinanceassistant;

import android.support.v4.app.Fragment;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.content.Intent;

import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class LoginFragment extends Fragment {

    // UI
    private AutoCompleteTextView mEmailView;
    private EditText mPasswordView;
    private Button mRegisterButton;
    private View mProgressView;
    private View mLoginFormView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
                 //onCreateView是创建该fragment的视图,并返回给调用者。
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_login, container, false);
        // 建立视图
        mEmailView = (AutoCompleteTextView) view.findViewById(R.id.email);
        mPasswordView = (EditText) view.findViewById(R.id.password);
        mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {//输入密码之后监听哪个按钮的触发
                if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {//对应“完成”按钮和回车按钮,说明选择的是登录而不是注册
                    attemptLogin();
                    return true;
                }
                return false;
            }
        });

        Button mEmailSignInButton = (Button) view.findViewById(R.id.email_sign_in_button);//登录按钮
        mEmailSignInButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                attemptLogin();

            }
        });//设置监听,调用attemplogin方法判断邮箱和密码是否正确


        mRegisterButton = view.findViewById(R.id.register_button);//注册按钮
        mRegisterButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {//跳转到注册界面
                Intent intent = new Intent(getActivity(), RegisterActivity.class);
                startActivity(intent);
            }
        });

        mLoginFormView = view.findViewById(R.id.login_form);
        mProgressView = view.findViewById(R.id.login_progress);

        return view;
    }

    private void attemptLogin() {
          //判断邮箱和密码是否能和数据库里面的数据匹配
        // 重置,不能记住密码
        mEmailView.setError(null);
        mPasswordView.setError(null);

        // 获取登录的信息
        String email = mEmailView.getText().toString();
        String password = mPasswordView.getText().toString();

        boolean cancel = false;
        View focusView = null;

        // 校验账号和密码
        if (login(email, password)) {//调用下面的login方法进行邮箱密码比对,比对在loginlab中进行
            mEmailView.setError(getString(R.string.error_error_acpw));
            focusView = mEmailView;
            cancel = true;
            //比对不成功则提示报错
        }


        if (cancel) {
            // 聚焦到错误发生地
            focusView.requestFocus();
        } else {
            // 成功登录
            showProgress(true);
            // 跳转到ManageListActivity
            Intent intent = ManageListActivity.newIntent(getActivity());
            startActivity(intent);

        }
    }



    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    // 动画
    private void showProgress(final boolean show) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
            int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);

            mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
            mLoginFormView.animate().setDuration(shortAnimTime).alpha(
                    show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
                }
            });

            mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
            mProgressView.animate().setDuration(shortAnimTime).alpha(
                    show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
                }
            });
        } else {
            // 若API不支持,则简单显示
            mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
            mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
        }
    }

    public boolean login(String account, String password) {//验证此账号密码是否正确
        Login login = LoginLab.get(getActivity()).getAccountAndPassword(account, password);
        if (login != null) {
            return false;
        } else
            return true;
    }
}

LoginLab

package wengxiaoyang.personalfinanceassistant;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import database.ManageDbSchema.ManageTable2;
import database.ManageCursorWrapper;
import database.ManageBaseHelper;


public class LoginLab {
    private static LoginLab sLoginLab;

    private Context mContext;
    private SQLiteDatabase mDatabase;

    // 构造方法
    private LoginLab(Context context) {
        mContext = context.getApplicationContext();
        mDatabase = new ManageBaseHelper(mContext).getWritableDatabase();//获得可读写操作对象
    }

    // 注册界面添加账号密码,创建contentvalues对象,调用mdatabase的insert方法将数据插入到数据库里面
    public void addLogin(Login l) {
        ContentValues values = getContentValues(l);
        mDatabase.insert(ManageTable2.NAME2, null, values);
    }

    // 在数据库中找到Login表,也就是table2
    private ManageCursorWrapper queryLogin(String whereClause, String[] whereArgs) {
        Cursor cursor = mDatabase.query(
                ManageTable2.NAME2,
                null,// null selects all columns
                whereClause,
                whereArgs,
                null,
                null,
                null
        );
        return new ManageCursorWrapper(cursor);
    }



    // 根据返回的参数cursor,在找到的login表里面再根据账号密码查找对应的用户
    public Login getAccountAndPassword(String account, String password) {

        ManageCursorWrapper cursor = queryLogin(
                ManageTable2.Cols2.ACCOUNT + " = ? and " + ManageTable2.Cols2.PASSWORD+ " = ?",
                new String[] { account, password }
        );
        try {
            if (cursor.getCount() == 0) {//此用户不存在
                return null;
            }
            cursor.moveToFirst();//从表的第一个用户开始查找
            return cursor.getLogin();
        } finally {
            cursor.close();
        }
    }

    // 获得Login数据,后一个参数的值赋给前面的一个参数,返回的login的值进行对比
    private static ContentValues getContentValues(Login login) {
        ContentValues values = new ContentValues();
        values.put(ManageTable2.Cols2.UUID, login.getId().toString());
        values.put(ManageTable2.Cols2.ACCOUNT, login.getAccount());
        values.put(ManageTable2.Cols2.PASSWORD, login.getPassword());
        return values;
    }

    // 根据上下文获取LoginLab
    public static LoginLab get(Context context) {
        if (sLoginLab == null) {
            sLoginLab = new LoginLab(context);
        }
        return sLoginLab;
    }

}

Manage

package wengxiaoyang.personalfinanceassistant;

import java.util.Date;
import java.util.UUID;

public class Manage {

    private UUID mId;
    private String mTitle;
    private String mMoney;
    private Date mDate;
    private int mPayMethod;
    private String mRemark;

    public Manage() {
        this(UUID.randomUUID());
    }

    public Manage(UUID id) {
        mId = id;
        mDate = new Date();
    }

    public UUID getId() {
        return mId;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public String getMoney() {
        return mMoney;
    }

    public void setMoney(String money) {
        mMoney = money;
    }

    public Date getDate() {
        return mDate;
    }

    public void setDate(Date date) {
        mDate = date;
    }

    public int getPayMethod() {
        return mPayMethod;
    }

    public void setPayMethod(int payMethod) {
        mPayMethod = payMethod;
    }

    public String getRemark() {
        return mRemark;
    }

    public void setRemark(String remark) {
        mRemark = remark;
    }


    public String getPhotoFilename() {
        return "IMG_" + getId().toString() + ".jpg";
    }

}

ManageFragment

package wengxiaoyang.personalfinanceassistant;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.ShareCompat;
import android.support.v4.content.FileProvider;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
//manager的总布局


public class ManageFragment extends Fragment {

    private static final String ARG_MANAGE_ID = "manage_id";
    private static final String DIALOG_DATE = "dialogDate";
    private static final String DIALOG_TIME = "dialogTime";
    private static final String DIALOG_PHOTO = "dialogPhoto";

    private static final int REQUEST_DATE = 0;
    private static final int REQUEST_TIME = 0;
    private static final int REQUEST_PHOTO = 3;

    private Manage mManage;
    private File mPhotoFile;
    private EditText mTitleField;
    private EditText mMoneyField;
    private Button mDateButton;
    private RadioGroup mRadioGroup;
    private RadioButton mRadioButton_cash;
    private RadioButton mRadioButton_card;
    private EditText mRemarkField;
    private Button mTimeButton;
    private Button mReportButton;
    private ImageButton mPhotoButton;
    private ImageView mPhotoView;

    //根据ID创建实例
    public static ManageFragment newInstance(UUID manageId) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_MANAGE_ID, manageId);

        ManageFragment fragment = new ManageFragment();
        fragment.setArguments(args);
        return fragment;
    }

    // 保存部分数据
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        UUID manageId = (UUID) getArguments().getSerializable(ARG_MANAGE_ID);
        mManage = ManageLab.get(getActivity()).getManage(manageId);
        setHasOptionsMenu(true);
        mPhotoFile = ManageLab.get(getActivity()).getPhotoFile(mManage);
    }

    @Override
    public void onPause() {
        super.onPause();
        // 更新数据库数据
        ManageLab.get(getActivity()).updateManage(mManage);
    }

    // UI
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_manage, container, false);

        // 标题
        mTitleField = v.findViewById(R.id.manage_title);
        mTitleField.setText(mManage.getTitle());
        mTitleField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mManage.setTitle(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        // 金额
        mMoneyField = v.findViewById(R.id.manage_money);
        mMoneyField.setText(mManage.getMoney());
        mMoneyField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mManage.setMoney(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        // 日期
        mDateButton = v.findViewById(R.id.manage_date);
        Date date = mManage.getDate();

        updateDate();
        mDateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager manager = getFragmentManager();
                DatePickerFragment dialog = DatePickerFragment.newInstance(mManage.getDate());
                dialog.setTargetFragment(ManageFragment.this, REQUEST_DATE);
                dialog.show(manager, DIALOG_DATE);
            }
        });

        // 时间
        mTimeButton = v.findViewById(R.id.manage_time);

        String dateString2 = (String) DateFormat.format("h:mm a", date);
        updateTime(dateString2);
        mTimeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager manager = getFragmentManager();
                TimePickerFragment dialog = TimePickerFragment.newInstance(mManage.getDate());
                dialog.setTargetFragment(ManageFragment.this, REQUEST_TIME);
                dialog.show(Objects.requireNonNull(manager), DIALOG_TIME);  //第二个参数是tag
            }
        });

        // 支付方式
        mRadioGroup = v.findViewById(R.id.manage_pay_method);
        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                Manage manage = new Manage();
                switch (checkedId) {
                    case R.id.manage_cash:
                        manage.setPayMethod(1);
                        break;
                    case R.id.manage_card:
                        manage.setPayMethod(2);
                        break;
                    default:
                        break;
                }
            }
        });

        System.out.println(mManage.getPayMethod());

        mRadioButton_cash = v.findViewById(R.id.manage_cash);
        mRadioButton_card = v.findViewById(R.id.manage_card);

        int PayMethod = mManage.getPayMethod();
        if (PayMethod == 1) {
            mRadioButton_cash.setChecked(true);
        } else if (PayMethod == 2) {
            mRadioButton_card.setChecked(true);
        }


        // 备注
        mRemarkField = v.findViewById(R.id.manage_remark);
        mRemarkField.setText(mManage.getRemark());
        mRemarkField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mManage.setRemark(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        // 发送报告
        mReportButton = v.findViewById(R.id.manage_report);
        mReportButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ShareCompat.IntentBuilder i = ShareCompat.IntentBuilder.from(getActivity());
                i.setType("text/plain");
                i.setText(getManageReport());
                i.setSubject(getString(R.string.manage_report_subject));
                i.createChooserIntent();
                i.startChooser();
            }
        });

        PackageManager packageManager = getActivity().getPackageManager();

        // 拍照
        mPhotoButton = v.findViewById(R.id.manage_camera);
        final Intent captureImage = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 如果不能拍照就禁用按钮
        boolean canTakePhoto = mPhotoFile != null &&
                captureImage.resolveActivity(packageManager) != null;
        mPhotoButton.setEnabled(canTakePhoto);
        // 跳转到相机
        mPhotoButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = FileProvider.getUriForFile(getActivity(),
                        "wengxiaoyang.personalfinanceassistant.fileprovider", mPhotoFile);
                captureImage.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                List<ResolveInfo> cameraActivities = getActivity().getPackageManager()
                        .queryIntentActivities(captureImage, PackageManager.MATCH_DEFAULT_ONLY);
                for (ResolveInfo activity : cameraActivities) {
                    getActivity().grantUriPermission(activity.activityInfo.packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
                startActivityForResult(captureImage, REQUEST_PHOTO);
            }
        });

        // 显示照片
        mPhotoView = v.findViewById(R.id.manage_photo);
        mPhotoView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mPhotoFile == null || !mPhotoFile.exists()) {
                    mPhotoView.setImageDrawable(null);
                } else {
                    FragmentManager manager = getFragmentManager();
                    PhotoDetailFragment dialog = PhotoDetailFragment.newInstance(mPhotoFile);
                    dialog.setTargetFragment(ManageFragment.this, REQUEST_PHOTO);
                    dialog.show(manager, DIALOG_PHOTO);
                }
            }
        });

        ViewTreeObserver mPhotoObserver = mPhotoView.getViewTreeObserver();
        mPhotoObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                updatePhotoView(mPhotoView.getWidth(), mPhotoView.getHeight());
            }
        });

        return v;
    }

    // 根据需求更新视图
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {
            return;
        }

        if (requestCode == REQUEST_DATE) {
            Date date = (Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
            mManage.setDate(date);
            updateDate();
        }
        if (requestCode == REQUEST_TIME) {
            Date date = mManage.getDate();
            String dateString2 = (String) DateFormat.format("h:mm a", date);
            updateTime(dateString2);
        }
        else if (requestCode == REQUEST_PHOTO) {
            Uri uri = FileProvider.getUriForFile(getActivity(),
                    "wengxiaoyang.personalfinanceassistant.fileprovider", mPhotoFile);
            getActivity().revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            updatePhotoView(mPhotoView.getWidth(), mPhotoView.getHeight());
        }
    }

    // 创建菜单
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.fragment_manage, menu);
    }

    // 根据选择响应
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.delete_manage:
                ManageLab.get(getActivity()).removeManage(mManage);
                getActivity().finish();
                return true;
            case android.R.id.home:     //向上导航时保证子标题可见状态
                getActivity().finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void updateDate() {
        mDateButton.setText(mManage.getDate().toString());
    }

    private void updateTime(String s) {

        mTimeButton.setText(s);
    }

    // 发送报告
    private String getManageReport() {
        String payString = null;
        if (mManage.getPayMethod() == 1) {
            payString = getString(R.string.manage_report_cash);
        } else if (mManage.getPayMethod() == 2){
            payString = getString(R.string.manage_report_card);
        }




        String dateString = (String) DateFormat.format("EEE, MMM dd, yyyy", mManage.getDate());


        String report = getString(R.string.manage_report,
                mManage.getTitle(), dateString, payString, mManage.getRemark());

        return report;
    }

    // 更新照片视图
    private void updatePhotoView(int width, int height) {
        if (mPhotoFile == null || !mPhotoFile.exists()) {
            mPhotoView.setImageDrawable(null);
        } else {
            Bitmap bitmap = PictureUtils.getScaledBitmap(mPhotoFile.getPath(), width, height);
            mPhotoView.setImageBitmap(bitmap);
        }
    }

}

ManageLab

package wengxiaoyang.personalfinanceassistant;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import database.ManageDbSchema.ManageTable;
import database.ManageCursorWrapper;
import database.ManageBaseHelper;
//对每一条记录的操作:增加、删除、修改、查找
public class ManageLab {
    private static ManageLab sManageLab;

    private Context mContext;
    private SQLiteDatabase mDatabase;

    private ManageLab(Context context) {
        mContext = context.getApplicationContext();
        mDatabase = new ManageBaseHelper(mContext).getWritableDatabase();
    }

    // 添加记录
    public void addManage(Manage m) {
        ContentValues values = getContentValues(m);
        mDatabase.insert(ManageTable.NAME, null, values);
    }

    // 删除记录
    public void removeManage(Manage c) {
        String uuidString = c.getId().toString();
        mDatabase.delete(ManageTable.NAME, ManageTable.Cols.UUID + " = ?", new String[]{uuidString});
    }

    // 得到照片
    public File getPhotoFile(Manage manage) {
        File filesDir = mContext.getFilesDir();
        return new File(filesDir, manage.getPhotoFilename());
    }

    // 更新记录
    public void updateManage(Manage manage) {
        String uuidString = manage.getId().toString();
        ContentValues values = getContentValues(manage);
        mDatabase.update(ManageTable.NAME, values, ManageTable.Cols.UUID + " = ?", new String[]{uuidString});
    }

    // 查找记录
    private ManageCursorWrapper queryManages(String whereClause, String[] whereArgs) {
        Cursor cursor = mDatabase.query(
                ManageTable.NAME,
                null,// null selects all columns
                whereClause,
                whereArgs,
                null,
                null,
                null
        );
        return new ManageCursorWrapper(cursor);
    }

    // 得到Manages集合
    public List<Manage> getManages() {
        List<Manage> manages = new ArrayList<>();

        ManageCursorWrapper cursor = queryManages(null,null);

        try {
            cursor.moveToFirst();
            while (!cursor.isAfterLast()) {
                manages.add(cursor.getManage());
                cursor.moveToNext();
            }
        }finally {
            cursor.close();
        }
        return manages;
    }

    // 根据ID获取Manage
    public Manage getManage(UUID id) {

        ManageCursorWrapper cursor = queryManages(
                ManageTable.Cols.UUID + " = ?",
                new String[] { id.toString() }
        );
        try {
            if (cursor.getCount() == 0) {
                return null;
            }
            cursor.moveToFirst();
            return cursor.getManage();
        } finally {
            cursor.close();
        }
    }

    // 获得数据库数据
    private static ContentValues getContentValues(Manage manage) {
        ContentValues values = new ContentValues();
        values.put(ManageTable.Cols.UUID, manage.getId().toString());
        values.put(ManageTable.Cols.TITLE, manage.getTitle());
        values.put(ManageTable.Cols.MONEY, manage.getMoney());
        values.put(ManageTable.Cols.DATE, manage.getDate().getTime());
        values.put(ManageTable.Cols.PAYMETHOD, manage.getPayMethod());
        values.put(ManageTable.Cols.REMARK, manage.getRemark());

        return values;
    }

    public static ManageLab get(Context context) {
        if (sManageLab == null) {
            sManageLab = new ManageLab(context);
        }
        return sManageLab;
    }

}

ManageListActivity

package wengxiaoyang.personalfinanceassistant;

import android.content.Context;
import android.content.Intent;
import android.support.v4.app.Fragment;

public class ManageListActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new ManageListFragment();
    }

    public static Intent newIntent(Context packageContext) {
        Intent intent = new Intent(packageContext, ManageListActivity.class);
        return intent;
    }
}

ManageFragment

package wengxiaoyang.personalfinanceassistant;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
//显示消费记录


public class ManageListFragment extends Fragment {

    private RecyclerView mManageRecyclerView;
    private ManageAdapter mAdapter;
    private static int mManageIndex;
    private boolean mSubtitleVisible;
    private TextView mNullManageListTextView;
    private Button mAddManageButton;

    private static final String SAVED_SUBTITLE_VISIBLE = "subtitle";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    // UI
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_manage_list, container, false);

        mManageRecyclerView =  view.findViewById(R.id.manage_recycler_view);
        mManageRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        mNullManageListTextView = view.findViewById(R.id.null_manage_list);

        mAddManageButton = view.findViewById(R.id.add_manage);
        mAddManageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Manage manage = new Manage();
                ManageLab.get(getActivity()).addManage(manage);//下面的两个按钮
                Intent intent = ManagePagerActivity.newIntent(getActivity(), manage.getId());
                startActivity(intent);
            }
        });

        // 保持记录条数可见
        if (savedInstanceState != null) {
            mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE);
        }

        updateUI();

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        updateUI();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(SAVED_SUBTITLE_VISIBLE, mSubtitleVisible);
    }

    // 创建菜单
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.fragment_manage_list, menu);

        MenuItem subtitleItem = menu.findItem(R.id.show_subtitle);
        if (mSubtitleVisible) {
            subtitleItem.setTitle(R.string.hide_subtitle);
        } else {
            subtitleItem.setTitle(R.string.show_subtitle);
        }
    }

    // 响应菜单点击
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.new_manage:   // 创建新记录
                Manage manage = new Manage();
                ManageLab.get(getActivity()).addManage(manage);
                Intent intent = ManagePagerActivity.newIntent(getActivity(), manage.getId());
                startActivity(intent);
                return true;
            case R.id.search_manage:    //搜索
                intent = SearchActivity.newIntent(getActivity());
                startActivity(intent);
                return true;
            case R.id.statistic_manage: //统计
                intent = new Intent(getActivity(), StatisticActivity.class);
                startActivity(intent);
                return true;
            case R.id.show_subtitle:    //显示记录条数
                mSubtitleVisible = !mSubtitleVisible;
                getActivity().invalidateOptionsMenu();
                updateSubtitle();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    // 更新记录条数
    private void updateSubtitle() {
        ManageLab manageLab = ManageLab.get(getActivity());
        int manageCount = manageLab.getManages().size();
        String subtitle = getString(R.string.subtitle_format, manageCount);

        if (!mSubtitleVisible) {
            subtitle = null;
        }
        AppCompatActivity activity = (AppCompatActivity) getActivity();
        activity.getSupportActionBar().setSubtitle(subtitle);
    }

    // 更新UI界面
    private void updateUI() {
        ManageLab manageLab = ManageLab.get(getActivity());
        List<Manage> manages = manageLab.getManages();

        if (mAdapter == null) {
            mAdapter = new ManageAdapter(manages);
            mManageRecyclerView.setAdapter(mAdapter);
        } else {
            //重绘当前可见区域
            //mAdapter.notifyDataSetChanged();

            //部分重绘
            mAdapter.setManages(manages);
            mAdapter.notifyItemChanged(mManageIndex);
        }

        if (manages.size() != 0) {
            mNullManageListTextView.setVisibility(View.INVISIBLE);
            mAddManageButton.setVisibility(View.INVISIBLE);
        } else {
            mNullManageListTextView.setVisibility(View.VISIBLE);
            mAddManageButton.setVisibility(View.VISIBLE);
        }

        updateSubtitle();
    }

    private class ManageHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private TextView mTitleTextView;
        private TextView mDateTextView;
        private Manage mManage;

        public ManageHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater.inflate(R.layout.list_item_manage, parent, false));
            itemView.setOnClickListener(this);

            mTitleTextView = itemView.findViewById(R.id.manage_title);
            mDateTextView = itemView.findViewById(R.id.manage_date);
        }

        public void bind(Manage manage) {
            mManage = manage;
            mTitleTextView.setText(mManage.getTitle());

            Date date = manage.getDate();

            mDateTextView.setText(date.toString());
        }

        @Override
        public void onClick(View view) {
            Intent intent = ManagePagerActivity.newIntent(getActivity(), mManage.getId());
            mManageIndex = getAdapterPosition();     //返回数据在adapter中的位置
            startActivity(intent);
        }
    }


    private class ManageAdapter extends RecyclerView.Adapter {

        private List<Manage> mManages;

        public ManageAdapter(List<Manage> manages) {
            mManages = manages;
        }
        //视图类别功能

        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            //先建立LayoutInflater
            LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
            return new ManageHolder(layoutInflater, parent);
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            Manage manage = mManages.get(position);
            ((ManageHolder)holder).bind(manage);

        }

        @Override
        public int getItemCount() {
            return mManages.size();
        }

        public void setManages(List<Manage> manages) {
            mManages = manages;
        }
    }


}

ManagePagerActivity

package wengxiaoyang.personalfinanceassistant;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

import java.util.List;
import java.util.UUID;
//主页的最下面两个按钮,可依次跳转支出的详情界面,tolast and tofirst
public class ManagePagerActivity extends AppCompatActivity {

    private static final String EXTRA_MANAGE_ID = "wengxiaoyang.personalfinanceassistant.manage_id";
    private static final String EXTRA_MANAGE_TITLE = "wengxiaoyang.personalfinanceassistant.manage_title";

    private ViewPager mViewPager;
    private List<Manage> mManages;
    private Button btn_first;
    private Button btn_last;

    public static Intent newIntent(Context packageContext, UUID manageId) {
        Intent intent = new Intent(packageContext, ManagePagerActivity.class);
        intent.putExtra(EXTRA_MANAGE_ID, manageId);
        return intent;
    }

    public static Intent newIntent(Context packageContext, String title) {
        Intent intent = new Intent(packageContext, ManagePagerActivity.class);
        intent.putExtra(EXTRA_MANAGE_TITLE, title);
        return intent;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manage_pager);

        UUID manageId = (UUID) getIntent().getSerializableExtra(EXTRA_MANAGE_ID);

        mViewPager = findViewById(R.id.manage_view_pager);
        // 根据所处位置隐藏按钮
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (position == 0) {
                    btn_first.setVisibility(View.INVISIBLE);
                    btn_last.setVisibility(View.VISIBLE);
                } else if (position == mManages.size() - 1) {
                    btn_first.setVisibility(View.VISIBLE);
                    btn_last.setVisibility(View.INVISIBLE);
                } else {
                    btn_first.setVisibility(View.VISIBLE);
                    btn_last.setVisibility(View.VISIBLE);
                }
            }

            @Override
            public void onPageSelected(int i) {

            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });

        btn_first = findViewById(R.id.btn_to_first);
        btn_first.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewPager.setCurrentItem(0);
            }
        });

        btn_last = findViewById(R.id.btn_to_last);
        btn_last.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewPager.setCurrentItem(mManages.size() - 1);
            }
        });

        mManages = ManageLab.get(this).getManages();
        FragmentManager fragmentManager = getSupportFragmentManager();
        mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
            @Override
            public Fragment getItem(int position) {
                Manage manage = mManages.get(position);
                return ManageFragment.newInstance(manage.getId());
            }

            @Override
            public int getCount() {
                return mManages.size();
            }
        });

        // 给每条记录编号
        for (int i = 0; i < mManages.size(); i++) {
            if (mManages.get(i).getId().equals(manageId)) {
                mViewPager.setCurrentItem(i);
                break;
            }
        }
    }
}

PhotoDetailFragment

package wengxiaoyang.personalfinanceassistant;

import android.app.AlertDialog;
import android.app.Dialog;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;

import java.io.File;

public class PhotoDetailFragment extends DialogFragment {
    private static final String ARG_FILE = "file";
    private ImageView mPhotoView;

    // 照片细节
    public static PhotoDetailFragment newInstance(File file) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_FILE, file);

        PhotoDetailFragment fragment =new PhotoDetailFragment();
        fragment.setArguments(args);
        return fragment;
    }

    // 创建对话框
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        File file = (File) getArguments().getSerializable(ARG_FILE);
        View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_photo, null);
        mPhotoView = v.findViewById(R.id.manage_photo_detail);
        Bitmap bitmap = PictureUtils.getScaledBitmap(file.getPath(), getActivity());
        mPhotoView.setImageBitmap(bitmap);

        return new AlertDialog.Builder(getActivity()).setView(v)
                .setPositiveButton(android.R.string.ok, null).create();
    }
}

PictureUtils

package wengxiaoyang.personalfinanceassistant;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;

public class PictureUtils {
    public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
        //读入磁盘上图像的尺寸
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        float srcWidth = options.outWidth;
        float srcHeight = options.outHeight;

        //弄清要减少多少
        int inSampleSize = 1;
        if (srcHeight > destHeight || srcWidth > destWidth) {
            float heightScale = srcHeight / destHeight;
            float widthScale = srcWidth / destWidth;
            inSampleSize = Math.round(heightScale > widthScale ? heightScale : widthScale);
        }

        options = new BitmapFactory.Options();
        options.inSampleSize = inSampleSize;

        //读入和创建常量bitmap
        return BitmapFactory.decodeFile(path, options);
    }

    public static Bitmap getScaledBitmap(String path, Activity activity) {
        Point size = new Point();
        activity.getWindowManager().getDefaultDisplay().getSize(size);
        return getScaledBitmap(path, size.x, size.y);
    }
}

RegisterActivity

package wengxiaoyang.personalfinanceassistant;

import android.support.v4.app.Fragment;

public class RegisterActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new RegisterFragment();
    }
}

RegisterFragment

package wengxiaoyang.personalfinanceassistant;
//注册界面
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.content.Intent;


import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.support.v4.app.Fragment;

public class RegisterFragment extends Fragment {

    // UI
    private AutoCompleteTextView mEmailView;
    private EditText mPasswordView;
    private View mProgressView;
    private View mLoginFormView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 布局
        //onCreateView是创建该fragment的视图,并返回给调用者。
        View view = inflater.inflate(R.layout.fragment_register, container, false);

        mEmailView = (AutoCompleteTextView) view.findViewById(R.id.email);
        mPasswordView = (EditText) view.findViewById(R.id.password);
        mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
                if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {//输入密码之后监听触发了哪个按钮
                    attemptLogin();
                    return true;
                }
                return false;
            }
        });

        Button mEmailSignInButton = (Button) view.findViewById(R.id.email_sign_in_button);//登录按钮
        mEmailSignInButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                attemptLogin();

            }
        });

        mLoginFormView = view.findViewById(R.id.register_form);
        mProgressView = view.findViewById(R.id.register_progress);

        return view;
    }

    private void attemptLogin() {

        // 重置错误
        mEmailView.setError(null);
        mPasswordView.setError(null);

        // 获取输入内容
        String email = mEmailView.getText().toString();
        String password = mPasswordView.getText().toString();

        boolean cancel = false;
        View focusView = null;

        // 检查密码是否有效
        if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
            mPasswordView.setError(getString(R.string.error_invalid_password));
            focusView = mPasswordView;
            cancel = true;
        }

        // 确认有效的邮箱地址
        if (TextUtils.isEmpty(email)) {
            mEmailView.setError(getString(R.string.error_field_required));
            focusView = mEmailView;
            cancel = true;
        } else if (!isEmailValid(email)) {
            mEmailView.setError(getString(R.string.error_invalid_email));
            focusView = mEmailView;
            cancel = true;
        }

        if (cancel) {
            // 聚焦到错误发生地
            focusView.requestFocus();
        } else {
            // 成功后
            showProgress(true);
            // 将数据添加进数据库
            Login login = new Login();
            login.setAccount(email);
            login.setPassword(password);
            LoginLab.get(getActivity()).addLogin(login);
            Intent intent = LoginActivity.newIntent(getActivity());
            startActivity(intent);

        }
    }

    private boolean isEmailValid(String email) {//邮箱必须有@符号
        //TODO: Replace this with your own logic
        return email.contains("@");
    }

    private boolean isPasswordValid(String password) {//密码太短
        //TODO: Replace this with your own logic
        return password.length() > 4;
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    private void showProgress(final boolean show) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
            int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);

            mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
            mLoginFormView.animate().setDuration(shortAnimTime).alpha(
                    show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
                }
            });

            mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
            mProgressView.animate().setDuration(shortAnimTime).alpha(
                    show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
                }
            });
        } else {
            // The ViewPropertyAnimator APIs are not available, so simply show
            // and hide the relevant UI components.
            mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
            mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
        }
    }

}

SearchActivity

package wengxiaoyang.personalfinanceassistant;

import android.content.Context;
import android.content.Intent;
import android.support.v4.app.Fragment;

public class SearchActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new SearchFragment();
    }

    public static Intent newIntent(Context packageContext) {
        Intent intent = new Intent(packageContext, SearchActivity.class);
        return intent;
    }

}

SearchFragment

package wengxiaoyang.personalfinanceassistant;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class SearchFragment extends Fragment {

    // UI
    private TextView mTextView;
    private EditText mSearchView;
    private Button mSearchButton;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 布局
        View view = inflater.inflate(R.layout.fragment_search, container, false);

        mTextView = view.findViewById(R.id.textView_search);

        mSearchView = (EditText) view.findViewById(R.id.edit_search);


        mSearchButton  = (Button) view.findViewById(R.id.button_search1);
        // 跳转到搜索的activity
        mSearchButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                String search = mSearchView.getText().toString();
                Intent intent = ManagePagerActivity.newIntent(getActivity(), search);
                startActivity(intent);
            }
        });

        return view;
    }
}

SingleFragmentActivity

package wengxiaoyang.personalfinanceassistant;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;

public abstract class SingleFragmentActivity extends AppCompatActivity {

    protected abstract Fragment createFragment();

    // 创建fragment
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment == null) {
            fragment = createFragment();
            fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
        }
    }
}

StatisticActivity

package wengxiaoyang.personalfinanceassistant;

import android.support.v4.app.Fragment;

public class StatisticActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new StatisticFragment();
    }


}

StatisticFragment

package wengxiaoyang.personalfinanceassistant;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
//统计年月日的花销总额度
public class StatisticFragment extends Fragment {

    private EditText mYear;
    private EditText mMonth;
    private EditText mDay;
    private Button mButton;
    private TextView mMoney;
    private Double totalMoney = 0.0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 布局
        View view = inflater.inflate(R.layout.fragment_statistic, container, false);

        // 年
        mYear = view.findViewById(R.id.edit_year);

        // 月
        mMonth = view.findViewById(R.id.edit_month);

        // 日
        mDay = view.findViewById(R.id.edit_day);

        mButton = view.findViewById(R.id.button_statistic);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 获取输入框内容
                String year = mYear.getText().toString();
                String month = mMonth.getText().toString();
                String day = mDay.getText().toString();
                // 查找到所有记录
                List<Manage> manages = ManageLab.get(getActivity()).getManages();
                // 匹配有相同时间的记录,获得其金额并相加
                for (int i = 0; i < manages.size(); i++){
                    if (year.equals(manages.get(i).getDate().toString().substring(24,28)) || month.equals(manages.get(i).getDate().toString().substring(4,7)) || day.equals(manages.get(i).getDate().toString().substring(8,10))) {
                        totalMoney += Double.parseDouble(manages.get(i).getMoney());
                    }
                }
                mMoney.setText(totalMoney.toString() + "元");
                totalMoney = 0.0;
            }
        });

        mMoney = view.findViewById(R.id.text_money);

        return view;
    }
}

TimePickerFragment

package wengxiaoyang.personalfinanceassistant;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TimePicker;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
//支出具体的时间(小时、分钟、秒)
public class TimePickerFragment extends DialogFragment {
    //两个按钮公用一个EXTRA_DATE,所以不用新添加一个TimePicker专用的RXTRA_TIME
    public static final String EXTRA_DATE = "wengxiaoyang.hziee.criminalintent.date";

    private static final String ARG_DATE = "date";

    private TimePicker mTimePicker;


    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Date date = (Date) getArguments().getSerializable(ARG_DATE);

        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //不加final的话,GregorianCalendar的构造方法会报错
        final int year = calendar.get(Calendar.YEAR);
        final int month = calendar.get(Calendar.MONTH);
        final int day = calendar.get(Calendar.DAY_OF_MONTH);
        //时分
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);

        View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_time, null);

        mTimePicker = v.findViewById(R.id.dialog_time_picker);
        mTimePicker.setCurrentHour(hour);
        mTimePicker.setCurrentMinute(minute);

        return new AlertDialog.Builder(getActivity()).setView(v)
                .setTitle(R.string.date_picker_title)
                .setPositiveButton(android.R.string.ok,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                int hour = mTimePicker.getCurrentHour();
                                int minute = mTimePicker.getCurrentMinute();

                                Date date = new GregorianCalendar(year, month, day, hour, minute).getTime();
                                sendResult(Activity.RESULT_OK, date);
                            }
                        })
                .create();
    }

    private void sendResult(int resultCode, Date date) {
        if (getTargetFragment() == null) {
            return;
        }
        Intent intent = new Intent();
        intent.putExtra(EXTRA_DATE, date);

        getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode,intent);
    }

    public static TimePickerFragment newInstance(Date date) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_DATE, date);

        TimePickerFragment fragment = new TimePickerFragment();
        fragment.setArguments(args);
        return fragment;
    }
}

res部分的drawable
ic_launcher_background.xml(如果源文件里面存在此文件,就可以不要新建)

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#008577"
        android:pathData="M0,0h108v108h-108z" />
    <path
        android:fillColor="#00000000"
        android:pathData="M9,0L9,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,0L19,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,0L29,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,0L39,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,0L49,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,0L59,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,0L69,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,0L79,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M89,0L89,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M99,0L99,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,9L108,9"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,19L108,19"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,29L108,29"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,39L108,39"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,49L108,49"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,59L108,59"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,69L108,69"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,79L108,79"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,89L108,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,99L108,99"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,29L89,29"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,39L89,39"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,49L89,49"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,59L89,59"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,69L89,69"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,79L89,79"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,19L29,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,19L39,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,19L49,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,19L59,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,19L69,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,19L79,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
</vector>

round_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/colorPrimary"/>
    <corners android:radius="100dp"/>

round_border.xml

<?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <stroke android:color="@color/colorPrimary"
            android:width="1dp"/>
    <corners android:radius="100dp"/>

接下来是插入的9张可可爱爱的蜡笔小新图片,在drawable文件夹里面添加任意图片,根据个人喜好,添加的方式参考其他博客。
在drawable-anydpi文件夹里面添加以下文件
ic_menu_add.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
 
    android:viewportHeight="24"
    android:tint="#333333">
    <path
        android:fillColor="#FF000000"
        android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

ic_menu_delete.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="#333333">
    <path
        android:fillColor="#FF000000"
        android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

ic_menu_search.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="#333333">
    <path
        android:fillColor="#FF000000"
        android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

ic_menu_statistic.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="#333333">
    <path
        android:fillColor="#FF000000"
        android:pathData="M11.8,10.9c-2.27,-0.59 -3,-1.2 -3,-2.15 0,-1.09 1.01,-1.85 2.7,-1.85 1.78,0 2.44,0.85 2.5,2.1h2.21c-0.07,-1.72 -1.12,-3.3 -3.21,-3.81V3h-3v2.16c-1.94,0.42 -3.5,1.68 -3.5,3.61 0,2.31 1.91,3.46 4.7,4.13 2.5,0.6 3,1.48 3,2.41 0,0.69 -0.49,1.79 -2.7,1.79 -2.06,0 -2.87,-0.92 -2.98,-2.1h-2.2c0.12,2.19 1.76,3.42 3.68,3.83V21h3v-2.15c1.95,-0.37 3.5,-1.5 3.5,-3.55 0,-2.84 -2.43,-3.81 -4.7,-4.4z"/>
</vector>

在drawable-v24文件夹添加以下文件
ic_launcher_foreground.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillType="evenOdd"
        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
        android:strokeWidth="1"
        android:strokeColor="#00000000">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="78.5885"
                android:endY="90.9159"
                android:startX="48.7653"
                android:startY="61.0927"
                android:type="linear">
                <item
                    android:color="#44000000"
                    android:offset="0.0" />
                <item
                    android:color="#00000000"
                    android:offset="1.0" />
            </gradient>
        </aapt:attr>
    </path>
    <path
        android:fillColor="#FFFFFF"
        android:fillType="nonZero"
        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
        android:strokeWidth="1"
        android:strokeColor="#00000000" />
</vector>

接下来是layout文件夹,这是前端布局代码,添加以下文件:
activity_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:exported="true"
    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"
    tools:context=".ManagePagerActivity">
    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/t10"/>

activity_manage.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context=".ManageActivity"
    android:background="@drawable/t10">

activity_manage_pager.xml

<?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="@drawable/t10">

    <android.support.v4.view.ViewPager
        android:id="@+id/manage_view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="67dp"
        android:padding="16dp">

        <Button
            android:id="@+id/btn_to_first"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/btn_to_first"
            android:background="@drawable/round_bg"/>

        <Button
            android:id="@+id/btn_to_last"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:text="@string/btn_to_last"
            android:background="@drawable/round_bg"/>

    </FrameLayout>

</LinearLayout>

dialog_date.xml

<?xml version="1.0" encoding="utf-8"?>
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialog_date_picker"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:calendarViewShown="true"
    android:headerBackground="@android:color/holo_blue_bright">
</DatePicker>

dialog_photo.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/manage_photo_detail"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

dialog_time.xml

<?xml version="1.0" encoding="utf-8"?>
<TimePicker xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialog_time_picker"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:calendarViewShown="true"
    android:timePickerMode="spinner">
</TimePicker>

fragment_login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"

    android:background="@drawable/t8"
    tools:context=".LoginActivity">

    <!-- Login progress -->
    <ProgressBar
        android:id="@+id/login_progress"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:visibility="gone" />

    <ScrollView
        android:id="@+id/login_form"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/email_login_form"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <AutoCompleteTextView
                    android:id="@+id/email"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/prompt_email"
                    android:textColorHint="#000000"
                    android:textColor="#000000"
                    android:inputType="textEmailAddress"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/prompt_password"
                    android:textColor="#000000"
                    android:textColorHint="#000000"
                    android:imeActionId="6"
                    android:imeActionLabel="@string/action_sign_in_short"
                    android:imeOptions="actionUnspecified"
                    android:inputType="textPassword"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <Button
                android:id="@+id/email_sign_in_button"
                style="?android:textAppearanceSmall"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:text="@string/action_sign_in"
                android:background="@drawable/round_bg"
                android:textStyle="bold" />

            <Button
                android:id="@+id/register_button"
                style="?android:textAppearanceSmall"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:text="@string/register_button"
                android:background="@drawable/round_bg"
                android:textStyle="bold" />

        </LinearLayout>
    </ScrollView>
</LinearLayout>

fragment_manage.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:background="@drawable/t4">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/manage_photo"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:scaleType="centerInside"
            android:cropToPadding="true"
            android:background="@android:color/darker_gray"/>

        <ImageButton
            android:id="@+id/manage_camera"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@android:drawable/ic_menu_camera"/>
    </LinearLayout>


    <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
        </LinearLayout>

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_marginStart="10dp">
            <TextView
                style="?android:listSeparatorTextViewStyle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/manage_title_label"
                android:textColor="#000000"/>

            <EditText
                android:id="@+id/manage_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/manage_title_hint"
                android:textColorHint="#000000"
                android:textColor="#000000"/>
        </LinearLayout>
    </LinearLayout>

    <TextView
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/manage_details_money"
        android:textColor="#000000"/>

    <EditText
        android:id="@+id/manage_money"
        android:layout_width="match_parent"
        android:inputType="numberDecimal"
        android:layout_height="wrap_content"
        android:hint="@string/manage_money_hint"
        android:textColorHint="#000000"
        android:textColor="#000000"/>

    <TextView
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/manage_details_time"
        android:textColor="#000000"/>

    <Button
        android:id="@+id/manage_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/round_bg"/>

    <Button
        android:id="@+id/manage_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/round_bg"/>

    <TextView
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/manage_details_label"
        android:textColor="#000000"/>

    <RadioGroup
        android:id="@+id/manage_pay_method"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <RadioButton
            android:id="@+id/manage_cash"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="@string/manage_cash_label"
            android:textColor="#000000"/>

        <RadioButton
            android:id="@+id/manage_card"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/manage_card_label"
            android:textColor="#000000"/>
    </RadioGroup>

    <EditText
        android:id="@+id/manage_remark"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/manage_remark_label"
        android:textColor="#000000"
        android:textColorHint="#000000"/>
    <Button
        android:id="@+id/manage_report"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/manage_report_text"/>

fragment_manage_list.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@drawable/t6">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/manage_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:textColor="#000000"
        android:textSize="30dp" />

    <TextView
        android:id="@+id/null_manage_list"
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="280dp"
        android:text="@string/null_manage_list_text"
        android:textColor="#000000"
        android:textSize="20dp" />

    <Button
        android:id="@+id/add_manage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/null_manage_list"
        android:layout_marginLeft="32dp"
        android:layout_marginRight="32dp"
        android:text="@string/add_manage"
        android:textColor="#000000"
        android:textSize="25dp"
        android:background="@drawable/round_bg"/>
</RelativeLayout>

fragment_register.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:background="@drawable/t4"
    tools:context=".RegisterActivity">

    <!-- Login progress -->
    <ProgressBar
        android:id="@+id/register_progress"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:visibility="gone" />

    <ScrollView
        android:id="@+id/register_form"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/email_register_form"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <AutoCompleteTextView
                    android:id="@+id/email"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/prompt_email"
                    android:textColor="#000000"
                    android:textColorHint="#000000"
                    android:inputType="textEmailAddress"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/prompt_password"
                    android:textColorHint="#000000"
                    android:textColor="#000000"
                    android:imeActionId="6"
                    android:imeActionLabel="@string/action_sign_in_short"
                    android:imeOptions="actionUnspecified"
                    android:inputType="textPassword"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <Button
                android:id="@+id/email_sign_in_button"
                style="?android:textAppearanceSmall"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:text="@string/action_register_in"
                android:background="@drawable/round_bg"
                android:textStyle="bold" />

        </LinearLayout>
    </ScrollView>
</LinearLayout>

fragment_search.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:background="@drawable/t7">


    <TextView
        android:id="@+id/textView_search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/search"
        android:textColor="#000000"
        android:textSize="30dp" />

    <EditText
        android:id="@+id/edit_search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:hint="@string/edit_search"
        android:textColor="#000000"
        android:textSize="20dp"
        android:textColorHint="#000000"/>

    <Button
        android:id="@+id/button_search1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/search"
        android:textSize="20dp"
        android:background="@drawable/round_bg"/>

fragment_statistic.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/t5">

    <EditText
        android:id="@+id/edit_year"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:hint="@string/edit_year"
        android:textColorHint="#000000"
        android:textColor="#000000"
        android:textSize="20sp" />
    <EditText
        android:id="@+id/edit_month"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:hint="@string/edit_month"
        android:textColor="#000000"
        android:textSize="20sp"
        android:textColorHint="#000000"/>

    <EditText
        android:id="@+id/edit_day"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:hint="@string/edit_day"
        android:textColor="#000000"
        android:textSize="20sp"
        android:textColorHint="#000000"/>

    <Button
        android:id="@+id/button_statistic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="统计金额"
        android:textColor="#000000"
        android:textSize="20dp"
        android:background="@drawable/round_bg"/>

    <TextView
        android:id="@+id/text_money"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#000000"
        android:layout_marginTop="100dp"
        android:layout_gravity="center"
        android:textSize="20dp"
        android:hint="是否超出预算"
        android:textColorHint="#000000"/>

</LinearLayout>

list_item_manage.xml

<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">

    <TextView
        android:id="@+id/manage_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:text="@string/item_manage_title"
        android:textSize="18sp"
        app:layout_constraintBottom_toTopOf="@+id/manage_date"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <TextView
        android:id="@+id/manage_date"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="@string/item_manage_date"
        android:textColor="#000000"
        android:textColorHint="#000000"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/manage_title" />

接下来是menu文件夹,添加以下文件:
fragment_manage.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/delete_manage"
        android:icon="@drawable/ic_menu_delete"
        app:showAsAction="ifRoom|withText"
        android:title="@string/delete_manage" />

fragment_manage_list.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/new_manage"
        android:icon="@drawable/ic_menu_add"
        android:title="@string/new_manage"
        app:showAsAction="ifRoom|withText" />

    <item
        android:id="@+id/search_manage"
        android:icon="@drawable/ic_menu_search"
        android:title="@string/search"
        app:showAsAction="ifRoom|withText" />

    <item
        android:id="@+id/statistic_manage"
        android:icon="@drawable/ic_menu_statistic"
        android:title="@string/item_statistic"
        app:showAsAction="ifRoom|withText" />

    <item
        android:id="@+id/show_subtitle"
        android:title="@string/show_subtitle"
        app:showAsAction="ifRoom" />

</menu>

接下来是mipmap-anydpi-v26文件夹,包括以下文件:
ic_launcher.xml

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background" />
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

ic_launcher_round.xml

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background" />
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

接下来是values文件夹,其包括colors.xml dimens.xml strings.xml styles.xml
colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#0099ff</color>
    <color name="colorPrimaryDark">#0099ff</color>
    <color name="colorAccent">#03dac5</color>
</resources>

dimens.xml

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="text_margin">16dp</dimen>
</resources>

strings.xml

<resources>
    <string name="app_name">理财小助手</string>
    <!-- Strings related to login -->
    <string name="prompt_email">邮箱</string>
    <string name="prompt_password">密码</string>
    <string name="action_sign_in">登录</string>
    <string name="action_register_in">注册</string>
    <string name="action_sign_in_short">Sign in</string>
    <string name="error_invalid_email">无效的邮箱地址</string>
    <string name="error_error_acpw">账号或密码错误</string>
    <string name="error_invalid_password">密码太短</string>
    <string name="error_incorrect_password">密码错误</string>
    <string name="error_field_required">必填</string>
    <string name="permission_rationale">"Contacts permissions are needed for providing email
        completions."
    </string>
    <string name="manage_title_hint">加一个标题吧</string>
    <string name="manage_title_label">项目名称</string>
    <string name="manage_details_money">金额</string>
    <string name="manage_money_hint">快写上你花了多少钱</string>
    <string name="manage_details_label">支付方式</string>
    <string name="manage_details_time">时间</string>
    <string name="manage_cash_label">现金</string>
    <string name="manage_card_label">银行卡</string>
    <string name="manage_remark_label">备注</string>
    <string name="btn_to_first">To First</string>
    <string name="btn_to_last">To Last</string>
    <string name="date_picker_title">记录日期</string>
    <string name="new_manage">新记录</string>
    <string name="show_subtitle">显示记录条数</string>
    <string name="hide_subtitle">隐藏记录条数</string>
    <string name="subtitle_format">%1$d 条记录</string>
    <string name="delete_manage">删除记录</string>
    <string name="null_manage_list_text">尚未存在理财记录</string>
    <string name="add_manage">添加记录</string>
    <string name="manage_report_text">发送理财报告</string>
    <string name="manage_report">%1$s! 理财在 %2$s. %3$s 和 %4$s发生</string>
    <string name="manage_report_cash">现金支付</string>
    <string name="manage_report_card">信用卡支付</string>
    <string name="manage_report_subject">PersonalFinanceAssistant理财报告</string>
    <string name="send_report">发送理财报告通过: </string>
    <string name="item_manage_title">Manage Title</string>
    <string name="item_manage_date">Manage Date</string>
    <string name="register_button">还没有注册?点我注册</string>
    <string name="search">搜索</string>
    <string name="edit_search">输入你想搜索的内容</string>
    <string name="edit_year">输入年</string>
    <string name="edit_month">输入月</string>
    <string name="edit_day">输入日</string>
    <string name="item_statistic">统计</string>
</resources>

styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">#000000</item>
        <item name="colorPrimaryDark">#000000</item>
        <item name="colorAccent">#000000</item>
    </style>

</resources>

接下来是xml文件夹,其中包括了一个文件files.xml
files.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path
    name="crime_photos"
    path="." />
</paths>

清单文件:
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="wengxiaoyang.personalfinanceassistant">
    <!-- To auto-complete the email text field in the login form with the user's emails -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <uses-feature
        android:name="android.hardware.camera2"
        android:required="false" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".StatisticActivity"></activity>
        <activity android:name=".SearchActivity" />
        <activity android:name=".RegisterActivity" />
        <activity
            android:name=".LoginActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".ManageListActivity" />
        <activity
            android:name=".ManagePagerActivity"
            android:parentActivityName=".ManageListActivity" />

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="wengxiaoyang.personalfinanceassistant.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/files" />
        </provider>
    </application>

</manifest>

最后一个test文件夹
ExampleUnitTest

package wengxiaoyang.personalfinanceassistant;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() {
        assertEquals(4, 2 + 2);
    }
}

怕你们还没有弄清楚,现在将工程目录再进行截图:

android studio课程设计 android studio课程设计理财app_apache_21


android studio课程设计 android studio课程设计理财app_apache_22


android studio课程设计 android studio课程设计理财app_java_23


android studio课程设计 android studio课程设计理财app_apache_24


最后的java代码不知道为什么会报错,但是程序能够运行,希望大佬知道原因的评论区交流一下。