最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義短信驗(yàn)證碼組件

 更新時(shí)間:2021年01月28日 11:27:53   作者:Unknown world  
這篇文章主要為大家詳細(xì)介紹了Android自定義短信驗(yàn)證碼組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

Android自定義短信驗(yàn)證碼組件,供大家參考,具體內(nèi)容如下

效果圖

1.布局實(shí)現(xiàn)

因?yàn)橐霉鈽?biāo),所以我用TextView代替了EditText,每一行顯示的驗(yàn)證碼個(gè)數(shù)由用戶決定,所以我這里用線性布局的權(quán)重,對(duì)TextView進(jìn)行控制寬度等分,然后設(shè)置選中和未選中當(dāng)前TextView的底部邊框,設(shè)置高亮顏色背景

2.接受用戶輸入

我這里使用了TextView,但是怎么接受用戶輸入的值呢。這里我直接繼承了RelativeLayout,然后添加了一個(gè)透明的EditText,覆蓋在這幾個(gè)TextView上面,用戶就可以點(diǎn)擊喚起鍵盤輸入

3.TextView如何顯示值和刪除值

我這里設(shè)置EditText的TextColor和BackgroundColor為Color.TRANSPARENT 透明,然后監(jiān)聽(tīng)EditText的addTextChangedListener事件和setOnKeyListener按鍵刪除事件,然后把值添加到TextView上,就能實(shí)現(xiàn)了,然后在寫(xiě)一個(gè)對(duì)外的接口。獲取到輸入的驗(yàn)證碼。

4.添加閃爍的動(dòng)畫(huà)

我這里使用了ObjectAnimator,初始化給每個(gè)TextView添加動(dòng)畫(huà),然后在輸入的時(shí)候給當(dāng)前的TextView啟動(dòng)動(dòng)畫(huà),取消其他TextView動(dòng)畫(huà)

具體源碼如下:

/**
 * @author wu_ming_zhi_bei
 * @date 2021/1/27 15:00
 * @Notes
 */
public class VerificationCodeView extends RelativeLayout {
  private Context mContext;
  private RelativeLayout.LayoutParams layoutParams;
  private int num = 4;//驗(yàn)證碼數(shù)量
  private int codeSize;//字體大小
  private int codeColor;//字體顏色
  private List<TextView> tvs = new ArrayList<>();
  private List<String> codes = new ArrayList<>();
  private EditText etCode;
  private InputMethodManager imm;
  List<ObjectAnimator> animators = new ArrayList<>();

  public VerificationCodeView(Context context) {
    this(context,null);
  }

  public VerificationCodeView(Context context, AttributeSet attrs) {
    this(context,attrs,0);
  }

  public VerificationCodeView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context,attrs);
  }

  private void init(Context context, AttributeSet attrs) {
    this.mContext = context;
    imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);

    TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.VerificationCodeView);
    num = a.getInteger(R.styleable.VerificationCodeView_num,4);
    codeSize = a.getDimensionPixelSize(R.styleable.VerificationCodeView_codeSize,18);
    codeColor = a.getColor(R.styleable.VerificationCodeView_codeColor,getResources().getColor(R.color.theme_color));
    //初始化一個(gè)大的LinearLayout來(lái)存放驗(yàn)證碼
    LinearLayout codeBox = new LinearLayout(mContext);
    codeBox.setOrientation(LinearLayout.HORIZONTAL);
    codeBox.setGravity(Gravity.CENTER);
    //添加方塊
    for(int i=0;i<num;i++){
      TextView tv = new TextView(mContext);
      tv.setTextSize(codeSize);
      tv.setTextColor(codeColor);
      tv.setGravity(Gravity.CENTER);
      tv.setPadding(0,0,0,10);
      LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
          LayoutParams.MATCH_PARENT,
          LayoutParams.MATCH_PARENT, 1);
      param.gravity = Gravity.CENTER;
      param.rightMargin = 20;
      param.leftMargin = 20;
      param.topMargin = 20;
      param.bottomMargin = 20;
      tv.setLayoutParams(param);
      //默認(rèn)第一個(gè)選中
      if(i==0){
        tv.setText("|");
        tv.setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom));
      }else{
        tv.setBackground(mContext.getResources().getDrawable(R.drawable.code_border_bottom));
      }
      codeBox.addView(tv);
      tvs.add(tv);//添加到數(shù)組
    }
    layoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    //添加codebox的位置在組件的最上面
    layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP,TRUE);
    layoutParams.setMargins(60,0,60,0);
    codeBox.setLayoutParams(layoutParams);

    //添加Edit
    etCode = new EditText(mContext);
    etCode.setLayoutParams(layoutParams);
    etCode.setLines(1);
    etCode.setMaxLines(1);
    etCode.setTextColor(Color.TRANSPARENT);
    etCode.setBackgroundColor(Color.TRANSPARENT);
    etCode.setCursorVisible(false);
    //添加edit監(jiān)聽(tīng)
    etCode.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 != null && editable.length()>0) {
          etCode.setText("");//清空數(shù)據(jù)
          if(codes.size() < num){
            codes.add(editable.toString());
            showCode();
          }
        }
      }
    });

    // 監(jiān)聽(tīng)驗(yàn)證碼刪除按鍵
    etCode.setOnKeyListener(new View.OnKeyListener() {
      @Override
      public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
        if (keyCode == KeyEvent.KEYCODE_DEL && keyEvent.getAction() == KeyEvent.ACTION_DOWN && codes.size()>0) {
          codes.remove(codes.size()-1);
          showCode();
          return true;
        }
        return false;
      }
    });
    addView(codeBox);
    addView(etCode);
    addAnimation();//添加?xùn)|安湖
    setTwinkle();//開(kāi)啟動(dòng)畫(huà)
  }

  //顯示驗(yàn)證碼
  private void showCode(){
    int size = codes.size();//1 6
    for(int i=0;i<num;i++){
      if(size>i){
        tvs.get(i).setText(codes.get(i));//添加到textview
      }else if(size==i){
        tvs.get(i).setText("|");
      }else{
        tvs.get(i).setText("");
      }
    }
    etCode.setFocusable(true);
    etCode.requestFocus();
    etCode.setFocusableInTouchMode(true);
    etCode.requestFocusFromTouch();
    setTwinkle();//動(dòng)畫(huà)
    callBack();//回調(diào)

  }

  private void showColor(){
    int size = codes.size();
    if(size==0){
      tvs.get(0).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom));
    }else{
      for(int i=0;i<tvs.size();i++){
        if(i==size-1){
          tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom));
        }else{
          tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_bottom));
        }
      }
    }
  }

  /**
   * 回調(diào)
   */
  private void callBack(){
    if(onInputListener==null){
      return;
    }
    if(codes.size()==num){
      onInputListener.onSucess(getPhoneCode());
    }else{
      onInputListener.onInput();
    }
  }

  //定義回調(diào)
  public interface OnInputListener{
    void onSucess(String code);
    void onInput();
  }
  private OnInputListener onInputListener;
  public void setOnInputListener(OnInputListener onInputListener){
    this.onInputListener = onInputListener;
  }

  /**
   * 獲得手機(jī)號(hào)驗(yàn)證碼
   * @return 驗(yàn)證碼
   */
  public String getPhoneCode(){
    StringBuilder sb = new StringBuilder();
    for (String code : codes) {
      sb.append(code);
    }
    return sb.toString();
  }


  /**
   * 顯示鍵盤
   */
  public void showSoftInput(){
    //顯示軟鍵盤
    if(imm!=null && etCode!=null) {
      etCode.postDelayed(new Runnable() {
        @Override
        public void run() {
          imm.showSoftInput(etCode, 0);
        }
      },200);
    }
  }

  /**
   * 隱藏鍵盤
   */
  public void hideSoftInput(){
    //顯示軟鍵盤
    if(imm!=null && etCode!=null) {
      etCode.postDelayed(new Runnable() {
        @Override
        public void run() {
          imm.hideSoftInputFromWindow(etCode.getWindowToken(), 0);
        }
      },200);
    }
  }

  /**
   * 添加動(dòng)畫(huà)
   */
  private void addAnimation(){
    for(int i=0;i<tvs.size();i++){
      ObjectAnimator animator = ObjectAnimator.ofInt(tvs.get(i), "TextColor", 0x00000000, 0xfff00000);
      animator.setDuration(10000);
      final int index = i;
      animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {

        }

        @Override
        public void onAnimationEnd(Animator animator) {

        }

        @Override
        public void onAnimationCancel(Animator animator) {
          tvs.get(index).setTextColor(codeColor);
        }

        @Override
        public void onAnimationRepeat(Animator animator) {

        }
      });
      animator.setInterpolator(new LinearInterpolator());
      animator.setRepeatCount(Animation.INFINITE);
      animators.add(animator);
    }
  }

  /**
   * 開(kāi)啟動(dòng)畫(huà)
   */
  private void setTwinkle(){
    int size = codes.size();
    for(int i=0;i<tvs.size();i++){
      if(i==size){
        animators.get(i).start();
        tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_current_bottom));
      }else{
        animators.get(i).cancel();
        tvs.get(i).setBackground(mContext.getResources().getDrawable(R.drawable.code_border_bottom));
      }
    }
  }

  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    for(int i=0;i<tvs.size();i++){
      animators.get(i).cancel();
    }
  }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android中子線程和UI線程通信詳解

    Android中子線程和UI線程通信詳解

    這篇文章主要介紹了Android中子線程和UI線程通信詳解,本文講解了一些概念、使用、及代碼實(shí)例,需要的朋友可以參考下
    2015-06-06
  • Android實(shí)現(xiàn)拍照截圖功能

    Android實(shí)現(xiàn)拍照截圖功能

    這篇文章主要介紹了Android實(shí)現(xiàn)拍照截圖功能,簡(jiǎn)單介紹了Android實(shí)現(xiàn)拍照截圖功能的步驟,供大家參考,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Android 動(dòng)態(tài)的顯示時(shí)間

    Android 動(dòng)態(tài)的顯示時(shí)間

    本文給大家分享一段代碼實(shí)現(xiàn)android動(dòng)態(tài)顯示時(shí)間,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2016-12-12
  • Android 輕松獲取CPU型號(hào)的方法

    Android 輕松獲取CPU型號(hào)的方法

    這篇文章主要介紹了在Android設(shè)備上獲取CPU型號(hào)是一項(xiàng)常見(jiàn)的任務(wù)的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • Android編譯的注意事項(xiàng)

    Android編譯的注意事項(xiàng)

    今天小編就為大家分享一篇關(guān)于Android編譯的注意事項(xiàng),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • Android 解決使用SearchView時(shí)軟鍵盤不支持actionSearch的問(wèn)題

    Android 解決使用SearchView時(shí)軟鍵盤不支持actionSearch的問(wèn)題

    本文主要介紹使用SearchView時(shí)軟鍵盤不支持actionSearch,這里提供了解決方案,希望能幫助開(kāi)發(fā)Android應(yīng)用的同學(xué)
    2016-07-07
  • Android手勢(shì)操作識(shí)別詳解

    Android手勢(shì)操作識(shí)別詳解

    這篇文章主要為大家詳細(xì)介紹了Android手勢(shì)操作識(shí)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Android開(kāi)發(fā)中Activity屬性設(shè)置小結(jié)

    Android開(kāi)發(fā)中Activity屬性設(shè)置小結(jié)

    Android應(yīng)用開(kāi)發(fā)中會(huì)經(jīng)常遇到Activity組件的使用,下面就來(lái)講解下Activity組件。Activity的生命周期、通信方式和IntentFilter等內(nèi)容,并提供了一些日常開(kāi)發(fā)中經(jīng)常用到的關(guān)于Activity的技巧和方法。通過(guò)本文,你可以進(jìn)一步了接Android中Activity的運(yùn)作方式。
    2015-05-05
  • Android studio gradle環(huán)境變量配置教程

    Android studio gradle環(huán)境變量配置教程

    這篇文章主要為大家詳細(xì)介紹了Android studio gradle環(huán)境變量配置教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Android實(shí)現(xiàn)可播放GIF動(dòng)畫(huà)的ImageView

    Android實(shí)現(xiàn)可播放GIF動(dòng)畫(huà)的ImageView

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可播放GIF動(dòng)畫(huà)的ImageView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09

最新評(píng)論

阿巴嘎旗| 景德镇市| 湾仔区| 二连浩特市| 泸西县| 洱源县| 兰考县| 泽州县| 威海市| 德清县| 武山县| 四会市| 台北市| 大埔县| 岚皋县| 卢氏县| 泸州市| 探索| 和林格尔县| 安图县| 鄄城县| 福建省| 麦盖提县| 屏东县| 阳高县| 沙河市| 微山县| 龙泉市| 杭州市| 抚宁县| 泸西县| 通山县| 阳原县| 道真| 万山特区| 黄浦区| 二连浩特市| 多伦县| 屯昌县| 万荣县| 曲靖市|