huting 2 лет назад
Родитель
Сommit
a193e3bcfd
22 измененных файлов: 1566 добавлений и 41 удалений
  1. 13
    0
      app/src/main/AndroidManifest.xml
  2. 2
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/project/api/bean/IFCode.java
  3. 1
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/after/TopEntrapmentActivity.java
  4. 62
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/user/ForgetPwdStep1Activity.java
  5. 147
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/user/ForgetPwdStep2Activity.java
  6. 109
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/user/ForgetPwdStep3Activity.java
  7. 60
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/project/utils/FunHelper.java
  8. 177
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/src/other/CountDownTimerUtils.java
  9. 45
    27
      app/src/main/java/com/huntersun/vkyes/etcopencard/src/ui/activity/LoginActivity.java
  10. 49
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/PwdEditText.java
  11. 61
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/PwdTextView.java
  12. 71
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/TInputConnection.java
  13. 361
    0
      app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/VerificationCodeView.java
  14. 7
    0
      app/src/main/res/drawable-v2/shape_divider_identifying.xml
  15. 28
    0
      app/src/main/res/drawable-v2/shape_icv_et_bg_focus.xml
  16. 27
    0
      app/src/main/res/drawable-v2/shape_icv_et_bg_normal.xml
  17. 75
    0
      app/src/main/res/layout/activity_forget_pwd_step1.xml
  18. 87
    0
      app/src/main/res/layout/activity_forget_pwd_step2.xml
  19. 115
    0
      app/src/main/res/layout/activity_forget_pwd_step3.xml
  20. 24
    0
      app/src/main/res/layout/layout_identifying_code.xml
  21. 23
    14
      app/src/main/res/layout/login_activity.xml
  22. 22
    0
      app/src/main/res/values/styles.xml

+ 13
- 0
app/src/main/AndroidManifest.xml Просмотреть файл

@@ -336,6 +336,19 @@
<activity android:name=".project.ui.activity.after.UndoLoopActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<!--忘记密码第一步-->
<activity android:name=".project.ui.activity.user.ForgetPwdStep1Activity"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<!--忘记密码第二步-->
<activity android:name=".project.ui.activity.user.ForgetPwdStep2Activity"
android:windowSoftInputMode="adjustPan"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
<!--忘记密码第三步-->
<activity android:name=".project.ui.activity.user.ForgetPwdStep3Activity"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
</application>

</manifest>

+ 2
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/project/api/bean/IFCode.java Просмотреть файл

@@ -28,6 +28,7 @@ public class IFCode {
// 定义Map常量2
public static final Map<String, String> LoadingMsgMap = new HashMap<String, String>();
static {
LoadingMsgMap.put(IFCode.IFCODE2, "发送中...");
LoadingMsgMap.put(IFCode.IFCODE4, "登录中...");
LoadingMsgMap.put(IFCode.IFCODE5, "登录中...");
LoadingMsgMap.put(IFCode.IFCODE6, "创建订单中...");
@@ -62,6 +63,7 @@ public class IFCode {
LoadingMsgMap.put(IFCode.IFCODE78, "VFJ-修改车辆信息中...");
}

public static final String IFCODE2 = "2"; //统一会员平台发送验证码接口
public static final String IFCODE4 = "4"; //登录
public static final String IFCODE5 = "5"; //通过code换取appid
public static final String IFCODE6 = "6"; //创建订单

+ 1
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/after/TopEntrapmentActivity.java Просмотреть файл

@@ -410,6 +410,7 @@ public class TopEntrapmentActivity extends AppActivity implements INRechargeChoo
toast("请输入充值金额,或者选择需要充值的金额!");
return;
}
//TODO 测试注释 正式需放开
// if(Double.parseDouble(FunHelper.getText(binding.etInputMoney)) < 10){
// toast("最低充值金额不小于10元!");
// return;

+ 62
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/user/ForgetPwdStep1Activity.java Просмотреть файл

@@ -0,0 +1,62 @@
package com.huntersun.vkyes.etcopencard.project.ui.activity.user;

import android.os.Bundle;
import android.view.View;

import com.huntersun.vky.obublelib.util.ValidatorUtils;
import com.huntersun.vkyes.etcopencard.databinding.ActivityForgetPwdStep1Binding;
import com.huntersun.vkyes.etcopencard.project.utils.FunHelper;
import com.huntersun.vkyes.etcopencard.src.app.AppActivity;

/**
* Date :2023-03-14
* Description:忘记密码第一步
*/
public class ForgetPwdStep1Activity extends AppActivity {
private ActivityForgetPwdStep1Binding binding;

private String phone;
@Override
protected View getLayoutView() {
binding = ActivityForgetPwdStep1Binding.inflate(getLayoutInflater());
return binding.getRoot();
}

@Override
protected void initView() {
phone = getIntent().getStringExtra("phone");
if (!FunHelper.isEmpty(phone)){
binding.etLoginPhone.setText(phone);
}

initClick();
}

@Override
protected void initData() {

}

private void initClick(){
binding.btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String phone = FunHelper.getText(binding.etLoginPhone);
if(FunHelper.isEmpty(phone)){
toast("请输入手机号!");
return;
}

if(!ValidatorUtils.isMobile(phone)){
toast("请输入正确的手机号!");
return;
}

Bundle bundle = new Bundle();
bundle.putString("phone",phone);
jumpToPage(ForgetPwdStep2Activity.class,bundle);
finish();
}
});
}
}

+ 147
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/user/ForgetPwdStep2Activity.java Просмотреть файл

@@ -0,0 +1,147 @@
package com.huntersun.vkyes.etcopencard.project.ui.activity.user;

import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.blankj.utilcode.util.LogUtils;
import com.google.gson.Gson;
import com.huntersun.vkyes.etcopencard.databinding.ActivityForgetPwdStep1Binding;
import com.huntersun.vkyes.etcopencard.databinding.ActivityForgetPwdStep2Binding;
import com.huntersun.vkyes.etcopencard.project.api.MyRetrofit;
import com.huntersun.vkyes.etcopencard.project.api.bean.IFCode;
import com.huntersun.vkyes.etcopencard.project.api.bean.ResultBean;
import com.huntersun.vkyes.etcopencard.project.tool.MyShared;
import com.huntersun.vkyes.etcopencard.project.ui.activity.MainActivity;
import com.huntersun.vkyes.etcopencard.project.utils.FunHelper;
import com.huntersun.vkyes.etcopencard.src.app.AppActivity;
import com.huntersun.vkyes.etcopencard.src.other.CountDownTimerUtils;
import com.jeremyliao.liveeventbus.LiveEventBus;

import java.util.HashMap;
import java.util.Map;

/**
* Date :2023-03-14
* Description:忘记密码第二步
*/
public class ForgetPwdStep2Activity extends AppActivity {
private ActivityForgetPwdStep2Binding binding;

//获取验证码倒计时
private CountDownTimerUtils codeCountDownTimer;

//手机号
private String phone;

@Override
protected View getLayoutView() {
binding = ActivityForgetPwdStep2Binding.inflate(getLayoutInflater());
return binding.getRoot();
}

@Override
protected void initView() {
LiveEventBus.get("countDownFinish", Boolean.class) .observe(this, s -> {//倒计时结束
clearCountDown(true);
});

phone = getIntent().getStringExtra("phone");
binding.tvPhone.setText("验证码已发送至:" + FunHelper.setPhoneSpace(phone));

binding.btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkParams();
}
});
binding.tvCountDownTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendCode();
}
});
}

@Override
protected void initData() {
if (FunHelper.isEmpty(phone)){
toast("手机号为空!");
return;
}
sendCode();
}

/*
* 检测参数
*/
private void checkParams(){
if(FunHelper.isEmpty(binding.verPwd.getInputContent())){
toast("请输入验证码");
return;
}

if (binding.verPwd.getInputContent().length() != 6){
toast("请输入正确的验证码");
return;
}

Bundle bundle = new Bundle();
bundle.putString("phone", phone);
bundle.putString("code",binding.verPwd.getInputContent());
jumpToPage(ForgetPwdStep3Activity.class,bundle);
finish();
}

/*
* 发送验证码
*/
private void sendCode(){
showDialog("发送中...");
Map<String, String> params = new HashMap<>();
params.put("mobile", phone);
MyRetrofit.newInstance(IFCode.IFCODE2, params, new MyRetrofit.ReturnResult() {
@Override
public void onSuccess(ResultBean resultBean, ResultBean.BizContent bizContent) {
hideDialog();
toast("验证码发送成功!");
FunHelper.showInputMethod(binding.verPwd.getEditText(),ForgetPwdStep2Activity.this);
showTimeCountDown(60*1000);
}
@Override
public void onError() {
MyRetrofit.ReturnResult.super.onError();
hideDialog();
}
});
}

/*
* 显示订单处理倒计时
*/
private void showTimeCountDown(long end_second) {
if (end_second <= 0) return;
codeCountDownTimer = new CountDownTimerUtils(this, null,null,null,binding.tvCountDownTime, end_second, 1000, false);
codeCountDownTimer.start();
}

/*
* 清除订单处理倒计时
* reSend:是否重新发送验证码
*/
private void clearCountDown(boolean reSend) {
if (codeCountDownTimer != null) {
codeCountDownTimer.cancel();
codeCountDownTimer = null;
}
if (reSend){
binding.tvCountDownTime.setText("点击重新发送验证码");
}
}

@Override
protected void onDestroy() {
super.onDestroy();
clearCountDown(false);
}
}

+ 109
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/project/ui/activity/user/ForgetPwdStep3Activity.java Просмотреть файл

@@ -0,0 +1,109 @@
package com.huntersun.vkyes.etcopencard.project.ui.activity.user;

import android.os.Bundle;
import android.view.View;

import com.huntersun.vkyes.etcopencard.databinding.ActivityForgetPwdStep3Binding;
import com.huntersun.vkyes.etcopencard.project.api.MyRetrofit;
import com.huntersun.vkyes.etcopencard.project.api.bean.IFCode;
import com.huntersun.vkyes.etcopencard.project.api.bean.ResultBean;
import com.huntersun.vkyes.etcopencard.project.utils.FunHelper;
import com.huntersun.vkyes.etcopencard.src.app.AppActivity;
import com.huntersun.vkyes.etcopencard.src.ui.activity.LoginActivity;
import com.jeremyliao.liveeventbus.LiveEventBus;

import java.util.HashMap;
import java.util.Map;

/**
* Date :2023-03-14
* Description:忘记密码第三步
*/
public class ForgetPwdStep3Activity extends AppActivity {

private ActivityForgetPwdStep3Binding binding;

//上个界面传递的手机号和验证码
private String phone;
private String code;

@Override
protected View getLayoutView() {
binding = ActivityForgetPwdStep3Binding.inflate(getLayoutInflater());
return binding.getRoot();
}

@Override
protected void initView() {
phone = getIntent().getStringExtra("phone");
code = getIntent().getStringExtra("code");

binding.btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkParams();
}
});
}

@Override
protected void initData() {

}

/*
* 检查参数
*/
private void checkParams(){
String pwd = FunHelper.getText(binding.etPassword);
String againPwd = FunHelper.getText(binding.etAgainPassword);
if (FunHelper.isEmpty(pwd)){
toast("请设置密码");
return;
}

if (FunHelper.isEmpty(againPwd)){
toast("请再次输入密码");
return;
}

if (!pwd.equals(againPwd)){
toast("两次密码输入不一致,请重新输入");
return;
}

toResetPwd();
}

/*
* 修改密码
*/
private void toResetPwd(){
showDialog("密码重置中...");
Map<String, String> params = new HashMap<>();
params.put("mobile", phone);
params.put("verificationCode", code);
params.put("password", FunHelper.getText(binding.etPassword));
params.put("affirmPassword", FunHelper.getText(binding.etAgainPassword));
MyRetrofit.newInstance(IFCode.IFCODE52, params, new MyRetrofit.ReturnResult() {
@Override
public void onSuccess(ResultBean resultBean, ResultBean.BizContent bizContent) {
hideDialog();
toast("密码修改成功,请重新登录!");

LiveEventBus.get("updatePwdSuccess").post(true);

Bundle bundle = new Bundle();
bundle.putString("phone",phone);
bundle.putString("pwd",FunHelper.getText(binding.etPassword));
jumpToPage(LoginActivity.class,bundle);
finish();
}
@Override
public void onError() {
MyRetrofit.ReturnResult.super.onError();
hideDialog();
}
});
}
}

+ 60
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/project/utils/FunHelper.java Просмотреть файл

@@ -1,12 +1,18 @@
package com.huntersun.vkyes.etcopencard.project.utils;

import android.app.Activity;
import android.content.Context;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@@ -230,4 +236,58 @@ public class FunHelper {

return isMatch;
}

/*
* 给手机号添加空格
*
* @param mobile
* @return
*/
public static String setPhoneSpace(String mobile) {
if (isEmpty(mobile)){
return "";
}

if (mobile.length() != 11){
return mobile;
}

StringBuilder builder = new StringBuilder();
for (int i = 0; i < mobile.length(); i++){
if (i < 2){
builder.append(mobile.charAt(i));
}else if (i == 2){
builder.append(mobile.charAt(i)).append(' ');
}else if (i > 3 && i < 6){
builder.append(mobile.charAt(i));
}else if ( i == 6){
builder.append(mobile.charAt(i)).append(' ');
}else{
builder.append(mobile.charAt(i));
}
}

return builder.toString();
}

/*
* 弹出软键盘
*
* @param editText
* @param activity
*/
public static void showInputMethod(EditText editText, Activity activity){
editText.setFocusable(true);
editText.setFocusableInTouchMode(true);
editText.requestFocus();

Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
}
}, 100);
}
}

+ 177
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/src/other/CountDownTimerUtils.java Просмотреть файл

@@ -0,0 +1,177 @@
package com.huntersun.vkyes.etcopencard.src.other;

import android.content.Context;
import android.os.CountDownTimer;
import android.widget.TextView;

import com.huntersun.vkyes.etcopencard.project.utils.FunHelper;
import com.jeremyliao.liveeventbus.LiveEventBus;

/**
* Date :2023-03-14
* Description:倒计时工具类
*/
public class CountDownTimerUtils extends CountDownTimer {
private Context context;
private TextView tvDay;
private TextView tvHour;
private TextView tvMin;
private TextView tvSec;
private TextView tvHMS;
private boolean isShowDay = false;

private String hint;
private String beforeHint; //时间前提示信息
private String afterHint;//时间后提示时间

public CountDownTimerUtils(Context context,
TextView tvHour,
TextView tvMin,
TextView tvSec,
int eventType,
long millisInFuture,
long countDownInterval) {
super(millisInFuture, countDownInterval);
this.context = context;
this.tvHour = tvHour;
this.tvMin = tvMin;
this.tvSec = tvSec;
this.isShowDay = false;
}

public CountDownTimerUtils(Context context,
TextView tvDay,
TextView tvHour,
TextView tvMin,
TextView tvSec,
long millisInFuture,
long countDownInterval,
boolean isShowDay) {
super(millisInFuture, countDownInterval);
this.context = context;
this.tvDay = tvDay;
this.tvHour = tvHour;
this.tvMin = tvMin;
this.tvSec = tvSec;
this.isShowDay = isShowDay;
}

public CountDownTimerUtils(Context context,
TextView tvHMS,
String hint,
long millisInFuture,
long countDownInterval,
boolean isShowDay) {
super(millisInFuture, countDownInterval);
this.context = context;
this.tvHMS = tvHMS;
this.hint = hint;
this.isShowDay = isShowDay;
}

@Override
public void onTick(long millisUntilFinished) {
DateBean bean = isShowDay ? getCountDownTimeWithDay(millisUntilFinished)
: getCountDownTime(millisUntilFinished);

if (beforeHint == null){
beforeHint = "";
}

if (hint == null) {
hint = "";
}

if (afterHint == null) {
afterHint = "";
}

//显示普通的 HH:MM:SS / _HH:MM:SS
if (tvHMS != null) {
tvHMS.setText((FunHelper.isEmpty(beforeHint) ? hint : beforeHint) + bean.hour + ":" + bean.minute + ":" + bean.second + afterHint);
return;
}

//时、分、秒各显示
if (isShowDay && tvDay != null) {
tvDay.setText((FunHelper.isEmpty(beforeHint) ? hint : beforeHint) + bean.day);
}

if (tvHour != null) {
tvHour.setText(bean.hour);
}

if (tvMin != null) {
tvMin.setText(bean.minute);
}

if (tvSec != null) {
tvSec.setText(((tvDay == null && tvHour == null && tvMin == null) ? beforeHint : "") + bean.second + afterHint);
}
}

@Override
public void onFinish() {
LiveEventBus.get("countDownFinish").post(true);
}

/*
* 获取倒计时(时分秒)
*
* @param time
* @return
*/
public static DateBean getCountDownTime(long time) {
long second = time / 1000;
long hour = second / 60 / 60;
long minute = (second - hour * 60 * 60) / 60;
long sec = (second - hour * 60 * 60) - minute * 60;

String rHour = (hour < 10) ? "0" + hour : hour + "";
String rMin = (minute < 10) ? "0" + minute : minute + "";
String rSs = (sec < 10) ? "0" + sec : sec + "";

DateBean bean = new DateBean();
bean.hour = rHour;
bean.minute = rMin;
bean.second = rSs;

return bean;
}

/*
* 获取倒计时(天时分秒)
*
* @param time
* @return
*/
public static DateBean getCountDownTimeWithDay(long time) {
long second = time / 1000;
long day = second / 60 / 60 / 24;
long hour = (second - day * 24 * 3600) / 3600;
long minute = ((second - day * 24 * 3600) - (hour * 3600)) / 60;
long sec = (second - day * 24 * 3600) - hour * 3600 - minute * 60;

String rDay = (day < 10) ? "0" + day : day + "";
String rHour = (hour < 10) ? "0" + hour : hour + "";
String rMin = (minute < 10) ? "0" + minute : minute + "";
String rSs = (sec < 10) ? "0" + sec : sec + "";

DateBean bean = new DateBean();
bean.day = rDay;
bean.hour = rHour;
bean.minute = rMin;
bean.second = rSs;

return bean;
}

static class DateBean {
public String day;
public String hour;
public String minute;
public String second;
}
}



+ 45
- 27
app/src/main/java/com/huntersun/vkyes/etcopencard/src/ui/activity/LoginActivity.java Просмотреть файл

@@ -6,9 +6,7 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Base64;
import android.util.Log;
import android.view.Gravity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -20,16 +18,11 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.EncodeUtils;
import com.blankj.utilcode.util.EncryptUtils;
import com.google.gson.Gson;
import com.gyf.immersionbar.ImmersionBar;
import com.hjq.base.BaseDialog;
import com.hjq.umeng.UmengClient;
import com.hjq.widget.view.CountdownView;
import com.hjq.widget.view.SubmitButton;
import com.huntersun.vkyes.etcopencard.R;
import com.huntersun.vkyes.etcopencard.project.api.Api;
import com.huntersun.vkyes.etcopencard.project.api.Converter;
@@ -38,34 +31,24 @@ import com.huntersun.vkyes.etcopencard.project.api.MyRetrofit;
import com.huntersun.vkyes.etcopencard.project.api.RequestParameters;
import com.huntersun.vkyes.etcopencard.project.api.Result;
import com.huntersun.vkyes.etcopencard.project.api.bean.IFCode;
import com.huntersun.vkyes.etcopencard.project.api.bean.LoginBean;
import com.huntersun.vkyes.etcopencard.project.api.bean.ResultBean;
import com.huntersun.vkyes.etcopencard.project.api.bean.SendTheVerificationCodeBean;
import com.huntersun.vkyes.etcopencard.project.tool.MyShared;
import com.huntersun.vkyes.etcopencard.project.tool.RSAUtil;
import com.huntersun.vkyes.etcopencard.project.tool.Utils;
import com.huntersun.vkyes.etcopencard.project.ui.activity.MainActivity;
import com.huntersun.vkyes.etcopencard.project.ui.activity.UpdatePasswordActivity;
import com.huntersun.vkyes.etcopencard.project.ui.activity.user.ForgetPwdStep1Activity;
import com.huntersun.vkyes.etcopencard.project.utils.FunHelper;
import com.huntersun.vkyes.etcopencard.src.aop.SingleClick;
import com.huntersun.vkyes.etcopencard.src.app.AppActivity;
import com.huntersun.vkyes.etcopencard.src.http.glide.GlideApp;
import com.huntersun.vkyes.etcopencard.src.other.KeyboardWatcher;
import com.huntersun.vkyes.etcopencard.src.ui.dialog.MenuDialog;
import com.huntersun.vkyes.etcopencard.src.wxapi.WXEntryActivity;
import com.hjq.umeng.Platform;
import com.hjq.umeng.UmengClient;
import com.hjq.umeng.UmengLogin;
import com.hjq.widget.view.SubmitButton;
import com.jeremyliao.liveeventbus.LiveEventBus;

import java.security.PublicKey;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import retrofit2.Response;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
* author : Android 轮子哥
@@ -141,6 +124,27 @@ public final class LoginActivity extends AppActivity
setOnClickListener(mForgetView, mCountdownView, mTvLoginCode, mCodeView, mCommitView);

mPasswordView.setOnEditorActionListener(this);

updatePwdSuccess();
}

/**
* 修改密码成功
*/
private void updatePwdSuccess(){
//修改密码之后-自动填充
String phone = getIntent().getStringExtra("phone");
String pwd = getIntent().getStringExtra("pwd");
if(!FunHelper.isEmpty(phone)){
mPhoneView.setText(phone);
}
if (!FunHelper.isEmpty(pwd)){
mPasswordView.setText(pwd);
}

LiveEventBus.get("updatePwdSuccess", Boolean.class) .observe(this, s -> {
finish();
});
}

@Override
@@ -173,10 +177,14 @@ public final class LoginActivity extends AppActivity
@Override
public void onClick(View view) {
if (view == mForgetView) {
Intent intent = new Intent();
/* Intent intent = new Intent();
intent.putExtra("start", false);
intent.setClass(LoginActivity.this, UpdatePasswordActivity.class);
startActivity(intent);
startActivity(intent);*/

Bundle bundle = new Bundle();
bundle.putString("phone",FunHelper.getText(mPhoneView));
jumpToPage(ForgetPwdStep1Activity.class,bundle);
return;
}

@@ -225,10 +233,19 @@ public final class LoginActivity extends AppActivity
toast(R.string.common_phone_input_error);
return;
}

LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
String value = loginStart ? mPasswordView.getText().toString() : mCodeView.getText().toString();
// 隐藏软键盘
hideKeyboard(getCurrentFocus());

if (FunHelper.isEmpty(value)){
toast("请输入密码!");
mPasswordView.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.shake_anim));
mCommitView.showError(3000);
return;
}

//提交数据处理
Map<String, String> params = new HashMap<>();
params.put("mobile", mPhoneView.getText() + "");
@@ -334,4 +351,5 @@ public final class LoginActivity extends AppActivity
// 指定导航栏背景颜色
.navigationBarColor(R.color.white);
}

}

+ 49
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/PwdEditText.java Просмотреть файл

@@ -0,0 +1,49 @@
package com.huntersun.vkyes.etcopencard.src.widget.vertfiycode;

import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;

import androidx.appcompat.widget.AppCompatEditText;

/**
* Date :2023-03-14
* Description:重写InputConnection 监听返回键
*/
public class PwdEditText extends AppCompatEditText {
private TInputConnection inputConnection;

public PwdEditText(Context context) {
super(context);
init();
}

public PwdEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

public PwdEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init(){
inputConnection = new TInputConnection(null,true);
}

/**
* 当输入法和EditText建立连接的时候会通过这个方法返回一个InputConnection。
* 我们需要代理这个方法的父类方法生成的InputConnection并返回我们自己的代理类。
* */
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
inputConnection.setTarget(super.onCreateInputConnection(outAttrs));
return inputConnection;
}

public void setBackSpaceListener(TInputConnection.BackspaceListener backSpaceLisetener){
inputConnection.setBackspaceListener(backSpaceLisetener);
}
}

+ 61
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/PwdTextView.java Просмотреть файл

@@ -0,0 +1,61 @@
package com.huntersun.vkyes.etcopencard.src.widget.vertfiycode;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;

import androidx.appcompat.widget.AppCompatTextView;

/**
* Date :2023-03-14
* Description:
*/
public class PwdTextView extends AppCompatTextView {
private float radius;

private boolean hasPwd;

public PwdTextView(Context context) {
this(context, null);
}

public PwdTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public PwdTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}


@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

if (hasPwd) {
// 画一个黑色的圆
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, paint);
}
}


public void clearPwd() {
this.hasPwd = false;
invalidate();
}

public void drawPwd(float radius) {
this.hasPwd = true;
if (radius == 0) {
this.radius = getWidth() / 4;
} else {
this.radius = radius;
}
invalidate();
}
}

+ 71
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/TInputConnection.java Просмотреть файл

@@ -0,0 +1,71 @@
package com.huntersun.vkyes.etcopencard.src.widget.vertfiycode;

import android.view.KeyEvent;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;

/**
* Date :2023-03-14
* Description:
*/
public class TInputConnection extends InputConnectionWrapper {

private BackspaceListener mBackspaceListener;

/**
* Initializes a wrapper.
* <p>
* <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
* places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
* has {@code null} in {@code target}.</p>
*
* @param target the {@link InputConnection} to be proxied.
* @param mutable set {@code true} to protect this object from being reconfigured to target
* another {@link InputConnection}. Note that this is ignored while the target is {@code null}.
*/
public TInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}

public interface BackspaceListener {
/**
* @return true 代表消费了这个事件
* */
boolean onBackspace();
}

/**
* 当软键盘删除文本之前,会调用这个方法通知输入框,我们可以重写这个方法并判断是否要拦截这个删除事件。
* 在谷歌输入法上,点击退格键的时候不会调用{@link #sendKeyEvent(KeyEvent event)},
* 而是直接回调这个方法,所以也要在这个方法上做拦截;
* */
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if(mBackspaceListener != null){
if(mBackspaceListener.onBackspace()){
return true;
}
}

return super.deleteSurroundingText(beforeLength, afterLength);
}

public void setBackspaceListener(BackspaceListener backspaceListener) {
this.mBackspaceListener = backspaceListener;
}

/**
* 当在软件盘上点击某些按钮(比如退格键,数字键,回车键等),该方法可能会被触发(取决于输入法的开发者),
* 所以也可以重写该方法并拦截这些事件,这些事件就不会被分发到输入框了
* */
@Override
public boolean sendKeyEvent(KeyEvent event) {
if( event.getKeyCode() == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN){
if(mBackspaceListener != null && mBackspaceListener.onBackspace()){
return true;
}
}
return super.sendKeyEvent(event);
}

}

+ 361
- 0
app/src/main/java/com/huntersun/vkyes/etcopencard/src/widget/vertfiycode/VerificationCodeView.java Просмотреть файл

@@ -0,0 +1,361 @@
package com.huntersun.vkyes.etcopencard.src.widget.vertfiycode;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.huntersun.vkyes.etcopencard.R;

/**
* Date :2023-03-14
* Description:自定义验证码输入框
*/
public class VerificationCodeView extends RelativeLayout {
private LinearLayout containerEt;

private PwdEditText et;
// 输入框数量
private int mEtNumber;
// 输入框的宽度
private int mEtWidth;
//输入框分割线
private Drawable mEtDividerDrawable;
//输入框文字颜色
private int mEtTextColor;
//输入框文字大小
private float mEtTextSize;
//输入框获取焦点时背景
private Drawable mEtBackgroundDrawableFocus;
//输入框没有焦点时背景
private Drawable mEtBackgroundDrawableNormal;
//是否是密码模式
private boolean mEtPwd;
//密码模式时圆的半径
private float mEtPwdRadius;

//存储TextView的数据 数量由自定义控件的属性传入
private PwdTextView[] mPwdTextViews;

private MyTextWatcher myTextWatcher = new MyTextWatcher();


public VerificationCodeView(Context context) {
this(context, null);
}

public VerificationCodeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public VerificationCodeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}

//初始化 布局和属性
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
LayoutInflater.from(context).inflate(R.layout.layout_identifying_code, this);
containerEt = (LinearLayout) this.findViewById(R.id.container_et);
et = (PwdEditText) this.findViewById(R.id.et);

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerificationCodeView, defStyleAttr, 0);
mEtNumber = typedArray.getInteger(R.styleable.VerificationCodeView_icv_et_number, 1);
mEtWidth = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_icv_et_width, 45);
mEtDividerDrawable = typedArray.getDrawable(R.styleable.VerificationCodeView_icv_et_divider_drawable);
mEtTextSize = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_icv_et_text_size, (int) sp2px(16, context));
mEtTextColor = typedArray.getColor(R.styleable.VerificationCodeView_icv_et_text_color, Color.BLACK);
mEtBackgroundDrawableFocus = typedArray.getDrawable(R.styleable.VerificationCodeView_icv_et_bg_focus);
mEtBackgroundDrawableNormal = typedArray.getDrawable(R.styleable.VerificationCodeView_icv_et_bg_normal);
mEtPwd = typedArray.getBoolean(R.styleable.VerificationCodeView_icv_et_pwd, false);
mEtPwdRadius = typedArray.getDimensionPixelSize(R.styleable.VerificationCodeView_icv_et_pwd_radius, 0);
//释放资源
typedArray.recycle();


// 当xml中未配置时 这里进行初始配置默认图片
if (mEtDividerDrawable == null) {
mEtDividerDrawable = context.getResources().getDrawable(R.drawable.shape_divider_identifying);
}

if (mEtBackgroundDrawableFocus == null) {
mEtBackgroundDrawableFocus = context.getResources().getDrawable(R.drawable.shape_icv_et_bg_focus);
}

if (mEtBackgroundDrawableNormal == null) {
mEtBackgroundDrawableNormal = context.getResources().getDrawable(R.drawable.shape_icv_et_bg_normal);
}

initUI();
}

// 初始UI
private void initUI() {
initTextViews(getContext(), mEtNumber, mEtWidth, mEtDividerDrawable, mEtTextSize, mEtTextColor);
initEtContainer(mPwdTextViews);
setListener();
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 设置当 高为 warpContent 模式时的默认值 为 50dp
int mHeightMeasureSpec = heightMeasureSpec;

int heightMode = MeasureSpec.getMode(mHeightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST) {
mHeightMeasureSpec = MeasureSpec.makeMeasureSpec((int) dp2px(50, getContext()), MeasureSpec.EXACTLY);
}

super.onMeasure(widthMeasureSpec, mHeightMeasureSpec);
}


//初始化TextView
private void initTextViews(Context context, int etNumber, int etWidth, Drawable etDividerDrawable, float etTextSize, int etTextColor) {
// 设置 editText 的输入长度
et.setCursorVisible(false);//将光标隐藏
et.setFilters(new InputFilter[]{new InputFilter.LengthFilter(etNumber)}); //最大输入长度
// 设置分割线的宽度
if (etDividerDrawable != null) {
etDividerDrawable.setBounds(0, 0, etDividerDrawable.getMinimumWidth(), etDividerDrawable.getMinimumHeight());
containerEt.setDividerDrawable(etDividerDrawable);
}
mPwdTextViews = new PwdTextView[etNumber];

for (int i = 0; i < mPwdTextViews.length; i++) {
PwdTextView textView = new PwdTextView(context);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, etTextSize);
textView.setTextColor(etTextColor);
textView.setWidth(etWidth);
textView.setHeight(etWidth);
if (i == 0) {
textView.setBackgroundDrawable(mEtBackgroundDrawableFocus);
} else {
textView.setBackgroundDrawable(mEtBackgroundDrawableNormal);
}
textView.setGravity(Gravity.CENTER);
textView.setFocusable(false);

mPwdTextViews[i] = textView;
}
}

//初始化存储TextView 的容器
private void initEtContainer(TextView[] mTextViews) {
for (TextView mTextView : mTextViews) {
containerEt.addView(mTextView);
}
}

private void setListener() {
// 监听输入内容
et.addTextChangedListener(myTextWatcher);

// 监听删除按键
et.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
onKeyDelete();
return true;
}
return false;
}
});
}


// 给TextView 设置文字
private void setText(String inputContent) {
for (int i = 0; i < mPwdTextViews.length; i++) {
PwdTextView tv = mPwdTextViews[i];
if (tv.getText().toString().trim().equals("")) {
if (mEtPwd) {
tv.drawPwd(mEtPwdRadius);
tv.setTextColor(getResources().getColor(R.color.transparent));
}else{
tv.setTextColor(mEtTextColor);
}

tv.setText(inputContent);
// 添加输入完成的监听
if (inputCompleteListener != null) {
inputCompleteListener.inputComplete();
}
tv.setBackgroundDrawable(mEtBackgroundDrawableNormal);
if (i < mEtNumber - 1) {
mPwdTextViews[i + 1].setBackgroundDrawable(mEtBackgroundDrawableFocus);
}
break;
}
}
}

// 监听删除
private void onKeyDelete() {
for (int i = mPwdTextViews.length - 1; i >= 0; i--) {
PwdTextView tv = mPwdTextViews[i];
if (!tv.getText().toString().trim().equals("")) {
if (mEtPwd) {
tv.clearPwd();
}
tv.setText("");
// 添加删除完成监听
if (inputCompleteListener != null) {
inputCompleteListener.deleteContent();
}
tv.setBackgroundDrawable(mEtBackgroundDrawableFocus);
if (i < mEtNumber - 1) {
mPwdTextViews[i + 1].setBackgroundDrawable(mEtBackgroundDrawableNormal);
}
break;
}
}
}


/*
* 获取输入文本
*
* @return string
*/
public String getInputContent() {
StringBuffer buffer = new StringBuffer();
for (TextView tv : mPwdTextViews) {
buffer.append(tv.getText().toString().trim());
}
return buffer.toString();
}

/*
* 删除输入内容
*/
public void clearInputContent() {
for (int i = 0; i < mPwdTextViews.length; i++) {
if (i == 0) {
mPwdTextViews[i].setBackgroundDrawable(mEtBackgroundDrawableFocus);
} else {
mPwdTextViews[i].setBackgroundDrawable(mEtBackgroundDrawableNormal);
}
if (mEtPwd) {
mPwdTextViews[i].clearPwd();
}
mPwdTextViews[i].setText("");
}
}

/*
* 设置输入框个数
*
* @param etNumber
*/
public void setEtNumber(int etNumber) {
this.mEtNumber = etNumber;
et.removeTextChangedListener(myTextWatcher);
containerEt.removeAllViews();
initUI();
}


/*
* 获取输入的位数
*
* @return int
*/
public int getEtNumber() {
return mEtNumber;
}


/*
* 设置是否是密码模式 默认不是
*
* @param isPwdMode
*/
public void setPwdMode(boolean isPwdMode) {
this.mEtPwd = isPwdMode;
}


/*
* 获取输入的EditText 用于外界设置键盘弹出
*
* @return EditText
*/
public EditText getEditText() {
return et;
}

// 输入完成 和 删除成功 的监听
private InputCompleteListener inputCompleteListener;

public void setInputCompleteListener(InputCompleteListener inputCompleteListener) {
this.inputCompleteListener = inputCompleteListener;
}


public interface InputCompleteListener {
void inputComplete();

void deleteContent();
}


public float dp2px(float dpValue, Context context) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpValue, context.getResources().getDisplayMetrics());
}

public float sp2px(float spValue, Context context) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spValue, context.getResources().getDisplayMetrics());
}


private class MyTextWatcher implements 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) {

}

@Override
public void afterTextChanged(Editable editable) {
String inputStr = editable.toString();
if (!TextUtils.isEmpty(inputStr)) {

String[] strArray = inputStr.split("");

for (int i = 0; i < strArray.length; i++) {

// 不能大于输入框个数
if (i > mEtNumber) {
break;
}
setText(strArray[i]);
et.setText("");
}
}
}
}
}

+ 7
- 0
app/src/main/res/drawable-v2/shape_divider_identifying.xml Просмотреть файл

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size
android:width="@dimen/dp_10"
android:height="6dp" />
<solid android:color="#00000000" />
</shape>

+ 28
- 0
app/src/main/res/drawable-v2/shape_icv_et_bg_focus.xml Просмотреть файл

@@ -0,0 +1,28 @@
<!--<?xml version="1.0" encoding="utf-8"?>-->
<!--<shape xmlns:android="http://schemas.android.com/apk/res/android"-->
<!-- android:shape="rectangle">-->
<!-- <solid android:color="@color/white" />-->
<!-- &lt;!&ndash; 大小 &ndash;&gt;-->
<!-- <size-->
<!-- android:width="@dimen/dp_40"-->
<!-- android:height="@dimen/dp_40" />&lt;!&ndash; 宽度和高度 &ndash;&gt;-->
<!-- <corners android:radius="@dimen/dp_5" />-->

<!-- <stroke-->
<!-- android:width="1dp"-->
<!-- android:color="@color/common_accent_color" />-->
<!--</shape>-->

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="-2dp"
android:right="-2dp"
android:left="-2dp">
<shape>
<solid android:color="@color/transparent"/>
<stroke
android:width="1dp"
android:color="@color/common_accent_color"/>
</shape>
</item>
</layer-list>

+ 27
- 0
app/src/main/res/drawable-v2/shape_icv_et_bg_normal.xml Просмотреть файл

@@ -0,0 +1,27 @@
<!--<?xml version="1.0" encoding="utf-8"?>-->
<!--<shape xmlns:android="http://schemas.android.com/apk/res/android"-->
<!-- android:shape="rectangle">-->
<!-- <solid android:color="@color/white" />-->
<!-- &lt;!&ndash; 大小 &ndash;&gt;-->
<!-- <size-->
<!-- android:width="@dimen/dp_40"-->
<!-- android:height="@dimen/dp_40" />&lt;!&ndash; 宽度和高度 &ndash;&gt;-->
<!-- <corners android:radius="@dimen/dp_5" />-->

<!-- <stroke-->
<!-- android:width="1dp"-->
<!-- android:color="#AAAAAA" />-->
<!--</shape>-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="-2dp"
android:right="-2dp"
android:left="-2dp">
<shape>
<solid android:color="@color/transparent"/>
<stroke
android:width="1dp"
android:color="#AAAAAA"/>
</shape>
</item>
</layer-list>

+ 75
- 0
app/src/main/res/layout/activity_forget_pwd_step1.xml Просмотреть файл

@@ -0,0 +1,75 @@
<?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"
style="@style/MatchMatch.Vertical"
android:background="@color/background_color">

<com.hjq.bar.TitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
app:leftIcon="@mipmap/back_black"
app:lineVisible="false"
app:title=""
app:titleColor="@color/black" />

<androidx.core.widget.NestedScrollView
style="@style/MatchWrap">
<LinearLayout style="@style/MatchWrap.Vertical"
android:paddingVertical="@dimen/dp_50"
android:paddingHorizontal="@dimen/dp_20">

<TextView
style="@style/WrapWrap"
android:text="忘记密码"
android:paddingHorizontal="@dimen/dp_20"
android:textColor="@color/color_333333"
android:textSize="@dimen/sp_18"
android:textStyle="bold"/>

<TextView
style="@style/WrapWrap"
android:text="请输入手机号"
android:textSize="@dimen/sp_13"
android:textColor="@color/color_666666"
android:paddingHorizontal="@dimen/dp_20"
android:paddingVertical="@dimen/dp_15"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_marginTop="@dimen/dp_35"
android:background="@drawable/edit_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_15">

<ImageView
android:layout_width="13dp"
android:layout_height="@dimen/dp_20"
android:src="@mipmap/phone" />

<com.hjq.widget.view.ClearEditText
android:id="@+id/et_login_phone"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:background="@null"
android:hint="@string/common_phone_input_hint"
android:inputType="phone"
android:textColorHint="#B3B3B3"
android:textColor="@color/color_333333"
app:regexType="mobile" />
</LinearLayout>

<Button
android:id="@+id/btnConfirm"
style="@style/BtnShortStyle"
android:layout_height="@dimen/dp_40"
android:layout_gravity="center"
android:layout_marginTop="@dimen/dp_30"
android:text="验证手机号"
android:textSize="@dimen/sp_15" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

+ 87
- 0
app/src/main/res/layout/activity_forget_pwd_step2.xml Просмотреть файл

@@ -0,0 +1,87 @@
<?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"
style="@style/MatchMatch.Vertical"
android:background="@color/background_color">

<com.hjq.bar.TitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
app:leftIcon="@mipmap/back_black"
app:lineVisible="false"
app:title=""
app:titleColor="@color/black" />

<androidx.core.widget.NestedScrollView
style="@style/MatchWrap">
<LinearLayout style="@style/MatchWrap.Vertical"
android:paddingVertical="@dimen/dp_50"
android:paddingHorizontal="@dimen/dp_20">

<TextView
style="@style/WrapWrap"
android:text="请输入验证码"
android:paddingHorizontal="@dimen/dp_20"
android:textColor="@color/color_333333"
android:textSize="@dimen/sp_18"
android:textStyle="bold"/>

<TextView
android:id="@+id/tvPhone"
style="@style/WrapWrap"
android:text="验证码已发送至:xxx xxxx xxxx"
android:textSize="@dimen/sp_13"
android:textColor="@color/color_666666"
android:paddingHorizontal="@dimen/dp_20"
android:paddingVertical="@dimen/dp_15"/>

<com.huntersun.vkyes.etcopencard.src.widget.vertfiycode.VerificationCodeView
android:id="@+id/verPwd"
style="@style/MatchWrap"
android:layout_marginTop="@dimen/dp_20"
android:layout_marginHorizontal="@dimen/dp_15"
app:icv_et_bg_focus="@drawable/shape_icv_et_bg_focus"
app:icv_et_bg_normal="@drawable/shape_icv_et_bg_normal"
app:icv_et_divider_drawable="@drawable/shape_divider_identifying"
app:icv_et_number="6"
android:focusable="true"
app:icv_et_pwd="false"
app:icv_et_pwd_radius="3dp"
app:icv_et_text_color="@color/common_accent_color"
app:icv_et_text_size="@dimen/sp_20"
app:icv_et_width="@dimen/dp_40" />

<LinearLayout
style="@style/MatchWrap.Horizontal"
android:paddingHorizontal="@dimen/dp_15"
android:paddingVertical="@dimen/dp_15">

<TextView
android:id="@+id/tvCountDownTime"
style="@style/WrapWrap"
android:text="00"
android:textSize="@dimen/sp_10"
android:textColor="@color/common_accent_color"/>

<TextView
style="@style/WrapWrap"
android:text="秒后可重新发送验证码"
android:textSize="@dimen/sp_10"
android:layout_marginLeft="@dimen/dp_7"
android:textColor="@color/color_666666"/>
</LinearLayout>

<Button
android:id="@+id/btnConfirm"
style="@style/BtnShortStyle"
android:layout_height="@dimen/dp_40"
android:layout_gravity="center"
android:layout_marginTop="@dimen/dp_30"
android:text="下一步"
android:layout_marginHorizontal="@dimen/dp_12"
android:textSize="@dimen/sp_15" />

</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

+ 115
- 0
app/src/main/res/layout/activity_forget_pwd_step3.xml Просмотреть файл

@@ -0,0 +1,115 @@
<?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"
style="@style/MatchMatch.Vertical"
android:background="@color/background_color">

<com.hjq.bar.TitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
app:leftIcon="@mipmap/back_black"
app:lineVisible="false"
app:title=""
app:titleColor="@color/black" />

<androidx.core.widget.NestedScrollView
style="@style/MatchWrap">
<LinearLayout style="@style/MatchWrap.Vertical"
android:paddingVertical="@dimen/dp_50"
android:paddingHorizontal="@dimen/dp_20">

<TextView
style="@style/WrapWrap"
android:text="设置新的密码"
android:paddingHorizontal="@dimen/dp_20"
android:textColor="@color/color_333333"
android:textSize="@dimen/sp_18"
android:textStyle="bold"/>

<TextView
style="@style/WrapWrap"
android:text="重置之前的密码,设置新密码"
android:textSize="@dimen/sp_13"
android:textColor="@color/color_666666"
android:paddingHorizontal="@dimen/dp_20"
android:paddingVertical="@dimen/dp_15"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_marginTop="@dimen/dp_35"
android:background="@drawable/edit_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_15">

<ImageView
android:layout_width="13dp"
android:layout_height="@dimen/dp_20"
android:src="@mipmap/password" />

<com.hjq.widget.view.PasswordEditText
android:id="@+id/etPassword"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="@string/common_password_input_error"
android:imeOptions="actionDone"
android:maxLength="20"
android:singleLine="true"
android:textColorHint="#B3B3B3"
android:textColor="@color/color_333333"/>

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_marginTop="@dimen/dp_15"
android:background="@drawable/edit_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_15">

<ImageView
android:layout_width="13dp"
android:layout_height="@dimen/dp_20"
android:src="@mipmap/password" />

<com.hjq.widget.view.PasswordEditText
android:id="@+id/etAgainPassword"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="请再次输入密码"
android:imeOptions="actionDone"
android:maxLength="20"
android:singleLine="true"
android:textColorHint="#B3B3B3"
android:textColor="@color/color_333333"/>

</LinearLayout>


<TextView
android:id="@+id/tvHintMsg"
style="@style/MatchWrap"
android:textSize="@dimen/sp_10"
android:paddingHorizontal="@dimen/dp_15"
android:paddingVertical="@dimen/dp_15"
android:textColor="#FF5353"
android:text="密码不少于8位,必须同时包含数字、大小写字母和特殊符号"/>

<Button
android:id="@+id/btnConfirm"
style="@style/BtnShortStyle"
android:layout_height="@dimen/dp_40"
android:layout_gravity="center"
android:text="确认更改"
android:textSize="@dimen/sp_15" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

+ 24
- 0
app/src/main/res/layout/layout_identifying_code.xml Просмотреть файл

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:id="@+id/container_et"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:showDividers="middle">

</LinearLayout>

<com.huntersun.vkyes.etcopencard.src.widget.vertfiycode.PwdEditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:inputType="number" />

</RelativeLayout>

+ 23
- 14
app/src/main/res/layout/login_activity.xml Просмотреть файл

@@ -52,7 +52,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_marginHorizontal="@dimen/dp_40"
android:layout_marginHorizontal="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_10"
android:background="@drawable/edit_bg"
android:gravity="center_vertical"
@@ -72,7 +72,6 @@
android:background="@null"
android:hint="@string/common_phone_input_hint"
android:inputType="textVisiblePassword"
android:text="15764350434"
app:regexType="mobile" />

</LinearLayout>
@@ -80,7 +79,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_marginHorizontal="@dimen/dp_40"
android:layout_marginHorizontal="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_20"
android:background="@drawable/edit_bg"
android:gravity="center_vertical"
@@ -102,10 +101,22 @@
android:imeOptions="actionDone"
android:maxLength="20"
android:singleLine="true"
android:text="6517@Qwer" />
/>

</LinearLayout>

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_login_forget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:foreground="?attr/selectableItemBackground"
android:text="@string/login_forget"
android:paddingTop="@dimen/dp_15"
android:paddingRight="@dimen/dp_15"
android:paddingLeft="@dimen/dp_15"
android:paddingBottom="@dimen/dp_10"
android:textColor="@color/common_accent_color" />

<LinearLayout
android:id="@+id/layout_code"
@@ -139,8 +150,6 @@

</LinearLayout>



<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -159,13 +168,13 @@
android:text="手机号登录"
android:textColor="@color/common_accent_color" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_login_forget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@string/login_forget"
android:textColor="@color/common_accent_color" />
<!-- <androidx.appcompat.widget.AppCompatTextView-->
<!-- android:id="@+id/tv_login_forget"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_gravity="end"-->
<!-- android:text="@string/login_forget"-->
<!-- android:textColor="@color/common_accent_color" />-->

</LinearLayout>

@@ -174,7 +183,7 @@
style="@style/ButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_40"
android:layout_marginHorizontal="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_30"
android:text="@string/login_text" />


+ 22
- 0
app/src/main/res/values/styles.xml Просмотреть файл

@@ -350,4 +350,26 @@
<!-- 圆角矩形宽高相等,取较宽高中大值-->
<attr name="mv_isWidthHeightEqual" format="boolean" />
</declare-styleable>
<!-- 自定义验证码输入框-->
<declare-styleable name="VerificationCodeView">
<!--输入框的数量-->
<attr name="icv_et_number" format="integer" />
<!--输入框的宽度-->
<attr name="icv_et_width" format="dimension|reference" />
<!--输入框之间的分割线-->
<attr name="icv_et_divider_drawable" format="reference" />
<!--输入框文字颜色-->
<attr name="icv_et_text_color" format="color|reference" />
<!--输入框文字大小-->
<attr name="icv_et_text_size" format="dimension|reference" />
<!--输入框获取焦点时边框-->
<attr name="icv_et_bg_focus" format="reference" />
<!--输入框没有焦点时边框-->
<attr name="icv_et_bg_normal" format="reference" />
<!--是否是密码模式-->
<attr name="icv_et_pwd" format="boolean" />
<!--密码模式时,圆的半径-->
<attr name="icv_et_pwd_radius" format="dimension|reference" />
</declare-styleable>
</resources>

Загрузка…
Отмена
Сохранить