欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

功能强大的登录界面Android实现代码

程序员文章站 2024-03-04 10:08:05
前言      一个好的应用需要一个有良好的用户体验的登录界面,现如今,许多应用的的登录界面都有着用户名,密码一键删除,用户名...

前言

     一个好的应用需要一个有良好的用户体验的登录界面,现如今,许多应用的的登录界面都有着用户名,密码一键删除,用户名,密码为空提示,以及需要输入验证码的功能。看着csdn上的大牛们的文章,心里想着也写一个登录界面学习学习,许多东西都是参考别的文章,综合起来的。废话少说,接下来看看是如何实现的。 

ps:由于懒得抠图。所以程序的图标很难看。
程序运行时的图示:

功能强大的登录界面Android实现代码

首先是布局文件没有什么难度。

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" 
 android:layout_height="match_parent" android:paddingleft="@dimen/activity_horizontal_margin" 
 android:paddingright="@dimen/activity_horizontal_margin" 
 android:paddingtop="@dimen/activity_vertical_margin" 
 android:paddingbottom="@dimen/activity_vertical_margin" tools:context=".mainactivity"> 
 
 <imageview 
 android:id="@+id/tv_login" 
 android:src="@drawable/ic_launcher" 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 android:layout_alignparenttop="true" 
 android:gravity="center" 
 /> 
 <com.example.administrator.texttest.deletableedittext 
 android:id="@+id/tv_user" 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 android:textsize="30dp" 
 android:layout_below="@id/tv_login" 
 android:drawableleft="@drawable/ic_launcher" 
 android:drawableright="@drawable/ic_launcher" 
 android:hint="请输入账户" 
 android:ems="10"/> 
 <com.example.administrator.texttest.deletableedittext 
 android:id="@+id/tv_psd" 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 android:textsize="30dp" 
 android:layout_below="@id/tv_user" 
 android:drawableleft="@drawable/ic_launcher" 
 android:drawableright="@drawable/ic_launcher" 
 android:hint="请输入密码" 
 android:inputtype="textpassword" 
 android:ems="10"/> 
 <linearlayout 
 android:id="@+id/lyyanzhengma" 
 android:orientation="horizontal" 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 
 android:layout_below="@id/tv_psd"> 
 <linearlayout 
  android:id="@+id/lyverify" 
  android:orientation="horizontal" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content"> 
  <textview 
  android:id="@+id/tvhidea" 
  android:layout_width="70dp" 
  android:layout_height="70dp" 
  android:visibility="gone" 
  android:gravity="center" 
  android:textsize="30dp" 
  /> 
  <textview 
  android:id="@+id/tvhideb" 
  android:layout_width="70dp" 
  android:layout_height="70dp" 
  android:visibility="gone" 
  android:gravity="center" 
  android:textsize="30dp" 
  /> 
  <textview 
  android:id="@+id/tvhidec" 
  android:layout_width="70dp" 
  android:layout_height="70dp" 
  android:visibility="gone" 
  android:gravity="center" 
  android:textsize="30dp" 
  /> 
  <textview 
  android:id="@+id/tvhided" 
  android:layout_width="70dp" 
  android:layout_height="70dp" 
  android:visibility="gone" 
  android:gravity="center" 
  android:textsize="30dp" 
  /> 
 </linearlayout> 
 <linearlayout 
  android:id="@+id/iv_num" 
  android:orientation="horizontal" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content"> 
  <imageview 
  android:layout_height="70dp" 
  android:layout_width="50dp" 
  android:id="@+id/ivnuma"/> 
  <imageview 
  android:layout_height="70dp" 
  android:layout_width="50dp" 
  android:id="@+id/ivnumb"/> 
  <imageview 
  android:layout_height="70dp" 
  android:layout_width="50dp" 
  android:id="@+id/ivnumc"/> 
  <imageview 
  android:layout_height="70dp" 
  android:layout_width="50dp" 
  android:id="@+id/ivnumd"/> 
 </linearlayout> 
 
 <linearlayout 
  android:orientation="horizontal" 
  android:layout_height="wrap_content" 
  android:layout_width="match_parent"> 
  <edittext 
  android:layout_height="wrap_content" 
  android:layout_width="120dp" 
  android:textsize="30dp" 
  android:id="@+id/etcheck" 
  android:maxlength="4" 
  android:singleline="true" 
  android:hint="验证码"/> 
  <textview 
  android:layout_height="wrap_content" 
  android:layout_width="wrap_content" 
  android:text="结果" 
  android:id="@+id/tvcheck" 
  android:textsize="30dp" 
  android:visibility="gone"/> 
 </linearlayout> 
 
  
 </linearlayout> 
 <button 
 android:id="@+id/bt_login" 
 android:text="登 录" 
 android:textsize="30dp" 
 android:layout_below="@id/lyyanzhengma" 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" /> 
 
</relativelayout> 

然后是加载一些布局文件,和一些控件的初始化

//登录按钮 
 private button btlogin; 
 //账户 
 private deletableedittext useredittext; 
 //密码 
 private deletableedittext psdedittext; 
 
 
 //验证码的数字文本 
 private textview tvhidea,tvhideb,tvhidec,tvhided; 
 
 //验证码的图片文本 
 private imageview ivnuma,ivnumb,ivnumc,ivnumd; 
 //验证码输入文本 
 private edittext etcheck; 
 //验证码的检测显示文本 
 private textview tvcheck; 
 
 //存储每个验证码的数字 
 private string numstrtmp = ""; 
 //存储整个验证码的数字 
 private string numstr = ""; 
 
 //存储验证码的数组 
 private int[] numarray = new int[4]; 
 //存储颜色的数组 
 private int[] colorarray = new int[6]; 
 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 setcontentview(r.layout.activity_main); 
 setupviews(); 
 
 } 
 
 private void setupviews() { 
 btlogin = (button) findviewbyid(r.id.bt_login); 
 btlogin.setonclicklistener(new onclicklistenerimpl()); 
 useredittext = (deletableedittext) findviewbyid(r.id.tv_user); 
 psdedittext = (deletableedittext) findviewbyid(r.id.tv_psd); 
 
 
 tvhidea = (textview) findviewbyid(r.id.tvhidea); 
 tvhideb = (textview) findviewbyid(r.id.tvhideb); 
 tvhidec = (textview) findviewbyid(r.id.tvhidec); 
 tvhided = (textview) findviewbyid(r.id.tvhided); 
 
 ivnuma = (imageview) findviewbyid(r.id.ivnuma); 
 ivnumb = (imageview) findviewbyid(r.id.ivnumb); 
 ivnumc = (imageview) findviewbyid(r.id.ivnumc); 
 ivnumd = (imageview) findviewbyid(r.id.ivnumd); 
 
 ivnuma.setonclicklistener(new onclicklistenerimpl()); 
 ivnumb.setonclicklistener(new onclicklistenerimpl()); 
 ivnumc.setonclicklistener(new onclicklistenerimpl()); 
 ivnumd.setonclicklistener(new onclicklistenerimpl()); 
 
 tvcheck = (textview) findviewbyid(r.id.tvcheck); 
 etcheck = (edittext) findviewbyid(r.id.etcheck); 
 
 setnum(); 

自定义edittext的实现过程:

思路:设置两个eidttext,在这个edittext中各设置图标。左边图标为账户和密码的图标提示,右边图标为一键删除 。因为edittext中的图标没有onclick事件,为了实现点击一键删除效果所以要使用ontouchevent回调方法,监听点击事件来判断实现一键删除。当账户和密码没有字符时,右边的一键删除图标设置隐藏,当有字符时,设置图标显示。当点击到右边图标范围时,删除所在行的字符。从而实现一键删除。 此外,当账户和密码为空而要登录时。这两行抖动提示。
废话不多说,直接上代码注释很清楚。

package com.example.administrator.texttest; 
 
import android.content.context; 
import android.graphics.drawable.drawable; 
import android.text.editable; 
import android.text.textwatcher; 
import android.util.attributeset; 
import android.view.motionevent; 
import android.view.view; 
import android.view.animation.animation; 
import android.view.animation.cycleinterpolator; 
import android.view.animation.translateanimation; 
import android.widget.edittext; 
 
/** 
 * created by administrator on 2015-10-10. 
 */ 
public class deletableedittext extends edittext { 
 
 private drawable mrightdrawable; 
 private boolean ishasfocus; 
 
 
 
 public deletableedittext(context context) { 
 this(context, null); 
 } 
 
 public deletableedittext(context context, attributeset attrs) { 
 this(context, attrs, android.r.attr.edittextstyle); 
 } 
 
 public deletableedittext(context context, attributeset attrs, int defstyleattr) { 
 super(context, attrs, defstyleattr); 
 setupviews(); 
 } 
 
 private void setupviews() { 
 
 //取的view的上下左右边距 
 drawable[] drawables = this.getcompounddrawables(); 
 
 // 取得right位置的drawable 
 // 即我们在布局文件中设置的android:drawableright 
 mrightdrawable = drawables[2]; 
 
 // 设置焦点变化的监听 
 this.setonfocuschangelistener(new focuschangelistenerimpl()); 
 // 设置edittext文字变化的监听 
 this.addtextchangedlistener(new textwatcherimpl()); 
 // 初始化时让右边clean图标不可见 
 setcleardrawablevisible(false); 
 
 
 
 } 
 @override 
 public boolean ontouchevent(motionevent event) { 
 switch (event.getaction()) { 
  //当点击松开时判断点击的位置。这里只进行了x轴方向的判断。 
  case motionevent.action_up: 
  //判断是否点击到了右边的图标区域 
  boolean isclean = (event.getx() > (getwidth() - gettotalpaddingright())) 
   && (event.getx() < (getwidth() - getpaddingright())); 
  if (isclean) { 
   //清除字符 
   settext(""); 
  } 
  break; 
 
  default: 
  break; 
 } 
 return super.ontouchevent(event); 
 } 
 
 private class focuschangelistenerimpl implements onfocuschangelistener { 
 @override 
 public void onfocuschange(view v, boolean hasfocus) { 
  ishasfocus = hasfocus; 
  if (ishasfocus) { 
  boolean isvisible = gettext().tostring().length() >= 1; 
  setcleardrawablevisible(isvisible); 
  } else { 
  setcleardrawablevisible(false); 
  } 
 } 
 
 } 
 
 // 当输入结束后判断是否显示右边clean的图标 
 private class textwatcherimpl implements textwatcher { 
 @override 
 public void aftertextchanged(editable s) { 
  //当有字符时为true 
  boolean isvisible = gettext().tostring().length() >= 1; 
  //显示右边的图标 
  setcleardrawablevisible(isvisible); 
 } 
 
 @override 
 public void beforetextchanged(charsequence s, int start, int count, 
     int after) { 
 
 } 
 
 @override 
 public void ontextchanged(charsequence s, int start, int before, 
     int count) { 
 
 } 
 
 } 
 
 // 隐藏或显示右边clean的图标 
 protected void setcleardrawablevisible(boolean isvisible) { 
 drawable rightdrawable; 
 if (isvisible) { 
  rightdrawable = mrightdrawable; 
 } else { 
  rightdrawable = null; 
 } 
 // 使用代码设置该控件right处的图标 
 setcompounddrawables(getcompounddrawables()[0], 
  getcompounddrawables()[1], rightdrawable, 
  getcompounddrawables()[3]); 
 } 
 
 // 显示动画 
 public void setshakeanimation() { 
 this.startanimation(shakeanimation(5)); 
 
 } 
 
 // cycletimes动画重复的次数 
 public animation shakeanimation(int cycletimes) { 
 //设置偏移动画 其中new translateanimation(0,10,0,10)四个值表示为 x坐标从0-->10,y坐标从0-->10 
 animation translateanimation = new translateanimation(0, 10, 0, 10); 
 //设置动画次数 
 translateanimation.setinterpolator(new cycleinterpolator(cycletimes)); 
 //设置动画间隔 
 translateanimation.setduration(1000); 
 return translateanimation; 
 } 
 
} 

其中需要注意的知识:

  1.drawable[] drawables = this.getcompounddrawables(); 得到此view的 drawable. getcompounddrawables()方法得到的有4个drawable对象,分别对应此view的左,上,右,下的边距

  2.boolean isclean = (event.getx() > (getwidth() - gettotalpaddingright()))&& (event.getx() < (getwidth() - getpaddingright()));  判断点击的区域是否为右边图标范围。其中event.getx()为点击的位置的x坐标大小。详细如下图所示:

功能强大的登录界面Android实现代码

 3.animation translateanimation = new translateanimation(0, 10, 0, 10); 设置偏移动画 其中new translateanimation(0,10,0,10)四个值表示为 x坐标从0-->10,y坐标从0-->10

 4.this.setonfocuschangelistener(new focuschangelistenerimpl());设置焦点变化的目的是为了更人性化。当焦点在此行并且有字符时才显示一键删除图标。不在此行时图标隐藏。

 5.this.addtextchangedlistener(new textwatcherimpl()); 设置text变化监听。new textwatcher{}中有3个方法。分别是:

1).public void beforetextchanged(charsequence s, int start, int count,int after) {}
2).public void ontextchanged(charsequence s, int start, int before,int count) {}
3).public void aftertextchanged(editable s) {}
我们只需要在aftertextchanged(){editable s}{}中添加要实现的方法即可。当监听到text变化时,设置右边图标显示。

textwatcher {
 @override
 public void aftertextchanged(editable s) {
 //当有字符时为true
 boolean isvisible = gettext().tostring().length() >= 1;
 //显示右边的图标
 setcleardrawablevisible(isvisible);
 }

验证码的实现过程:

思路:设置4个imageview。 首先随机生成4个10以内的数字存储在数组里。并且记录整个验证码。在利用bitmap.createbitmap方法讲这4个数字转化为图片并且设置随机颜色。每个数字图片转化的时候在随机设置旋转角度使这4个数字图标倾斜一定的角度。 验证码就生成了。

验证验证码的过程只是模拟下: 将输入的验证码跟记录的验证码作比较。相同 提示正确,不同提示错误。并且重置验证码。

点击验证码图片区域也会重置验证码。
代码的注释很详细。上代码~~~~: 

package com.example.administrator.texttest; 
 
import android.graphics.bitmap; 
import android.graphics.canvas; 
import android.graphics.color; 
import android.graphics.matrix; 
import android.support.v7.app.appcompatactivity; 
import android.os.bundle; 
import android.text.textutils; 
import android.view.menu; 
import android.view.menuitem; 
import android.view.view; 
import android.widget.button; 
import android.widget.edittext; 
import android.widget.imageview; 
import android.widget.textview; 
import android.widget.toast; 
 
import java.util.random; 
 
public class mainactivity extends appcompatactivity { 
 //登录按钮 
 private button btlogin; 
 //账户 
 private deletableedittext useredittext; 
 //密码 
 private deletableedittext psdedittext; 
 
 
 //验证码的数字文本 
 private textview tvhidea,tvhideb,tvhidec,tvhided; 
 
 //验证码的图片文本 
 private imageview ivnuma,ivnumb,ivnumc,ivnumd; 
 //验证码输入文本 
 private edittext etcheck; 
 //验证码的检测显示文本 
 private textview tvcheck; 
 
 //存储每个验证码的数字 
 private string numstrtmp = ""; 
 //存储整个验证码的数字 
 private string numstr = ""; 
 
 //存储验证码的数组 
 private int[] numarray = new int[4]; 
 //存储颜色的数组 
 private int[] colorarray = new int[6]; 
 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 setcontentview(r.layout.activity_main); 
 setupviews(); 
 
 } 
 
 private void setupviews() { 
 btlogin = (button) findviewbyid(r.id.bt_login); 
 btlogin.setonclicklistener(new onclicklistenerimpl()); 
 useredittext = (deletableedittext) findviewbyid(r.id.tv_user); 
 psdedittext = (deletableedittext) findviewbyid(r.id.tv_psd); 
 
 
 tvhidea = (textview) findviewbyid(r.id.tvhidea); 
 tvhideb = (textview) findviewbyid(r.id.tvhideb); 
 tvhidec = (textview) findviewbyid(r.id.tvhidec); 
 tvhided = (textview) findviewbyid(r.id.tvhided); 
 
 ivnuma = (imageview) findviewbyid(r.id.ivnuma); 
 ivnumb = (imageview) findviewbyid(r.id.ivnumb); 
 ivnumc = (imageview) findviewbyid(r.id.ivnumc); 
 ivnumd = (imageview) findviewbyid(r.id.ivnumd); 
 
 ivnuma.setonclicklistener(new onclicklistenerimpl()); 
 ivnumb.setonclicklistener(new onclicklistenerimpl()); 
 ivnumc.setonclicklistener(new onclicklistenerimpl()); 
 ivnumd.setonclicklistener(new onclicklistenerimpl()); 
 
 
 
 tvcheck = (textview) findviewbyid(r.id.tvcheck); 
 etcheck = (edittext) findviewbyid(r.id.etcheck); 
 
 
 
 
 setnum(); 
 
 
 
 
 } 
 private void setnum() { 
 initnum(); 
 tvhidea.settext("" + numarray[0]); 
 tvhidea.settextcolor(randomcolor()); 
 tvhideb.settext("" + numarray[1]); 
 tvhideb.settextcolor(randomcolor()); 
 tvhidec.settext("" + numarray[2]); 
 tvhidec.settextcolor(randomcolor()); 
 tvhided.settext("" + numarray[3]); 
 tvhided.settextcolor(randomcolor()); 
 
 
 matrix matrixa = new matrix(); 
 //重设矩阵 
 matrixa.reset(); 
 matrixa.setrotate(randomangle()); 
 bitmap bmnuma = bitmap.createbitmap(getbitmapfromview(tvhidea,20,50),0,0,20,50,matrixa,true); 
 ivnuma.setimagebitmap(bmnuma); 
 
 matrix matrixb = new matrix(); 
 //重设矩阵 
 matrixb.reset(); 
 matrixb.setrotate(randomangle()); 
 bitmap bmnumb = bitmap.createbitmap(getbitmapfromview(tvhideb,20,50),0,0,20,50,matrixb,true); 
 ivnumb.setimagebitmap(bmnumb); 
 
 matrix matrixc = new matrix(); 
 //重设矩阵 
 matrixc.reset(); 
 matrixc.setrotate(randomangle()); 
 bitmap bmnumc = bitmap.createbitmap(getbitmapfromview(tvhidec,20,50),0,0,20,50,matrixc,true); 
 ivnumc.setimagebitmap(bmnumc); 
 
 matrix matrixd = new matrix(); 
 //重设矩阵 
 matrixd.reset(); 
 matrixd.setrotate(randomangle()); 
 bitmap bmnumd = bitmap.createbitmap(getbitmapfromview(tvhided,20,50),0,0,20,50,matrixd,true); 
 ivnumd.setimagebitmap(bmnumd); 
 
 } 
 
 private bitmap getbitmapfromview(view v,int width,int height ) { 
 int widspec = view.measurespec.makemeasurespec(width,view.measurespec.exactly); 
 int heispec = view.measurespec.makemeasurespec(height,view.measurespec.exactly); 
 //重新绘制图片大小 
 v.measure(widspec, heispec); 
 // 
 v.layout(0, 0, width, height); 
 bitmap bitmap = bitmap.createbitmap(width,height, bitmap.config.argb_8888); 
 
 //画出图片 
 canvas canvas = new canvas(bitmap); 
 v.draw(canvas); 
 
 return bitmap; 
 
 } 
 
 
 //设置随机倾斜的角度 
 private int randomangle() { 
 
 
 return 20*(new random().nextint(5)-new random().nextint(3)); 
 } 
 
 
 
 //随机生成颜色 
 private int randomcolor() { 
 colorarray[0]=0xff000000; //black 
 colorarray[1] = 0xffff00ff; // magenta 
 colorarray[2] = 0xffff0000; // red 
 colorarray[3] = 0xff00ff00; // green 
 colorarray[4] = 0xff0000ff; // blue 
 colorarray[5] = 0xff00ffff; // cyan 
 int randomcoloid = new random().nextint(5); 
 return colorarray[randomcoloid]; 
 
 
 
 
 } 
 //初始化验证码 
 private void initnum() { 
 numstr=""; 
 numstrtmp=""; 
 for (int i = 0; i < numarray.length; i++) { 
  //随机生成10以内数字 
  int numinttmp = new random().nextint(10); 
  //保存各个验证码 
  numstrtmp = string.valueof(numinttmp); 
  //保存整个验证码 
  numstr = numstr+numstrtmp; 
  numarray[i] = numinttmp; 
 } 
 
 } 
 
 private class onclicklistenerimpl implements view.onclicklistener { 
 @override 
 public void onclick(view v) { 
  //当点击的为登录按钮时 
  if(v==btlogin){ 
  //判断账户字符是否为空, 
  if (textutils.isempty(useredittext.gettext().tostring())){ 
   //为空时抖动提示 
   useredittext.setshakeanimation(); 
   toast.maketext(mainactivity.this,"账户或密码不能为空",toast.length_short).show(); 
  } 
  //判断密码字符是否为空 
  if (textutils.isempty(psdedittext.gettext().tostring())){ 
   //为空时抖动提示 
   psdedittext.setshakeanimation(); 
   toast.maketext(mainactivity.this,"账户或密码不能为空",toast.length_short).show(); 
  } 
 
  //验证输入的验证码是否正确 
  if(etcheck.gettext().tostring()!=null&&etcheck.gettext().tostring().trim().length()>0){ 
   tvcheck.setvisibility(view.visible); 
   if (numstr.equals(etcheck.gettext().tostring())){ 
   tvcheck.settextcolor(color.green); 
   tvcheck.settext("验证码正确!"); 
   }else{ 
   tvcheck.settextcolor(color.red); 
   tvcheck.settext("验证码错误!"); 
   etcheck.settext(""); 
   setnum(); 
   } 
  } 
  //如果onclick不是登录按钮时只剩下验证码图片有监听事件。等同于点击验证码图片。改变验证码。 
  }else { 
  setnum(); 
  tvcheck.setvisibility(view.gone); 
  } 
 
 
 } 
 } 
} 

需要注意的知识:
1.bitmap.createbitmap(getbitmapfromview(tvhidea,20,50),0,0,20,50,matrixa,true); 
bitmap.createbitmap(bitmap source, int x, int y, int width, int height,matrix m, boolean filter)
bitmap source:要从中截图的原始位图
int x:  起始x坐标
int y:起始y坐标
int width:  要截的图的宽度
int height:要截的图的高度
boolean filter 当进行的不只是平移变换时,filter参数为true可以进行滤波处理,有助于改善新图像质量;flase时,计算机不做过滤处理。 

2.intwidspec = view.measurespec.makemeasurespec(width,view.measurespec.exactly);
  int heispec = view.measurespec.makemeasurespec(height,view.measurespec.exactly);
 设置view的宽和高。view.measurespec.exactly 指的是设置为实际view的大小。即前面的width(height)为多大就为多大。

3.bitmap.createbitmap(width,height, bitmap.config.argb_8888); create一个图标。 

4.canvas canvas =newcanvas(bitmap);
v.draw(canvas);  画出图片

5.v.measure(widspec, heispec);
//v.layout(0,0, width, height);  重新绘制图片的大小。 

后面是运行时的图片:

当有输入时右边的一键删除图标显示、当失去焦点时一键删除图标隐藏、点击验证码更新验证码:

功能强大的登录界面Android实现代码

功能强大的登录界面Android实现代码

后面的就不详细图示了。

源码下载:http://xiazai.jb51.net/201610/yuanma/androidlogin(jb51.net).rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。