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

Реализация мощного интерфейса входа 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=\ 
 /> 
 <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=\ 
 android:drawableRight=\ 
 android:hint="введите аккаунт" 
 android:ems=\ 
 <com.example.administrator.texttest.DeletableEditText> 
 android:id=\ 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 android:textSize="30dp" 
 android:layout_below=\ 
 android:drawableLeft=\ 
 android:drawableRight=\ 
 android:hint=\ 
 android:inputType=\ 
 android:ems=\ 
 <LinearLayout 
 android:id=\ 
 android:orientation=\ 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 android:layout_below=\ 
 <LinearLayout 
  android:id=\ 
  android:orientation=\ 
  android:layout_width="wrap_content" 
  android:layout_height=\ 
  <TextView> 
  android:id=\ 
  android:layout_width=\ 
  android:layout_height=\ 
  android:visibility=\ 
  android:gravity=\ 
  android:textSize="30dp" 
  /> 
  <TextView> 
  android:id=\ 
  android:layout_width=\ 
  android:layout_height=\ 
  android:visibility=\ 
  android:gravity=\ 
  android:textSize="30dp" 
  /> 
  <TextView> 
  android:id=\ 
  android:layout_width=\ 
  android:layout_height=\ 
  android:visibility=\ 
  android:gravity=\ 
  android:textSize="30dp" 
  /> 
  <TextView> 
  android:id=\ 
  android:layout_width=\ 
  android:layout_height=\ 
  android:visibility=\ 
  android:gravity=\ 
  android:textSize="30dp" 
  /> 
 </LinearLayout> 
 <LinearLayout 
  android:id=\ 
  android:orientation=\ 
  android:layout_width="wrap_content" 
  android:layout_height=\ 
  <ImageView 
  android:layout_height=\ 
  android:layout_width=\ 
  android:id=\ 
  <ImageView 
  android:layout_height=\ 
  android:layout_width=\ 
  android:id=\ 
  <ImageView 
  android:layout_height=\ 
  android:layout_width=\ 
  android:id=\ 
  <ImageView 
  android:layout_height=\ 
  android:layout_width=\ 
  android:id=\ 
 </LinearLayout> 
 <LinearLayout 
  android:orientation=\ 
  android:layout_height="wrap_content" 
  android:layout_width=\ 
  <EditText 
  android:layout_height="wrap_content" 
  android:layout_width=\ 
  android:textSize="30dp" 
  android:id=\ 
  android:maxLength=\ 
  android:singleLine=\ 
  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, в каждом из которых устанавливаются значки. Значок слева - это значок подсказки для учетной записи и пароля, а значок справа - это значок одно-click удаления. Поскольку у значков в EidtText нет события onClick, чтобы реализовать эффект одно-click удаления, необходимо использовать метод обратного вызова OnTouchEvent, чтобы监тировать события нажатия и определить реализацию одно-click удаления. Если учетная запись и пароль пусты, значок одно-click удаления справа устанавливается в режим скрытия, а при наличии символов значок устанавливается в режим отображения. При нажатии на значок справа удаляется символ в текущей строке. Таким образом, реализуется одно-click удаление. Кроме того, при попытке входа в систему, когда учетная запись и пароль пусты, эти строки вибрируют в качестве подсказки.
Не будем говорить больше, давайте сразу перейдем к комментариям в коде, они очень ясны.

пакет 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; 
/** 
 * Создано администратором 10 октября 2015 года. 
 */ 
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); 
  } 
  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; 
 } 
  rightDrawable = null; 
 } 
 // Использование кода для установки значка в правом месте контроллера 
 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(); Получение drawable этого View. Метод getCompoundDrawables() возвращает четыре Drawable объекта, которые соответствуют левому, верхнему, правому и нижнему полям этого View

  2.boolean isClean = (event.getX() > (getWidth() - getTotalPaddingRight())) && (event.getX() < (getWidth() - getPaddingRight())); Проверка, находится ли нажатая область в диапазоне правой иконки. где event.getX() это размер X-координаты места нажатия. Подробнее см. рисунок:


 3.Анимация перевода 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()); Установка监тора изменений текста. В 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) {
 //Когда есть символы, значение true
 boolean isVisible = getText().toString().length() >= 1;
 //Отображение правого значка
 setClearDrawableVisible(isVisible);
 }

КапчаПроцесс реализации:

Мысль:Настройка 4 ImageView. Сначала случайным образом генерируется 4 числа от 0 до 10 и хранятся в массиве. Также записывается вся капча. Затем с помощью метода Bitmap.createBitmap преобразуются эти 4 числа в изображения и устанавливаются случайные цвета. При преобразовании каждого числа в изображение случайным образом устанавливается угол поворота, чтобы эти 4 числовых значка были наклонены под определенным углом. Таким образом, капча создается.

Процесс проверки капчи всего лишь имитация: сравнение введенной капчи с записанной. Если они совпадают, то отображается сообщение о правильности, если нет, то о ошибке. Также сбрасывается капча.

Нажатие на область изображения капчи также будет сбрасывать капчу.
Комментарии кода очень详细ные. Давайте посмотрим на код ~~~: 

пакет 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; //Чёрный 
 colorArray[1] = 0xFFFF00FF; // ФИОТ 
 colorArray[2] = 0xFFFF0000; // КРАСНЫЙ 
 colorArray[3] = 0xFF00FF00; // ЗЕЛЕНЫЙ 
 colorArray[4] = 0xFF0000FF; // СИНЕЯ 
 colorArray[5] = 0xFF00FFFF; // ЦИАН 
 int randomColoId = new Random().nextInt(5); 
 return colorArray[randomColoId]; 
 } 
 // Инициализация кода проверки 
 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: исходное bitmap, из которого нужно сделать вырез
int x: начальная координата x
int y: начальная координата y
int width: ширина изображения, которое нужно вырезать
int height: высота изображения, которое нужно вырезать
boolean filter При выполнении не только трансформации перемещения, параметр filter принимает значение true для выполнения фильтрации, что помогает улучшить качество нового изображения; при false компьютер не выполняет фильтрацию. 

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 (во время отправки письма замените # на @) для отчета и предоставьте соответствующие доказательства. Как только будет установлено, что это правда, сайт немедленно удалит подозрительное содержимое, нарушающее авторские права.

Давайте посмотрим, что вам понравится