English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

كود تنفيذ واجهة المستخدم الخاصة بالدخول القوية لـ Android

前言

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

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

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

 
  
 <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"/> 
  
  
  <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> 
  
   
  <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، في هذا EidtText ضبط الرسومات. الرسومات على الجانب الأيسر هي رسومات تلميح الحساب وكلمة المرور، والرسومات على الجانب الأيمن هي رابط حذف واحد. لأن الرسومات في EidtText لا تحتوي على أحداث onClick، لتحقيق تأثير حذف واحد بالضغط يجب استخدام طريقة التدفق OnTouchEvent، لمراقبة أحداث الضغط لتحقيق حذف واحد. عند عدم وجود حروف للحساب وكلمة المرور، يتم تعيين الرسومات على الجانب الأيمن إلى المخفية، وعند وجود حروف يتم تعيين الرسومات إلى العرض. عند الضغط على نطاق الرسومات على الجانب الأيمن، يتم حذف الحروف في السطر الحالي. بذلك يتم تحقيق حذف واحد. بالإضافة إلى ذلك، عند الحاجة إلى تسجيل الدخول بينما يكون الحساب وكلمة المرور فارغين، يتم عرض هذه الأسطر المزعجة.
لا أقول كثيرًا، لكن التعليقات على الكود واضحة.

باقة كوم إكسامبل إي أدمينستراتور تيكستتست; 
استيراد android.content.Context; 
استيراد android.graphics.drawable.Drawable; 
استيراد android.text.Editable; 
استيراد android.text.TextWatcher; 
استيراد android.util.AttributeSet; 
استيراد android.view.MotionEvent; 
import android.view.View; 
استيراد android.view.animation.Animation; 
استيراد android.view.animation.CycleInterpolator; 
import android.view.animation.TranslateAnimation; 
import android.widget.EditText; 
/** 
 * تم إنشاء هذا الكود بواسطة Administrator في 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() { 
 // يحصل على مسافات الجوانب العلوية والسفلية واليسرى واليمنى للعرض 
 Drawable[] drawables = this.getCompoundDrawables(); 
 // يحصل على 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) { 
  //عند وجود حرف يكون صحيحًا 
  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) يعني أرقام الأعمدة من 0 إلى 10، وأرقام الأرقام من 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(); الحصول على drawable للـ View. يقدم getCompoundDrawables() أربعةDrawable، ينسقون الحواف اليسرى، العلوية، اليمنى، والسفلية للـ View

  2. boolean isClean = (event.getX() > (getWidth() - getTotalPaddingRight()))&& (event.getX() < (getWidth() - getPaddingRight())); التحقق من ما إذا كان منطق النقر في نطاق صورة الرمز الأيمن. حيث event.getX() هو حجم الـ X للنقر. التفاصيل في الصورة التالية:


 3. Animation translateAnimation = new TranslateAnimation(0, 10, 0, 10); إعداد حركة الترجيح حيث new TranslateAnimation(0,10,0,10) يعني أرقام الأعمدة من 0 إلى 10، وأرقام الأرقام من 0 إلى 10

 4. this.setOnFocusChangeListener(new FocusChangeListenerImpl()); إعداد تغيير التركيز لجعل التجربة أكثر إنسانية. عند وجود التركيز في هذا السطر ولديه حروف، يتم عرض رمز الحذف السريع. إذا لم يكن التركيز في هذا السطر، يتم إخفاء الرمز.

 5. this.addTextChangedListener(new TextWatcherImpl()); إعداد مستمع التغيير في النص. يحتوي 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}{} لتنفيذ ما نريد. عند استماع إلى تغيير النص، يتم عرض الرمز على الجانب الأيمن.

TextWatcher {
 @Override
 public void afterTextChanged(Editable s) {
 //عند وجود حرف يكون صحيحًا
 boolean isVisible = getText().toString().length() >= 1;
 //عرض الرمز على الجانب الأيمن
 setClearDrawableVisible(isVisible);
 }

الكود التحققعملية التنفيذ:

الفكرة:إعداد 4 ImageView. أولاً، يتم إنشاء 4 أرقام عشوائية بين 0 و10 وتخزينها في مصفوفة. وتم تسجيل الكود التحقق بأكمله. باستخدام طريقة Bitmap.createBitmap، يتم تحويل هذه الأرقام إلى صور وتعيين ألوان عشوائية. عند تحويل كل رقم إلى صورة، يتم تعيين زاوية التدوير العشوائية لجعل هذه الأرقام تظهر بزاوية معينة. يتم إنشاء الكود التحقق.

عملية التحقق من الكود التحقق مجرد محاكاة: مقارنة الكود التحقق المدخل بالكود التحقق المسجل. إذا كانت متطابقة، يتم عرض رسالة صحيحة، وإذا كانت مختلفة، يتم عرض رسالة خطأ. وإعادة تعيين الكود.

النقر على منطقة صورة الكود التحقق أيضًا يعيد تعيين الكود.
تعليقات الكود مفصلة جدًا. سأكتب الكود ~ ~ ~: 

باقة كوم إكسامبل إي أدمينستراتور تيكستتست; 
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]; 
 } 
 // کد تأیید را initializes 
 private void initNum() { 
 numStr=""; 
 numStrTmp=""; 
 for (int i = 0; i < numArray.length; i++) { 
  // عدد تصادفی بین 0 تا 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: البitmap الأصلي الذي سيتم من خلاله قطع الصورة
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); إنشاء أيقونة. 

4.Canvas canvas =newCanvas(bitmap);
v.draw(canvas); رسم الصورة

5.v.measure(widSpec, heiSpec);
//v.layout(0,0, width, height); إعادة رسم حجم الصورة. 

الصور التالية هي صور التشغيل:

عند وجود إدخال، يتم عرض أيقونة الحذف السريع على الجانب الأيمن، وعند فقدان التركيز، يتم إخفاء أيقونة الحذف السريع، بالنقر على تحديث الرمز التحقق من تحديث الرمز التحقق:

لن يتم عرض الصور التالية بشكل مفصل.

تحميل المصدر:http://xiazai.jb51.net/201610/yuanma/Androidlogin(jb51.net).rar

هذا هو نهاية محتويات هذا المقال، نأمل أن تكون قد ساعدتكم في التعلم، ونأمل أيضًا أن تدعموا تعليمات النفخ.

البيان: محتويات هذا المقال تم جمعها من الإنترنت، ملكية المحتويات مملوكة للمساهمين، تم جمع المحتويات من قبل المستخدمين عبر الإنترنت بشكل متعاون، هذا الموقع لا يمتلك حقوق الملكية، لم يتم تعديل المحتويات بشكل يدوي، ولا يتحمل هذا الموقع أي مسؤولية قانونية. إذا اكتشفت محتويات تتضمن حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال # بـ @) لتقديم الشكوى، وقدم الدليل على الدليل، إذا تم التحقق من ذلك، سيتم حذف المحتويات المزعجة فورًا.

أنت قد تحب