项目介绍:
小哈记账是一款用于记账APP,基于Android Studio开发工具,采用Java语言进行开发,同时使用litepal和阿里云数据库进行数据的增删查改,以图标的形式在App的界面上显示。App可以清晰显示收支情况,并以图表的形式展示每月收支情况;同时可以记录消费用途,项目能够精确到每一个款项的收入支出时间、结余并且可以设置每月的预算。超出预算提醒,并且有每周,每月及每年的账单统计,较为清晰明确帮助用户分析自己当前的支出和收入。同时拥有用户登录、注册、修改头像等功能。
本项目中使用到的技术:LitePal数据库,阿里云RDS数据库,MPAndroidChart图表库,部分自定义控件等。
支持Android5.0以上版本。
本文将介绍小哈记账的注册页面制作。
效果图:
源代码:
activity_register.xml
该文件是注册页面的布局文件,最外层是一个RelativeLayout,内部又分为五部分,最上面为顶部的RelativeLayout,存放顶部标题栏内容。第一个LinearLayout存放注册表单内容,第二个LinearLayout存放错误提示内容,后面两个ImageView分别存放注册按钮和用于显示隐藏密码的小眼睛。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<!--顶部-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/top_color"
android:orientation="horizontal"
android:paddingBottom="8sp"
android:paddingTop="36sp">
<ImageView
android:id="@+id/button_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="18sp"
android:layout_marginTop="10sp"
android:src="@drawable/ic_back_white_24" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="8sp"
android:text="使用手机号注册"
android:textColor="@color/white"
android:textSize="@dimen/top_title" />
</RelativeLayout>
<!--注册内容-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerHorizontal="true"
android:layout_marginTop="100sp">
<!--用户名-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="用 户 名:"
android:textColor="@color/grey_5"
android:textSize="@dimen/register_title"/>
<EditText
android:id="@+id/register_name"
android:layout_width="220sp"
android:layout_height="wrap_content"
android:singleLine="true"
android:gravity="left"
android:maxLength="20"
android:textSize="16sp"
android:textColor="#000000"/>
</LinearLayout>
<!--手机号-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8sp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="手 机 号:"
android:textColor="@color/grey_5"
android:textSize="@dimen/register_title"/>
<EditText
android:id="@+id/register_phone"
android:layout_width="220sp"
android:layout_height="wrap_content"
android:singleLine="true"
android:gravity="left"
android:maxLength="11"
android:textSize="16sp"
android:textColor="#000000"/>
</LinearLayout>
<!--验证码-->
<!--<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8sp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="验 证 码:"
android:textColor="@color/grey_5"
android:textSize="@dimen/register_title"/>
<EditText
android:id="@+id/register_code"
android:layout_width="110sp"
android:layout_height="wrap_content"
android:singleLine="true"
android:gravity="left"
android:textSize="16sp"
android:textColor="@color/black"/>
<LinearLayout
android:id="@+id/get_code"
android:layout_width="wrap_content"
android:layout_height="40sp"
android:layout_alignParentRight="true"
android:orientation="vertical"
style="@style/InputBoxStyleCode">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取验证码"
android:textSize="14sp"
android:textColor="@color/white" />
</LinearLayout>
</LinearLayout>-->
<!--密码-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8sp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密    码:"
android:textColor="@color/grey_5"
android:textSize="@dimen/register_title"/>
<EditText
android:id="@+id/register_password"
android:layout_width="220sp"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:singleLine="true"
android:gravity="left"
android:maxLength="16"
android:textSize="16sp"
android:textColor="#000000"/>
</LinearLayout>
<!--确认密码-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8sp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认密码:"
android:textColor="@color/grey_5"
android:textSize="@dimen/register_title"/>
<EditText
android:id="@+id/register_password2"
android:layout_width="220sp"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:singleLine="true"
android:gravity="left"
android:maxLength="16"
android:textSize="16sp"
android:textColor="#000000"/>
</LinearLayout>
</LinearLayout>
<!--提示内容-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/name_exist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="136sp"
android:text="用户名已存在"
android:textColor="@color/red"
android:visibility="invisible" />
<TextView
android:id="@+id/phone_exist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="32sp"
android:text="手机号不合法"
android:textColor="@color/red"
android:visibility="invisible" />
</LinearLayout>
<!--注册按钮-->
<ImageView
android:id="@+id/register_button"
android:layout_width="80sp"
android:layout_height="80sp"
android:layout_centerHorizontal="true"
android:layout_marginTop="380sp"
android:background="@drawable/login_login_button" />
<!--密码隐藏与显示-->
<ImageView
android:id="@+id/register_eye"
android:layout_width="20sp"
android:layout_height="20sp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginTop="260sp"
android:layout_marginRight="74sp"
android:background="@drawable/eye_none" />
</RelativeLayout>
RegisterActivity.java
该文件为注册活动,使用到了阿里云数据库,阿里云数据库的配置将在后续文章中详细介绍,部分功能我仍然以注释的形式保留了本地数据库的注册代码,没有云数据库的可以先使用本地数据库进行调试。(MyAppCompatActivity.java见文章1——欢迎页的制作)
注册功能本app,需要填写用户名,手机号,密码和确认密码(xml布局中留有验证码功能,但还未进行开发)。用户名和手机号设置为不可重复,并且手机号要合法。密码和确认密码要一致。所以我们需要添加事件对用户输入的用户名、手机号以及密码进行判断。
用户名检测是否已经存在函数:
此处有两种形式数据库(本地和云数据库)的代码,供大家自行选择。
/*查询用户名是否存在*/
private void name_is_exist(boolean hasFocus){
if(!hasFocus){
/*阿里云数据库*/
name = nameEdit.getText().toString();
final Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
if (bo) {
name_exist.setVisibility(View.VISIBLE);
} else{
name_exist.setVisibility(View.INVISIBLE);
}
return false;
}
});
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try {
bo = Database_Sql.querySelect_exist_x("user_name",name);
} catch (SQLException throwables) {
bo = false;
throwables.printStackTrace();
}
handler.sendMessage(msg);
}
}).start();
/*本地数据库
name = nameEdit.getText().toString();
name_exist.setVisibility(View.INVISIBLE);
List<Users> users = LitePal.findAll(Users.class,true);
for (Users user : users) {
if (user.getUser_name().equals(name)) {
name_exist.setVisibility(View.VISIBLE);
}
}*/
}
}
判断手机号是否已经注册函数:
此处也是两种数据库的代码供大家自行选择。
/*查询手机号是否注册*/
private void phone_is_exist(boolean hasFocus){
/*阿里云数据库*/
if(!hasFocus){
phone_exist.setVisibility(View.INVISIBLE);
phone = phoneEdit.getText().toString();
if(!isPhone(phone)){
phone_exist.setText("手机号不合法");
phone_exist.setVisibility(View.VISIBLE);
}else {
final Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
if (boo) {
phone_exist.setText("该手机号已注册");
phone_exist.setVisibility(View.VISIBLE);
} else {
phone_exist.setVisibility(View.INVISIBLE);
}
return false;
}
});
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try {
boo = Database_Sql.querySelect_exist_x("user_phone",phone);
} catch (SQLException throwables) {
boo = false;
throwables.printStackTrace();
}
handler.sendMessage(msg);
}
}).start();
}
/*本地数据库
phone = phoneEdit.getText().toString();
phone_exist.setVisibility(View.INVISIBLE);
if(!isPhone(phone)){
phone_exist.setText("手机号不合法");
phone_exist.setVisibility(View.VISIBLE);
}else {
List<Users> users = LitePal.findAll(Users.class);
for (Users user : users) {
if (user.getUser_phone().equals(phone)) {
phone_exist.setText("该手机号已注册");
phone_exist.setVisibility(View.VISIBLE);
}
}
}*/
}
}
判断是否为手机号函数:
/*判断是否是手机号*/
private static boolean isPhone(String phone){
String telRegex = "^[1][3-9]\\d{9}$";
//"[1]"代表第1位为数字1,"[3456789]"代表第二位可以为3-9中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
return phone.matches(telRegex);
}
以下为完整代码:
package com.example.xiaohaaccounting.Activity;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.InputType;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.xiaohaaccounting.Entity_class.Users;
import com.example.xiaohaaccounting.R;
import com.example.xiaohaaccounting.Utils_class.ActivityCollector;
import com.example.xiaohaaccounting.Utils_class.Database_Sql;
import com.example.xiaohaaccounting.Utils_class.MyAppCompatActivity;
import org.litepal.LitePal;
import java.sql.SQLException;
public class RegisterActivity extends MyAppCompatActivity {
private ImageView register_eye;
private EditText nameEdit;
private EditText phoneEdit;
//private EditText codeEdit;
private EditText passwordEdit;
private EditText password2Edit;
//private LinearLayout get_code;
private TextView name_exist;
private TextView phone_exist;
private String name;
private String phone;
private String password;
private String password2;
private String code;
private Boolean bo = false;
private Boolean boo = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
/*返回登录页面*/
ImageView button_back = (ImageView) findViewById(R.id.button_back);
button_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
initView();//初始化控件
/*检测用户名是否存在*/
nameEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
name_is_exist(hasFocus);
}
});
/*检测手机号是否合法,是否注册*/
phoneEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
phone_is_exist(hasFocus);
}
});
/*获取验证码*//*
get_code.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});*/
/*显示或隐藏密码*/
register_eye.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(password2Edit.getInputType() == 129){
register_eye.setBackground(getDrawable(R.drawable.eye));
password2Edit.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
} else{
register_eye.setBackground(getDrawable(R.drawable.eye_none));
password2Edit.setInputType(129);
}
}
});
/*注册*/
ImageView register_button = (ImageView) findViewById(R.id.register_button);
register_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
register();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
});
}
/*初始化控件*/
private void initView(){
nameEdit = (EditText) findViewById(R.id.register_name);
phoneEdit = (EditText) findViewById(R.id.register_phone);
//codeEdit = (EditText) findViewById(R.id.register_code);
passwordEdit = (EditText) findViewById(R.id.register_password);
password2Edit = (EditText) findViewById(R.id.register_password2);
//get_code = (LinearLayout) findViewById(R.id.get_code);
name_exist = (TextView) findViewById(R.id.name_exist);
phone_exist = (TextView) findViewById(R.id.phone_exist);
register_eye = (ImageView) findViewById(R.id.register_eye);
}
/*查询用户名是否存在*/
private void name_is_exist(boolean hasFocus){
if(!hasFocus){
/*阿里云数据库*/
name = nameEdit.getText().toString();
final Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
if (bo) {
name_exist.setVisibility(View.VISIBLE);
} else{
name_exist.setVisibility(View.INVISIBLE);
}
return false;
}
});
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try {
bo = Database_Sql.querySelect_exist_x("user_name",name);
} catch (SQLException throwables) {
bo = false;
throwables.printStackTrace();
}
handler.sendMessage(msg);
}
}).start();
/*本地数据库
name = nameEdit.getText().toString();
name_exist.setVisibility(View.INVISIBLE);
List<Users> users = LitePal.findAll(Users.class,true);
for (Users user : users) {
if (user.getUser_name().equals(name)) {
name_exist.setVisibility(View.VISIBLE);
}
}*/
}
}
/*查询手机号是否注册*/
private void phone_is_exist(boolean hasFocus){
/*阿里云数据库*/
if(!hasFocus){
phone_exist.setVisibility(View.INVISIBLE);
phone = phoneEdit.getText().toString();
if(!isPhone(phone)){
phone_exist.setText("手机号不合法");
phone_exist.setVisibility(View.VISIBLE);
}else {
final Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
if (boo) {
phone_exist.setText("该手机号已注册");
phone_exist.setVisibility(View.VISIBLE);
} else {
phone_exist.setVisibility(View.INVISIBLE);
}
return false;
}
});
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try {
boo = Database_Sql.querySelect_exist_x("user_phone",phone);
} catch (SQLException throwables) {
boo = false;
throwables.printStackTrace();
}
handler.sendMessage(msg);
}
}).start();
}
/*本地数据库
phone = phoneEdit.getText().toString();
phone_exist.setVisibility(View.INVISIBLE);
if(!isPhone(phone)){
phone_exist.setText("手机号不合法");
phone_exist.setVisibility(View.VISIBLE);
}else {
List<Users> users = LitePal.findAll(Users.class);
for (Users user : users) {
if (user.getUser_phone().equals(phone)) {
phone_exist.setText("该手机号已注册");
phone_exist.setVisibility(View.VISIBLE);
}
}
}*/
}
}
/*注册*/
private void register() throws SQLException {
name = nameEdit.getText().toString();
//code = codeEdit.getText().toString();
password = passwordEdit.getText().toString();
password2 = password2Edit.getText().toString();
if(TextUtils.isEmpty(name)){
Toast.makeText(getApplicationContext(),"用户名不能为空",Toast.LENGTH_SHORT).show();
} else if(TextUtils.isEmpty(phone)){
Toast.makeText(getApplicationContext(),"手机号不能为空",Toast.LENGTH_SHORT).show();
} else if(!isPhone(phone)){
Toast.makeText(getApplicationContext(),"手机号不合法",Toast.LENGTH_SHORT).show();
} else if(boo){
Toast.makeText(getApplicationContext(),"手机号已注册",Toast.LENGTH_SHORT).show();
}/* else if(TextUtils.isEmpty(code)){
Toast.makeText(getApplicationContext(),"验证码不能为空",Toast.LENGTH_SHORT).show();
} */else if(TextUtils.isEmpty(password)){
Toast.makeText(getApplicationContext(),"密码不能为空",Toast.LENGTH_SHORT).show();
} else if(TextUtils.isEmpty(password2)){
Toast.makeText(getApplicationContext(),"两次密码不一致",Toast.LENGTH_SHORT).show();
} else if(password.equals(password2)){
new Thread(new Runnable() {
@Override
public void run() {
try {
Database_Sql.insertIntoData(name,phone,password);//调用插入数据库语句
} catch (SQLException e) {
e.printStackTrace();
}
}
}).start();
Users user = new Users();
user.setUser_name(name);
user.setUser_password(password);
user.setUser_phone(phone);
user.save();
Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_LONG).show();
finish();
} else if(password != password2){
AlertDialog.Builder register_dialog = new AlertDialog.Builder(RegisterActivity.this);
register_dialog.setTitle("警告");
register_dialog.setMessage("两次密码不一致,请重新输入密码");
register_dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
register_dialog.show();
}
}
/*判断是否是手机号*/
private static boolean isPhone(String phone){
String telRegex = "^[1][3-9]\\d{9}$";
//"[1]"代表第1位为数字1,"[3456789]"代表第二位可以为3-9中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
return phone.matches(telRegex);
}
}