在我们的项目中,获取验证码、手机号验证以及密码输入是很常见的小功能。
手机号
1. 布局文件
<EditText
android:id="@+id/et_login_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@null"
android:cursorVisible="true"
android:hint="请输入手机号"
android:inputType="phone"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:singleLine="true"
android:textColor="@color/black"
android:textColorHint="#999799"
android:textSize="16sp" />
2. 校验手机号
/**
* 匹配手机号的规则:[356789]是手机号第二位可能出现的数字
*/
public static final String REGEX_MOBILE = "^[1][356789][0-9]{9}$";
/**
* 校验手机号
* @param mobile
* @return 校验通过返回true,否则返回false
*/
public static boolean isMobile(String mobile) {
return Pattern.matches(REGEX_MOBILE, mobile);
}
验证码
方式一
1.TimeCountDown.java
public class TimeCountDown extends AppCompatTextView {
private static final String TAG = TimeCountDown.class.getSimpleName();
private static final int COUNT_DOWN_START = 1;//开始计时
private static final int COUNT_DOWN_LOADING = 2;//计数中
private static final int COUNT_DOWN_FINISH = 3;//计数完成
private static final int COUNT_DOWN_ERROR = 4;//计数出错
/**
* 倒计时时间为60 s
*/
private int countTime = 60;
/**
* 变量,用来计数当前倒计时的时间
*/
private int mCount;
/**
* 倒计时之前显示的文字
*/
private String beforeCount = "获取验证码";
/**
* 倒计时之后显示的文字
*/
private String afterCount = "秒";
/**
* handler
*/
private Handler mHandler;
private Timer mTimer;
private TimerTask mTimerTask;
private OnTimerCountDownListener onTimerCountDownListener;
public TimeCountDown(Context context) {
super(context);
init();
}
public TimeCountDown(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public void init() {
mCount = countTime;
setText(beforeCount);
mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case COUNT_DOWN_START:
if (null != onTimerCountDownListener) {
onTimerCountDownListener.onCountDownStart();
}
mCount--;
break;
case COUNT_DOWN_LOADING:
if (null != onTimerCountDownListener) {
onTimerCountDownListener.onCountDownLoading(mCount);
}
setText(msg.arg1 + afterCount);
mCount--;
break;
case COUNT_DOWN_FINISH:
if (null != onTimerCountDownListener) {
onTimerCountDownListener.onCountDownFinish();
}
if (mCount < 0) {
//当倒计时时间小于0后,取消计时任务
mTimer.cancel();
setText("重新获取");
mCount = countTime;
}
break;
case COUNT_DOWN_ERROR:
if (null != onTimerCountDownListener) {
onTimerCountDownListener.onCountDownError();
}
break;
}
}
};
}
public void initTimer() {
mTimer = new Timer();
mTimerTask = new TimerTask() {
public void run() {
Log.d(TAG, "当前count:" + mCount);
switch (mCount) {
case 60:
sendMessage(COUNT_DOWN_START, 0);
break;
case -1:
sendMessage(COUNT_DOWN_FINISH, 0);
break;
default:
sendMessage(COUNT_DOWN_LOADING, mCount);
break;
}
}
};
//每隔1秒发送一次空消息
mTimer.schedule(mTimerTask, 0, 1000);
}
private void sendMessage(int flag, int factor) {
Message msg = new Message();
switch (flag) {
case COUNT_DOWN_ERROR:
case COUNT_DOWN_FINISH:
case COUNT_DOWN_START:
break;
case COUNT_DOWN_LOADING:// 计数中
msg.arg1 = factor;
break;
default:
break;
}
msg.what = flag;
mHandler.sendMessage(msg);
}
//这个必须要写,在退出界面时,要取消计时任务,不然,会一直在计时,直到为0.
public void cancel() {
mTimer.cancel();
}
public void setOnTimerCountDownListener(OnTimerCountDownListener listener) {
this.onTimerCountDownListener = listener;
}
public interface OnTimerCountDownListener {
/**
* 计时开始
*/
public void onCountDownStart();
/**
* 计时中
*/
public void onCountDownLoading(int currentCount);
/**
* 计时错误失败
*/
public void onCountDownError();
/**
* 计时完成
*/
public void onCountDownFinish();
}
}
2.代码
/**
* 已开通
*/
(
contentViewId = R.layout.fragment_open,
hasNavigationView = false)
public class OpenFragment extends BaseFragment implements TimeCountDown.OnTimerCountDownListener {
private TimeCountDown countDown;
protected void toHandleMessage(Message msg) {
}
protected void findViewAfterViewCreate() {
countDown = (TimeCountDown) mRootView.findViewById(R.id.countdown);
}
protected void initDataAfterFindView() {
countDown.setOnTimerCountDownListener(this);
countDown.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
countDown.initTimer();
}
});
}
public void onCountDownStart() {
}
public void onCountDownLoading(int currentCount) {
countDown.setClickable(false);
}
public void onCountDownError() {
}
public void onCountDownFinish() {
countDown.setClickable(true);
}
public void onDestroy() {
super.onDestroy();
countDown.cancel();
}
}
方式二
private void startTimer(final TextView smsCodeTv) {
smsCodeTv.setTextColor(Color.parseColor("#a1a1a1"));
smsCodeTv.setText("60s");
smsCodeTv.setEnabled(false);
new Thread() {
public void run() {
for (int i = 59;i >= 0;i--) {
final int second = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
if (second <= 0) {
smsCodeTv.setTextColor(Color.parseColor("#fabf40"));
smsCodeTv.setText("获取验证码");
smsCodeTv.setEnabled(true);
}else {
smsCodeTv.setTextColor(Color.parseColor("#a1a1a1"));
smsCodeTv.setText(second + " s");
}
}
});
}
}
}.start();
}
密码
1. 布局文件
<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:gravity="center"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#11000000"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/edt_Pwd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="输入支付密码"
android:inputType="textPassword"
android:padding="10dp"
android:paddingRight="10dp" />
<ToggleButton
android:id="@+id/tb_show"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginRight="10dp"
android:background="@drawable/toggle_pwd_selector"
android:padding="10dp"
android:textOff=""
android:textOn="" />
</LinearLayout>
</LinearLayout>
toggle_pwd_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/ic_pwd_select"/>
<item android:state_checkable="false" android:drawable="@drawable/ic_pwd_normal"/>
</selector>
2. 代码使用
public class MainActivity extends AppCompatActivity {
private EditText mPwd;
private ToggleButton mShowPwd;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPwd = findViewById(R.id.edt_Pwd);
mShowPwd = findViewById(R.id.tb_show);
mShowPwd.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
//如果选中,显示密码
mPwd.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
//否则隐藏密码
mPwd.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
});
}
}