English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Préambule
Une bonne application nécessite une interface de connexion avec une bonne expérience utilisateur. De nos jours, de nombreuses interfaces de connexion des applications ont des fonctionnalités telles que la suppression d'un nom d'utilisateur et d'un mot de passe en un clic, un avertissement lorsque le nom d'utilisateur et le mot de passe sont vides, et la nécessité de saisir un code de vérification. En lisant les articles des grands experts de csdn, j'ai pensé à écrire une interface de connexion pour apprendre. Beaucoup de choses sont参考 d'autres articles, combinées. Sans plus attendre, voyons maintenant comment cela est réalisé.
ps: Parce que je n'ai pas envie de gratter des images, l'icône du programme est très laid.
Illustration de l'exécution du programme :
Le fichier de conception n'a pas de difficulté.
<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="Saisissez le nom d'utilisateur" 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="Saisissez le mot de passe" 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>
Ensuite, charger des fichiers de conception et initialiser des contrôles.
//bouton de connexion private Button btLogin; //compte private DeletableEditText userEditText; //mot de passe private DeletableEditText psdEditText; //texte numérique du captcha 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();
Processus de mise en œuvre de l'EditText personnalisé :
Planification :Définir deux EidtText, dans chacun de ces EidtText définir des icônes. L'icône de gauche indique l'icône de compte et de mot de passe, et l'icône de droite est l'icône de suppression en un clic. Comme les icônes dans l'EditText n'ont pas d'événement onClick, pour réaliser l'effet de suppression en un clic, il faut utiliser la méthode de rappel OnTouchEvent pour écouter les événements de clic et réaliser la suppression en un clic. Lorsque le compte et le mot de passe ne contiennent pas de caractères, l'icône de suppression en un clic à droite est définie comme cachée, et lorsqu'il y a des caractères, l'icône est définie comme visible. Lorsque vous cliquez sur la gamme de l'icône de droite, supprimez les caractères de la ligne en cours. Cela permet de réaliser la suppression en un clic. De plus, lorsque le compte et le mot de passe sont vides et que vous devez vous connecter, ces deux lignes tremblent pour indiquer un avertissement.
Pas de bavardage, passons directement aux commentaires de code, ils sont clairs.
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; /** * Créé par l'Administrateur le 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() { //Obtenir les marges supérieure, inférieure, gauche et droite de la vue Drawable[] drawables = this.getCompoundDrawables(); // Obtenir le Drawable à la position right // C'est ce que nous avons configuré dans le fichier de mise en page : android:drawableRight mRightDrawable = drawables[2; // Définir l'écouteur de changement de focus this.setOnFocusChangeListener(new FocusChangeListenerImpl()); // Définir l'écouteur de modification de texte EditText this.addTextChangedListener(new TextWatcherImpl()); // Au démarrage, rendez l'icône de nettoyage à droite invisible setClearDrawableVisible(false); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { //Lorsque vous relâchez le clic, vérifiez l'emplacement du clic. Ici, seules les directions de l'axe X sont jugées. case MotionEvent.ACTION_UP: //vérifiez si vous avez cliqué sur la zone d'icône à droite boolean isClean = (event.getX() > (getWidth() - getTotalPaddingRight())) && (event.getX() < (getWidth() - getPaddingRight())); if (isClean) { //Effacer les caractères 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); } } } // Lorsque l'entrée est terminée, vérifiez si l'icône de nettoyage à droite doit être affichée private class TextWatcherImpl implements TextWatcher { @Override public void afterTextChanged(Editable s) { //Lorsqu'il y a des caractères, c'est true boolean isVisible = getText().toString().length() >= 1; //Afficher l'icône de droite 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) { } } // Masquer ou afficher l'icône de clean à droite protected void setClearDrawableVisible(boolean isVisible) { Drawable rightDrawable; if (isVisible) { rightDrawable = mRightDrawable; } else { rightDrawable = null; } // Utiliser le code pour définir l'icône à droite de ce contrôle setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], rightDrawable, getCompoundDrawables()[3 } // Afficher l'animation public void setShakeAnimation() { this.startAnimation(shakeAnimation(5)); } // CycleTimes, le nombre de répétitions de l'animation public Animation shakeAnimation(int CycleTimes) { //Définir l'animation de déplacement, où new TranslateAnimation(0,10,0,10) pour représenter les quatre valeurs : l'axe des X commence à 0-->10, l'axe des Y commence à 0-->10 Animation translateAnimation = new TranslateAnimation(0, 10, 0, 10); //Définir le nombre de répétitions de l'animation translateAnimation.setInterpolator(new CycleInterpolator(CycleTimes)); //Définir l'intervalle de l'animation translateAnimation.setDuration(1000); return translateAnimation; } }
Points à noter :
1.Drawable[] drawables = this.getCompoundDrawables(); cela permet d'obtenir les drawable. getCompoundDrawables() retourne4un objet Drawable, correspondant respectivement aux marges gauche, haute, droite et basse de ce View
2.boolean isClean = (event.getX() > (getWidth() - getTotalPaddingRight())) && (event.getX() < (getWidth() - getPaddingRight())); Juger si la zone cliquée est la portée de l'icône de droite. Dans ce cas, event.getX() est la taille de la coordonnée X de la position de clic. Détails comme dans l'image suivante :
3.Animation translateAnimation = new TranslateAnimation(0, 10, 0, 10); Configurer l'animation de déplacement. new TranslateAnimation(0,10,0,10) pour représenter les quatre valeurs : l'axe des X commence à 0-->10, l'axe des Y commence à 0-->10
4.this.setOnFocusChangeListener(new FocusChangeListenerImpl()); L'objectif de la modification de la focalisation est de rendre cela plus humain. Seulement lorsque le focus est sur cette ligne et qu'il y a des caractères, l'icône d'effacement d'un clic est affichée. Sinon, l'icône est cachée.
5.this.addTextChangedListener(new TextWatcherImpl()); Configurer l'écouteur de changement de texte. new TextWatcher{} contient3méthodes. Ils sont respectivement :
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) {}
Nous n'avons besoin que d'ajouter la méthode à réaliser dans afterTextChanged(){Editable s}{} pour cela. Lorsque nous détectons une variation de texte, nous définissons l'icône de droite pour s'afficher.
TextWatcher { @Override public void afterTextChanged(Editable s) { //Lorsqu'il y a des caractères, c'est true boolean isVisible = getText().toString().length() >= 1; //Afficher l'icône de droite setClearDrawableVisible(isVisible); }
CaptchaLe processus d'implémentation :
Planification :Configurer4ImageView. Premièrement, générer aléatoirement4un10Les nombres à l'intérieur sont stockés dans un tableau. Et enregistrer tout le captcha. En utilisant la méthode createBitmap de Bitmap pour parler de cela4Les nombres sont convertis en images et les couleurs sont définies aléatoirement. Chaque image de nombre est convertie en rotant aléatoirement l'angle de rotation }}4Les icônes numériques sont inclinées d'un certain angle. Le captcha est généré.
Le processus de vérification du captcha est simplement simulé : comparez le captcha entré avec le captcha enregistré. Si ils sont identiques, indiquez que c'est correct, sinon indiquez que c'est incorrect et réinitialisez le captcha.
Cliquez sur la zone de l'image du captcha pour réinitialiser le captcha également.
Les commentaires du code sont très détaillés. Voici le code ~~~~ :
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 { //bouton de connexion private Button btLogin; //compte private DeletableEditText userEditText; //mot de passe private DeletableEditText psdEditText; //texte numérique du captcha 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(); //Réinitialiser la matrice 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(); //Réinitialiser la matrice matrixB.reset(); Bitmap bmNumB = Bitmap.createBitmap(getBitmapFromView(tvHideB,20,50),0,0,20,50,matrixB,true); ivNumB.setImageBitmap(bmNumB); Matrix matrixC = new Matrix(); //Réinitialiser la matrice matrixC.reset(); Bitmap bmNumC = Bitmap.createBitmap(getBitmapFromView(tvHideC,20,50),0,0,20,50,matrixC,true); ivNumC.setImageBitmap(bmNumC); Matrix matrixD = new Matrix(); //Réinitialiser la matrice matrixD.reset(); 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); //Redéfinir la taille de l'image v.measure(widSpec, heiSpec); // v.layout(0, 0, width, height); Bitmap bitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888); //Dessiner l'image Canvas canvas = new Canvas(bitmap); v.draw(canvas); return bitmap; } //Définir un angle d'inclinaison aléatoire private int randomAngle() { return}} 20*(new Random().nextInt(5)-new Random().nextInt(3)); } //générer une couleur au hasard 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]; } //initialiser le code de vérification private void initNum() { numStr=""; numStrTmp=""; for (int i = 0; i < numArray.length; i++) { //généré au hasard10numéro à l'intérieur int numIntTmp = new Random().nextInt(10); //enregistrer chaque code de vérification numStrTmp = String.valueOf(numIntTmp); //enregistrer tout le code de vérification numStr = numStr+numStrTmp; numArray[i] = numIntTmp; } } private class OnClickListenerImpl implements View.OnClickListener { @Override public void onClick(View v) { //quand le bouton cliqué est le bouton de connexion if(v==btLogin){ //vérifier si le caractère du compte est vide, if (TextUtils.isEmpty(userEditText.getText().toString())){ //si vide, indication de secousse userEditText.setShakeAnimation(); Toast.makeText(MainActivity.this,"Le compte ou le mot de passe ne peut pas être vide",Toast.LENGTH_SHORT).show(); } //vérifier si le caractère du mot de passe est vide if (TextUtils.isEmpty(psdEditText.getText().toString())){ //si vide, indication de secousse psdEditText.setShakeAnimation(); Toast.makeText(MainActivity.this,"Le compte ou le mot de passe ne peut pas être vide",Toast.LENGTH_SHORT).show(); } //Vérifier si le code de vérification entré est correct 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("Code de vérification correct !"); }else{ tvCheck.setTextColor(Color.RED); tvCheck.setText("Code de vérification incorrect !"); etCheck.setText(""); setNum(); } } //Si OnClick n'est pas le bouton de connexion, il ne reste que l'image de code de vérification qui a un événement d'écoute. Équivalent à cliquer sur l'image de code de vérification. Changer le code de vérification. }else { setNum(); tvCheck.setVisibility(View.GONE); } } } }
Connaissances à noter :
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 : le bitmap original à partir duquel l'image est coupée
int x : coordonnée x de départ
int y : coordonnée y de départ
int width : la largeur de l'image à couper
int height : la hauteur de l'image à couper
boolean filter lors de la transformation de déplacement, si le paramètre filter est true, le traitement de filtrage peut être effectué, ce qui aide à améliorer la qualité de l'image nouvelle;false, l'ordinateur ne fait pas de traitement de filtrage.
2.intwidSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int heiSpec = View.MeasureSpec.makeMeasureSpec(height,View.MeasureSpec.EXACTLY);
Définir la largeur et la hauteur de la Vue. View.MeasureSpec.EXACTLY signifie que la taille est définie sur la taille réelle de la Vue. C'est-à-dire que la taille de width(height) précédente est aussi grande que possible.
3.Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888); Créer une icône.
4.Canvas canvas =newCanvas(bitmap);
.v.draw(canvas); Dessiner l'image
5.v.measure(widSpec, heiSpec);
//v.layout(0,0, width, height); Redessiner la taille de l'image.
Voici les images du runtime :
Lorsque l'utilisateur saisit quelque chose, l'icône de suppression rapide de droite s'affiche, et l'icône de suppression rapide disparaît lorsque l'utilisateur perd le focus. Cliquez sur le captcha pour mettre à jour le captcha :
Les détails suivants ne seront pas illustrés en détail.
Téléchargement de code source :http://xiazai.jb51.net/201610/yuanma/Androidlogin(jb51.net).rar
Voici la fin de cet article, j'espère qu'il vous sera utile dans vos études, et j'espère que vous soutiendrez également le tutoriel de cri.
Déclaration : le contenu de cet article est extrait du réseau, propriété de ses auteurs respectifs, contribué et téléchargé par les utilisateurs d'Internet. Ce site ne détient pas de droits de propriété, n'a pas été édité par l'homme, et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation, et fournir des preuves pertinentes. Une fois confirmée, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)