本次实现的是有关登录,注册和整体页面的改观,实现下方选项导致页面的切换效果。

利用到的技术有Sqlite数据库的增删改查,与fragment实现。由于暂时没有找到合适的图标,先借用微信的图标暂代一下。

①在数据库这方面的学习后,我总结出三步走战略

第一步:定义实体类。先建立好用户对象,存储数据。

package com.example.fragment;

public class User {
//username 用户名
//password 密码
public int id;
public String username;
public String password; public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User(){} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
}
}

第二步:创建数据库管理类。建立DBHelper继承extends SQLiteOpenHelper,然后创建表。

package com.example.fragment;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; public class UserDBHelper extends SQLiteOpenHelper {
public UserDBHelper(Context context,String name, SQLiteDatabase.CursorFactory factory, int version){
super(context,name,factory,1);
}
@Override
public void onCreate(SQLiteDatabase db) {
String created="create table Users ("
+"id integer primary key autoincrement, "
+"username text, "
+"password text)";
db.execSQL(created);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

该类中,共有三个方法,一个是构造函数,剩下两个是重写的方法,onCreate和onUpgrade,主要关注onCreate方法,在这个方法中创建了数据表,我这里定义数据表名为Users。构造函数主要关注参数,因为等会儿要调用,参数一共有四个,分别为系统上下文Context,数据库名,游标工厂(通常为null)以及数据库版本号,都是比较直接的参数,然后最后的onUpgrade,从字面上来理解,就是在数据库更新的时候调用的方法,需要传入新老版本号。

第三步:定义数据库操作类。方便我们增删改查操作的实现,不必再一个一个重写。

package com.example.fragment;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import java.util.ArrayList;
import java.util.List; public class UserOperator {
private UserDBHelper UserDBHelper;
private SQLiteDatabase db;
public UserOperator(Context context){
UserDBHelper=new UserDBHelper(context,"db_user",null,1);
db=UserDBHelper.getWritableDatabase();
}
//增加一条用户信息
public void addUser(User bean){
db.execSQL("insert into Users (username,password) values(?,?)",new Object[]{bean.username,bean.password});
}
//更新用户密码
public void updateUser(User bean){
db.execSQL("update Users set password=? where username=?",new Object[]{bean.password,bean.username});
}
//删除某位用户
public void deleteUser(String username){
db.execSQL("delete from Users where username=?",new String[]{username});
}
//判断用户是否存在
public User isExit(String name){
User bean=null;
Cursor c=db.rawQuery("select * from Users where username=?",new String[]{name});
while(c.moveToNext()){
bean=new User();
bean.setUsername(c.getString(c.getColumnIndex("username")));
bean.setPassword(c.getString(c.getColumnIndex("password")));
}
c.close();
return bean;
}
//获取所有用户
public List<User> getallUser(){
List<User> list=new ArrayList<>();
Cursor c=db.rawQuery("select * from Users",null);
while(c.moveToNext()){
User bean=new User();
bean.setUsername(c.getString(c.getColumnIndex("username")));
bean.setPassword(c.getString(c.getColumnIndex("password")));
list.add(bean);
}
c.close();
return list;
} }

数据库操作类的构造方法是值得一提的,主要执行了如下两步操作:

//数据库名:db_user

UserDBHelper=new UserDBHelper(context,"db_user",null,1);

//初始化数据库操作对象

db = UserDBHelper.getWritableDatabase();

第一步就是刚才讲到创建数据库管理类时提到的构造方法。可以观察到传入的四个参数:

1.上下文Context与调用数据库操作类时传入的上下文一致,2.定义了数据库名称为“db_user”,3.游标工厂为null,4.数据库版本号为1。

第二步为初始化数据库操作的对象。因为这里需要执行sql语句,所以必须要创建数据库的对象。

另外还需要关注的地方就是增删改查四类sql语句的写法,主要有如下:

增:(add)

db.execSQL("insert into Users (username,password) values(?,?)",new Object[]{bean.username,bean.password});

删:(delete)

db.execSQL("delete from Users where username=?",new String[]{username});

改:(update)

db.execSQL("update Users set password=? where username=?",new Object[]{bean.password,bean.username});

查:(select)

Cursor c=db.rawQuery("select * from Users where username=?",new String[]{name});
Cursor c=db.rawQuery("select * from Users",null);

说明:查询语句我觉得是四种操作之中最为复杂的一个,也是与用户需求最为贴合的一个需求。数据库把查询结果放入游标Cursor之中,然后通过遍历Cursor,把结果再赋给实体类User的对象或者是实体类泛型集合List<User>的对象,最终实现数据从数据库中到逻辑部分的传递。

那么,完成了这“三步走”之后,剩下的就是在Activity中的调用了。记得要在Activity中不仅要定义数据库操作类的对象,更要对其进行初始化。这是很重要的。

一共两个Activity:loginActivity和RegisterActivity

package com.example.fragment;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; import androidx.annotation.Nullable; public class loginActivity extends Activity implements View.OnClickListener{
private UserOperator muserOperator;
private TextView mTvLoginactivityRegister;
//private RelativeLayout mRlLoginactivityTop;
private EditText mEtLoginactivityUsername;
private EditText mEtLoginactivityPassword;
//private LinearLayout mLlLoginactivityTwo;
private Button mBtLoginactivityLogin; @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
muserOperator=new UserOperator(this);
initView(); } private void initView() {
mBtLoginactivityLogin = findViewById(R.id.bt_loginactivity_login);
mTvLoginactivityRegister = findViewById(R.id.tv_loginactivity_register);
mEtLoginactivityUsername = findViewById(R.id.et_loginactivity_username);
mEtLoginactivityPassword = findViewById(R.id.et_loginactivity_password); mBtLoginactivityLogin.setOnClickListener(this);
mTvLoginactivityRegister.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()){
case R.id.tv_loginactivity_register:
startActivity(new Intent(this,RegisterActivity.class));
finish();
break;
case R.id.bt_loginactivity_login:
String username=mEtLoginactivityUsername.getText().toString().trim();
String password=mEtLoginactivityPassword.getText().toString().trim();
User bean=muserOperator.isExit(username);
if(!TextUtils.isEmpty(username)&&!TextUtils.isEmpty(password)){
User bean1=muserOperator.isExit(username);
if(bean.password.equals(password)){
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}else{
Toast.makeText(this, "用户名或密码不正确,请重新输入", Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(this, "请输入你的用户名或密码", Toast.LENGTH_SHORT).show();
}
break;
}
}
}

RegisterActivity

package com.example.fragment;

import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import java.util.List; public class RegisterActivity extends AppCompatActivity implements View.OnClickListener{
private List<User> userList;
private String realCode;
private UserOperator muserOperator;
private Button mBtRegisteractivityRegister;
//private RelativeLayout mRlRegisteractivityTop;
private ImageView mIvRegisteractivityBack;
//private LinearLayout mLlRegisteractivityBody;
private EditText mEtRegisteractivityUsername;
private EditText mEtRegisteractivityPassword1;
private EditText mEtRegisteractivityPassword2;
private EditText mEtRegisteractivityPhonecodes;
private ImageView mIvRegisteractivityShowcode;
//private RelativeLayout mRlRegisteractivityBottom; @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
muserOperator=new UserOperator(this);
init();
// //将验证码用图片的形式显示出来
mIvRegisteractivityShowcode.setImageBitmap(Code.getInstance().createBitmap());
realCode = Code.getInstance().getCode().toLowerCase(); } private void init() {
mBtRegisteractivityRegister = findViewById(R.id.bt_registeractivity_register);
mIvRegisteractivityBack = findViewById(R.id.iv_registeractivity_back);
mEtRegisteractivityUsername = findViewById(R.id.et_registeractivity_username);
mEtRegisteractivityPassword1 = findViewById(R.id.et_registeractivity_password1);
mEtRegisteractivityPassword2 = findViewById(R.id.et_registeractivity_password2);
mEtRegisteractivityPhonecodes = findViewById(R.id.et_registeractivity_phoneCodes);
mIvRegisteractivityShowcode = findViewById(R.id.iv_registeractivity_showCode);
//按钮的点击事件,返回事件,点击二维码事件,注册事件
mIvRegisteractivityBack.setOnClickListener(this);
mIvRegisteractivityShowcode.setOnClickListener(this);
mBtRegisteractivityRegister.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()){
case R.id.iv_registeractivity_back:
Intent intent1=new Intent(this,loginActivity.class);
startActivity(intent1);
finish();
break;
case R.id.iv_registeractivity_showCode:
mIvRegisteractivityShowcode.setImageBitmap(Code.getInstance().createBitmap());
realCode = Code.getInstance().getCode().toLowerCase();
break;
case R.id.bt_registeractivity_register:
String username = mEtRegisteractivityUsername.getText().toString().trim();
String password = mEtRegisteractivityPassword1.getText().toString().trim();
String password2 = mEtRegisteractivityPassword2.getText().toString().trim();
String phoneCode = mEtRegisteractivityPhonecodes.getText().toString().toLowerCase(); if(!password.equals(password2)) {
Toast.makeText(this, "两次密码不一致,请重新注册", Toast.LENGTH_SHORT).show();
break;
} if(!TextUtils.isEmpty(username)&&!TextUtils.isEmpty(password)&&!TextUtils.isEmpty(phoneCode)){
if(phoneCode.equals(realCode)){
User bean=muserOperator.isExit(username);
if (bean!=null){
Toast.makeText(this, "该用户已存在,请重新注册", Toast.LENGTH_SHORT).show();
}else{
User bean2=new User(username,password);
muserOperator.addUser(bean2);
Intent intent2 = new Intent(this, loginActivity.class);
startActivity(intent2);
finish();
Toast.makeText(this, "验证通过,注册成功", Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(this, "验证码错误,注册失败", Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(this, "未完善信息,注册失败", Toast.LENGTH_SHORT).show();
}
break;
}
}
}

这样第一部分登录与注册就完成了,接下来就是第二步的fragment的模块:分四块

第一块:添加账单

第二块:显示本月的账单收支对比

第三块:利用图表来形象的展示

第四块:个人信息的展示与修改

由于目前刚刚掌握fragment的使用,先做了一个小案例:使用的是微信的相关界面。

在activity_main的布局中加入fragment与四个图片来控制这四块的切换,并设置第一个展示的是WeChart_Fragment

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity"> <fragment
android:id="@+id/fragment"
android:name="com.example.fragment.WeChart_Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/> <LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal"> <ImageView
android:id="@+id/image1"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:background="#ffffff"
android:src="@drawable/bottom_1" />
<ImageView
android:id="@+id/image2"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:background="#ffffff"
android:src="@drawable/bottom_2"
/>
<ImageView
android:id="@+id/image3"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:background="#ffffff"
android:src="@drawable/bottom_3"
/> <ImageView
android:id="@+id/image4"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:background="#ffffff"
android:src="@drawable/bottom_4" /> </LinearLayout> </RelativeLayout>

然后就是创建四个Fragment布局文件并通过对应的Java文件来展示view

最后在MainActivity中设置四个图片的监听事件,分被调用不同的Fragment

下面来简单看一下如何启动fragemnt

View.OnClickListener l = new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager fm = getFragmentManager(); // 获取Fragment
FragmentTransaction ft = fm.beginTransaction(); // 开启一个事务
Fragment f = null; //为Fragment初始化
switch (v.getId()) { //通过获取点击的id判断点击了哪个张图片
case R.id.image1:
f = new WeChart_Fragment(); //创建第一个Fragment
break;
case R.id.image2:
f = new Message_Fragment();//创建第二个Fragment
break;
case R.id.image3:
f = new Find_Fragment();//创建第三个Fragment
break;
case R.id.image4:
f = new Me_Fragment();//创建第四个Fragment
break;
default:
break;
}
ft.replace(R.id.fragment,f); //替换Fragment
ft.commit(); //提交事务
}
};

最后来看看今天的成果展示:

登录界面:

注册界面:

登陆成功后的界面:

安卓开发实战-记账本APP(三)的更多相关文章

  1. 安卓开发实战-记账本APP(六)

    记账本APP开发---终结篇 昨天的动态数字录屏奉上:在抖音上拍了一个(ps:欢迎点赞) https://v.douyin.com/poEjmG/ 今天将图表的内容进行了制作,我用的是MPChart的 ...

  2. 安卓开发实战-记账本APP(四)

    今天实现的内容有:添加账本信息,个人头像的切换,密码的修改,退出登录. 添加账本信息有三个功能: ①记一笔支出项目 ②记一笔收入项目 ③清空所有项目 在此期间遇到的困难有:Activity与Fragm ...

  3. 安卓开发实战-记账本APP(五)

    今天将昨天剩余的bug修复,并且完成图标的美化,设置长按删除,模仿支付宝实现金额的动态增加. ①将昨天的布局进行了修改:之前是fragment,改成FrameLayout布局,不再设置name,进而在 ...

  4. android开发实战-记账本APP(一)

    记账本开发流程: 对于一个记账本的初步开发而言,我实现的功能有: ①实现一个记账本的页面 ②可以添加数据并更新到页面中 ③可以将数据信息以图表的形式展现 (一)首先,制作一个记账本的页面. ①在系统自 ...

  5. android开发实战-记账本APP(二)

    继昨天的开发,继续完成今天的内容. (一)开始构建一些业务逻辑,开始构建记账本的添加一笔记账的功能. ①对fab按钮的click时间进行修改,创建一个AlertDialog.Builder对象,因此我 ...

  6. Android开发实战——记账本(2)

    开发日志(2)——Bean目录以及数据库 首先编写一些自己生成的数据进行测试,看一下能否显示在模拟器上.那前提就是先写出bean目录,这和之前学的Javaweb步骤差不多.bean目录有三个变量事件. ...

  7. Android开发实战——记账本(4)

    开发日志(4)——MainActivity 在MainActivity中编写了几个方法.首先,点击账本的一条记录可以选择删除他,然后重写了fab,使之在点击他后能够添加记录.还写了删除全部记录的方法. ...

  8. Android开发实战——记账本(6)

    开发日志——(6) 今天将app签名打包,并部署在了真机上.真机上的截图: 运行成功:

  9. Android开发实战——记账本(5)

    开发日志——(5)     今天打算将图标的功能实现,将打开图表的选项放在右上方,所以重写MainActivity中的onOptionsItemSelected方法.增添Chart选项 public ...

随机推荐

  1. Kafka 集群在马蜂窝大数据平台的优化与应用扩展

    马蜂窝技术原创文章,更多干货请订阅公众号:mfwtech Kafka 是当下热门的消息队列中间件,它可以实时地处理海量数据,具备高吞吐.低延时等特性及可靠的消息异步传递机制,可以很好地解决不同系统间数 ...

  2. 【题解】LOJ2759. 「JOI 2014 Final」飞天鼠(最短路)

    [题解]LOJ2759. 「JOI 2014 Final」飞天鼠(最短路) 考虑最终答案的构成,一定是由很多飞行+一些上升+一些下降构成. 由于在任何一个点上升或者下降代价是一样的,所以: 对于上升操 ...

  3. 【题解】CF986E Prince's Problem(树上差分+数论性质)

    [题解]CF986E Prince's Problem(树上差分+数论性质) 题目大意: 给定你一棵树,有点权\(val_i\le 10^7\).现在有\(m\)组询问给定参数\(x,y,w\)问你对 ...

  4. 07Shell数组

    Shell 数组变量 普通数组:只能使用整数作为数组索引 关联数组:可以使用字符串作为数组索引 普通数组 定义数组 方法1: 一次赋一个值 数组名[索引]=变量值 示例 # array1[0]=pea ...

  5. 组件的props属性和state状态

    props属性: 我使用代码来说明React中props属性: // Profile.jsx import React from 'react' ; export default Class Prof ...

  6. kubernetes基础——一文读懂k8s

    容器 容器与虚拟机对比图(左边为容器.右边为虚拟机)   容器技术是虚拟化技术的一种,以Docker为例,Docker利用Linux的LXC(LinuX Containers)技术.CGroup(Co ...

  7. (四)注册登录--重用Django

    一.使用已有登录功能 (1)进入Lib\sitepackages\django\contrib\admin\templates\registration下,将对应模板,复制到项目template模板中 ...

  8. 单机Web后端接口服务压力测试

    单机Web后端接口服务压力测试 工具:Apache jmeter 环境:Window 10 语言:Kotlin + java 架构:SpringBoot + + Mysql + redis + Spr ...

  9. 第一章 概述——1.TCP/IP设计遵循的两个原则

    1.端到端原则(end-to-end principle) 当我们设计一个大的系统(如操作系统或协议族)时,随之而来的一个问题通常是在什么位置实现某个功能.影响TCP/IP协议族设计的一个重要原则是端 ...

  10. STM321的SPI驱动遇到的一个坑!!

    最近在做项目要用到FATFS文件驱动和SD卡驱动,SD卡驱动我用的是SPI的通信方式,在挂载文件系统是总是挂在失败了,花了一天时间反复检查,才发现SPI在接收时候卡死: 为了寻找问题的原因,整个人都快 ...