【Android】登录界面的实现
程序员文章站
2024-03-22 23:01:16
...
资料来源:https://github.com/tyzlmjj/AndroidUI/tree/master/ClearEditText
先把ClearEditText.java和PasswordEditText.java复制到java/包名/中,然后在布局文件中写入
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<ImageView/>
<包名.ClearEditText
android:hint="请输入注册手机号/账号"
android:theme="@style/MyEditText"
/>
<包名.PasswordEditText
android:hint="请输入密码"
android:textSize="12sp"
android:inputType="numberPassword"
android:theme="@style/MyEditText"
/>
<Button
android:text="登录"
/>
<LinearLayout>
<TextView
android:text="忘记密码?"
/>
<TextView
android:text="注册"
/>
</LinearLayout>
</LinearLayout>
改变下划线的颜色,灰色和黄色
values/styles.xml
<resources>
<style
name="MyEditText"
parent="Theme.AppCompat.Light">
<item name="colorControlNormal">#a4a4a3</item>
<item name="colorControlActivated">#febf22</item>
</style>
</resources>
实现的效果是,输入内容就出现“x”,当密码输入到达6位时,登录按钮变色,然后点击登录会提示抖动密码错误
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by 123 on 2017/08/07.
*/
public class LoginActivity extends Activity implements View.OnClickListener{
private ClearEditText mAccountEditText;
private ClearEditText mPasswordEditText;
private Button mLoginButton;
private TextView mForgetPasswordTextView;
private TextView mSignTextView;
private String mAccountString;
private String mPasswordString;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
setContentView(R.layout.login_layout);
initView();
intiData();
initEvent();
}
private void initView(){
mAccountEditText=findViewById(R.id.id_login_account_edit_text);
mPasswordEditText=findViewById(R.id.id_login_password_edit_text);
mLoginButton=findViewById(R.id.id_login_login_button);
mForgetPasswordTextView=findViewById(R.id.id_login_forget_password_text_view);
mSignTextView=findViewById(R.id.id_login_sign_text_view);
}
private void intiData(){
mPasswordString=mPasswordEditText.getText().toString();
}
private void initEvent(){
mLoginButton.setOnClickListener(this);
mLoginButton.setClickable(false);
mForgetPasswordTextView.setOnClickListener(this);
mSignTextView.setOnClickListener(this);
//edit监听事件
mPasswordEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if (editable.toString().length()>5){
setLoginButton(1);
}
else setLoginButton(0);
}
});
}
private void setLoginButton(int effective){
//按键有效
if (effective==1){
mLoginButton.setTextColor(Color.parseColor("#000000"));//黑
mLoginButton.setBackgroundColor(Color.parseColor("#febf22"));//黄杖
mLoginButton.setClickable(true);
}else {
mLoginButton.setClickable(false);
mLoginButton.setTextColor(Color.parseColor("#ffffff"));//白
mLoginButton.setBackgroundColor(Color.parseColor("#a4a4a3"));//灰
}
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.id_login_login_button:
mPasswordEditText.setError("密码输入错误");
mPasswordEditText.startShakeAnimation();
break;
case R.id.id_login_sign_text_view:
mAccountString=mAccountEditText.getText().toString();
Bundle bundle=new Bundle();
bundle.putString("account key",mAccountString);
//Intent intent=new Intent(this,SignActivity.class);
//intent.putExtra("login bundle",bundle);
//startActivity(intent);
break;
case R.id.id_login_forget_password_text_view:
pf("R.id.id_login_forget_password_text_view");
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
ActivityCollector.finishAll();
System.exit(0);
return true;
}
return super.onKeyDown(keyCode, event);
}
private void pf(String string){
Toast.makeText(this, string,Toast.LENGTH_SHORT).show();
}
}
ClearEditText.java
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.Animation;
import android.view.animation.CycleInterpolator;
import android.view.animation.TranslateAnimation;
public class ClearEditText extends AppCompatEditText {
//按钮资源
private final int CLEAR = R.drawable.clearfill;
//动画时长
private final int ANIMATOR_TIME = 200;
//按钮左右间隔,单位DP
private final int INTERVAL = 5;
//清除按钮宽度,单位DP
private final int WIDTH_OF_CLEAR = 23;
//间隔记录
private int Interval;
//清除按钮宽度记录
private int mWidth_clear;
//右内边距
private int mPaddingRight;
//清除按钮的bitmap
private Bitmap mBitmap_clear;
//清除按钮出现动画
private ValueAnimator mAnimator_visible;
//消失动画
private ValueAnimator mAnimator_gone;
//是否显示的记录
private boolean isVisible = false;
//右边添加其他按钮时使用
private int mRight = 0;
public ClearEditText(final Context context) {
super(context);
init(context);
}
public ClearEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ClearEditText(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mBitmap_clear = createBitmap(CLEAR,context);
Interval = dp2px(INTERVAL);
mWidth_clear = dp2px(WIDTH_OF_CLEAR);
mPaddingRight = Interval + mWidth_clear + Interval ;
mAnimator_gone = ValueAnimator.ofFloat(1f, 0f).setDuration(ANIMATOR_TIME);
mAnimator_visible = ValueAnimator.ofInt(mWidth_clear + Interval,0).setDuration(ANIMATOR_TIME);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//设置内边距
setPadding(getPaddingLeft(), getPaddingTop(), mPaddingRight+ mRight, getPaddingBottom());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));//抗锯齿
if (mAnimator_visible.isRunning()) {
int x = (int) mAnimator_visible.getAnimatedValue();
drawClear(x,canvas);
invalidate();
}else if (isVisible){
drawClear(0,canvas);
}
if(mAnimator_gone.isRunning()){
float scale = (float) mAnimator_gone.getAnimatedValue();
drawClearGone(scale, canvas);
invalidate();
}
}
/**
* 绘制清除按钮出现的图案
* @param translationX 水平移动距离
* @param canvas
*/
protected void drawClear( int translationX,Canvas canvas){
int right = getWidth()+getScrollX() - Interval - mRight +translationX;
int left = right-mWidth_clear;
int top = (getHeight()-mWidth_clear)/2;
int bottom = top + mWidth_clear;
Rect rect = new Rect(left,top,right,bottom);
canvas.drawBitmap(mBitmap_clear, null, rect, null);
}
/**
* 绘制清除按钮消失的图案
* @param scale 缩放比例
* @param canvas
*/
protected void drawClearGone( float scale,Canvas canvas){
int right = (int) (getWidth()+getScrollX()- Interval - mRight -mWidth_clear*(1f-scale)/2f);
int left = (int) (getWidth()+getScrollX()- Interval - mRight -mWidth_clear*(scale+(1f-scale)/2f));
int top = (int) ((getHeight()-mWidth_clear*scale)/2);
int bottom = (int) (top + mWidth_clear*scale);
Rect rect = new Rect(left,top,right,bottom);
canvas.drawBitmap(mBitmap_clear, null, rect, null);
}
/**
* 开始清除按钮的显示动画
*/
private void startVisibleAnimator() {
endAnaimator();
mAnimator_visible.start();
invalidate();
}
/**
* 开始清除按钮的消失动画
*/
private void startGoneAnimator() {
endAnaimator();
mAnimator_gone.start();
invalidate();
}
/**
* 结束所有动画
*/
private void endAnaimator(){
mAnimator_gone.end();
mAnimator_visible.end();
}
/**
* Edittext内容变化的监听
* @param text
* @param start
* @param lengthBefore
* @param lengthAfter
*/
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
if(text.length()>0) {
if (!isVisible) {
isVisible = true;
startVisibleAnimator();
}
}else{
if (isVisible) {
isVisible = false;
startGoneAnimator();
}
}
}
/**
* 触控执行的监听
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
boolean touchable = ( getWidth() - Interval - mRight - mWidth_clear < event.getX() ) && (event.getX() < getWidth() - Interval - mRight);
if (touchable) {
setError(null);
this.setText("");
}
}
return super.onTouchEvent(event);
}
/**
* 开始晃动动画
*/
public void startShakeAnimation(){
if(getAnimation() == null){
this.setAnimation(shakeAnimation(4));
}
this.startAnimation(getAnimation());
}
/**
* 晃动动画
* @param counts 0.5秒钟晃动多少下
* @return
*/
private Animation shakeAnimation(int counts){
Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
translateAnimation.setInterpolator(new CycleInterpolator(counts));
translateAnimation.setDuration(500);
return translateAnimation;
}
/**
* 给图标染上当前提示文本的颜色并且转出Bitmap
* @param resources
* @param context
* @return
*/
public Bitmap createBitmap(int resources, Context context) {
final Drawable drawable = ContextCompat.getDrawable(context, resources);
final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(wrappedDrawable, getCurrentHintTextColor());
return drawableToBitamp(wrappedDrawable);
}
/**
* drawable转换成bitmap
* @param drawable
* @return
*/
private Bitmap drawableToBitamp(Drawable drawable)
{
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}
public int dp2px(float dipValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
//----------------以下方法为方便子类继承,只使用ClearEditText就没有用处---------------------------------------------------------------------
public int getInterval() {
return Interval;
}
public int getmWidth_clear() {
return mWidth_clear;
}
public Bitmap getmBitmap_clear() {
return mBitmap_clear;
}
public void addRight(int right){
mRight += right;
}
}
PasswordEditText .java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Created by 家杰 on 2015/11/20.
*/
public class PasswordEditText extends ClearEditText{
//资源
private final int INVISIBLE = R.drawable.close;
private final int VISIBLE = R.drawable.open;
//按钮宽度dp
private int mWidth;
//按钮的bitmap
private Bitmap mBitmap_invisible;
private Bitmap mBitmap_visible;
//间隔
private int Interval;
//内容是否可见
private boolean isVisible = false;
public PasswordEditText(final Context context) {
super(context);
init(context);
}
public PasswordEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PasswordEditText(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
setSingleLine();
//设置EditText文本为隐藏的(注意!需要在setSingleLine()之后调用)
setTransformationMethod(PasswordTransformationMethod.getInstance());
mWidth = getmWidth_clear();
Interval = getInterval();
addRight(mWidth+Interval);
mBitmap_invisible = createBitmap(INVISIBLE,context);
mBitmap_visible = createBitmap(VISIBLE,context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int right = getWidth()+getScrollX()- Interval ;
int left = right-mWidth;
int top = (getHeight()-mWidth)/2;
int bottom = top + mWidth;
Rect rect = new Rect(left,top,right,bottom);
if(isVisible){
canvas.drawBitmap(mBitmap_visible, null, rect, null);
}else{
canvas.drawBitmap(mBitmap_invisible, null, rect, null);
}
}
/**
* 改写父类的方法
*/
@Override
protected void drawClear(int translationX, Canvas canvas) {
float scale = 1f - (float)(translationX)/(float)(getmWidth_clear()+Interval);
int right = (int) (getWidth()+getScrollX()- Interval-mWidth-Interval -getmWidth_clear()*(1f-scale)/2f);
int left = (int) (getWidth()+getScrollX()- Interval-mWidth-Interval -getmWidth_clear()*(scale+(1f-scale)/2f));
int top = (int) ((getHeight()-getmWidth_clear()*scale)/2);
int bottom = (int) (top + getmWidth_clear()*scale);
Rect rect = new Rect(left,top,right,bottom);
canvas.drawBitmap(getmBitmap_clear(), null, rect, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
boolean touchable = ( getWidth() - mWidth - Interval < event.getX() ) && (event.getX() < getWidth() - Interval);
if (touchable) {
isVisible = !isVisible;
if (isVisible){
//设置EditText文本为可见的
setTransformationMethod(HideReturnsTransformationMethod.getInstance());
}else{
//设置EditText文本为隐藏的
setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
}
return super.onTouchEvent(event);
}
}