Android实现真正的344格式化手机号码输入框

57 篇文章 0 订阅
订阅专栏
50 篇文章 1 订阅
订阅专栏

前言:在最近一个项目的登录页上,输入手机号码这个输入框,UI稿要求显示344样式的格式化手机号码,例如“130 1234 5678”,在之前其实也有过类似的需求,但是在实现344格式化手机号码的过程中或多或少碰到不少坑,当时也没有深究,以项目排期紧为由将需求拍回去了,折中的方案是设置输入框的android:inputType=“phone”,android:maxLength=“11”,这是最常见的手机号输入框的实现方式,全部由系统自己处理,无bug,程序员的最爱,但是这一次我决定say no!

一、调研主流App

之前想做这样的一个格式化手机号输入框时也查看过网上的一些代码,但是在使用他们的代码时,总会有各种各样的bug(空指针、角标越界等等),各种各样的技术博客都是将别人的代码拷过来不假思索的粘贴就变成自己的了,也不实践完善验证代码的正确性,所以目前没看到一款真正能用,不会出现bug的输入框控件。

准备干之前我想各一线大厂这种格式化手机号码的输入框肯定是正确好用的(崇拜的心理),于是准备看看他们实现的效果都是啥样的,结果也是让我感到惊讶,一起来看看!

为保证调研质量,所有app都升级到了最新版本。

1.今日头条 V7.2.9
在这里插入图片描述
今日头条的使用情况:
手机号登录为344格式化样式,最多只能输入11位有效字符,但是还可以输入字符,没有做输入过滤,在中间删除字符重新输入过程中无崩溃。

2.新浪微博 V9.6.2
在这里插入图片描述
新浪微博的使用情况:
在输入过程中,微博过滤所有的无效字符,只能输入0-9这些数字,其他的都不会输入。但是却没有做手机号位数限制,好吧,如果说与国家的手机号有关,那我无话可说,但是从第11位数字往后就没有了格式化了,也就是上图所示这样。

3.美团 V10.0.401
在这里插入图片描述
美团的使用情况:
美团在输入时,有最多11位数字限制,如果将光标移动到非末尾位置输入,会自动将最后一位移除,在光标位置插入新的字符,但是也没有做过滤,如图所示可以输入标点符号,字母只能输入p。

4.网易云音乐 V6.2.2
在这里插入图片描述
网易云音乐的使用情况:
网易云音乐并没有做344格式化手机号的处理,默认最多输入11位字符,输入满11位时,光标在非末尾位置时无法增加新的字符,如图所示,网易云可以输入加减乘除、逗号、点、字母w和p。

5.支付宝 V10.1.65.6567
在这里插入图片描述
支付宝的使用情况:
也没做位数限制,从第11位开始没有格式化样式了,过滤掉了其他的字符,但是还能输入减号。

6.优酷 V8.0.3
在这里插入图片描述
优酷的使用情况:
大优酷竟然不让截屏?可以看到没有做344手机号格式化,也没有限制输入长度,倒是过滤掉了所有的非数字的字符。

7.安居客 V12.16.4
在这里插入图片描述
安居客的使用情况
最多输入11位数字,也做了344格式化手机号码,所有字符无法输入(过滤的很干净),但是当我想点中间的某位数字时,竟然整块选中无法取消,这个时候你只有两种选择,要不点击获取验证码,要不重新输入手机号码,这个功能真的非常恶心!

8.贝壳找房 V2.11.0
在这里插入图片描述
贝壳找房的使用情况
在贝壳中进行手机号输入,问题和网易云音乐一样,可以输入±*/,.wp这些字符,并且还有一点也比较恶心,当光标移动到非末尾位置时,这时候不论是删除或者输入字符时,光标马上会跳到最后一位,个人感觉这个用户体验非常不好。

二、功能实现

通过对上述一些生活中常用的覆盖衣食住行的主流app的输入框比较,现在没有一款能够满足真正意义上的344格式化手机号码输入框,有的是没有过滤特殊字符,有的是没有做长度限制,这里抛开国际化手机号码长度的问题,以中国现有11位手机号码长度为例,来动手写一个自定义的输入框,真正好用的344格式化号码,这里贴上最终的代码:

/*
 * 实现自定义手机号输入框,手机号码效果为344效果,例如111 1111 1111
 */
public class PhoneEditText extends EditText implements TextWatcher {

  // 特殊下标位置
  private static final int PHONE_INDEX_3 = 3;
  private static final int PHONE_INDEX_4 = 4;
  private static final int PHONE_INDEX_8 = 8;
  private static final int PHONE_INDEX_9 = 9;

  private String preCharSequence;

  private OnPhoneEditTextChangeListener onPhoneEditTextChangeListener;

  public PhoneEditText(Context context) {
    super(context);
    initView();
  }

  public PhoneEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView();
  }

  public PhoneEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initView();
  }

  public interface OnPhoneEditTextChangeListener {
    /**
     * 对外提供接口监听
     * @param s 字符串
     * @param isEleven 现在是否是11位数字
     */
    void onTextChange(String s, boolean isEleven);
  }

  public void setOnPhoneEditTextChangeListener(OnPhoneEditTextChangeListener listener) {
    this.onPhoneEditTextChangeListener = listener;
  }

  private void initView() {
    //设置输入过滤器
    setFilters(new InputFilter[] {
        new InputFilter() {
          @Override
          public CharSequence filter(CharSequence source, int start, int end,
              Spanned spanned, int dstart, int dend) {
            //在onTextChanged方法里执行setText(sb.toString());会到这里,内容一样直接返回
            if (TextUtils.equals(source, preCharSequence)) {
              return null;
            }
            //过滤掉空格和换行,dstart为13表示光标位置是11位数字+2个空格时,返回空字符
            if (" ".equals(source.toString())
                || source.toString().contentEquals("\n")
                || dstart == 13) {
              return "";
            }
            //这里是当光标移动到非末尾位置进行输入操作时,返回空字符
            else if (getPhoneText().toString().length() == 11) {
              return "";
            } else {
              return null;
            }
          }
        }, new InputFilter() {
      @Override
      public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
          int dend) {
        //过滤掉所有的特殊字符,这里的字母只过滤掉了wp,因为在众多机型测试时,只能输入这两个,如果不放心可以添加a-z所有字母
        String speChat = "[`~!@#$%^&*()+\\-=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?wp]";
        Pattern pattern = Pattern.compile(speChat);
        Matcher matcher = pattern.matcher(source.toString());
        if (matcher.find()) {
          return "";
        } else {
          return null;
        }
      }
    }
    });
  }

  @Override
  public void beforeTextChanged(CharSequence s, int start, int count, int after) {

  }

  @Override
  public void onTextChanged(CharSequence s, int start, int before, int count) {
    super.onTextChanged(s, start, before, count);

    if (TextUtils.equals(preCharSequence, s)) {
      return;
    }

    if (null != onPhoneEditTextChangeListener) {
      onPhoneEditTextChangeListener.onTextChange(getPhoneText(),
          getPhoneText().length() == 11);
    }

    if (s == null || s.length() == 0) {
      return;
    }
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
      if (i != PHONE_INDEX_3 && i != PHONE_INDEX_8 && s.charAt(i) == ' ') {
        continue;
      } else {
        sb.append(s.charAt(i));
        if ((sb.length() == PHONE_INDEX_4 || sb.length() == PHONE_INDEX_9)
            && sb.charAt(sb.length() - 1) != ' ') {
          sb.insert(sb.length() - 1, ' ');
        }
      }
    }

    //这里主要处理添加空格后的字符串,before=0为输入字符,before=1为删除字符,将光标移动到正确的位置
    if (!sb.toString().equals(s.toString())) {
      int index = start + 1;
      if (sb.charAt(start) == ' ') {
        if (before == 0) {
          index++;
        } else {
          index--;
        }
      } else {
        if (before == 1) {
          index--;
        }
      }

      preCharSequence = sb.toString();
      setText(sb.toString());
      //对setSelection添加异常捕获,防止出现意外的IndexOutOfBoundsException异常
      try {
        setSelection(index);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  @Override
  public void afterTextChanged(Editable s) {

  }

  // 获得不包含空格的手机号
  public String getPhoneText() {
    String str = getText().toString();
    return replaceBlank(str);
  }

  private String replaceBlank(String str) {
    String dest = "";
    if (str != null) {
      Pattern p = Pattern.compile("\\s*|\t|\r|\n");
      Matcher m = p.matcher(str);
      if (m.find()) {
        dest = m.replaceAll("");
      }
    }
    return dest;
  }
}

使用也非常简单,在xml文件中使用:

<com.xxxx.widget.PhoneEditText
        android:id="@+id/et_phone"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/login_editor_bg"
        android:inputType="phone"
        android:maxLength="13"
        android:maxLines="1"
        android:paddingLeft="16.5dp"
        android:textColor="@color/white"
        android:textCursorDrawable="@drawable/cursor_edit"
        android:textSize="16dp"
        tools:text="156 1234 5678" />

在activity中使用:

etPhone.setOnPhoneEditTextChangeListener(new PhoneEditText.OnPhoneEditTextChangeListener() {
      @Override
      public void onTextChange(String s, boolean isEleven) {
        setIvClearVisibility(s);

        if (isEleven && tvSmscode.isEnabled()) {
          tvSmscode.setTextColor(getResources().getColor(R.color.white));
          tvSmscode.setClickable(true);
        } else {
          tvSmscode.setTextColor(getResources().getColor(R.color.color_30FFFFFF));
          tvSmscode.setClickable(false);
        }
      }
    });

具体的逻辑都已经在PhoneEditText中内部处理了,外界只用关心回调即可,用起来还是很方便的。

完成后一起来看看最终效果:
在这里插入图片描述
效果符合预期,最多输入11位有效数字,过滤所有的非数字字符,光标在中间删除插入也不会出现光标跳闪现象,用户体验好~

三、写在最后

其实这东西并不难,也没有什么技巧,我也只是将现有的各种问题总结处理了一下,作为一个独立的控件能够很方便的被各方使用,以后再碰到类似的需求丝毫不用慌,拿过来用就完了,一次封装,无限使用,给用户提供最完美的用户体验!

如果有问题,欢迎留言,一起探讨~

Android 手机号344格式化,字符串拼接和EditText输入框
csdn_aiyang的博客
05-10 341
国内手机号一般11位数字,在登录注册等页面经常会用到,其他信息介绍页面也可能会用到手机号的显示。
Android 完美实现手机号344格式化效果
Z·Pan
03-08 2813
一、前言: 在展示手机号码的时候,会遇到手机号按照344格式效果,这种效果的实现遇到过两次了,也踩过了许多的坑,在这里记录一下一个完美实现这种效果的方式。输入、插入、删除等光标位置停留比较好的交互效果。 二、效果: 关于输入空格崩溃的情况在简书有修复 https://www.jianshu.com/p/1c949029d6b2 三、代码实现: public class ZpPhone...
Android EditText 手机号344格式化输入的最佳实现
BaseDev
04-05 604
PhoneTextWatcher 手机号格式化监听器,支持普通输入/删除,中间输入/删除,在任意位置下黏贴/剪贴多个数字等多种交互场景。 目前支持的手机号格式为 3-4-4 分隔符可以自定义 Preview How to get Step 1. Add the JitPack repository to your build file Add it in your root build.gradle at the end of repositories: allprojects { reposi
带动画效果的手机号输入框 (3-4-4格式)
07-03
Android自定义控件:带动画效果的手机号输入框 (3-4-4格式)
Android 手机号输入格式化 3-3-4
Penguinfool的博客
09-06 691
其实这个手机号默认格式化,非常非常简单的,我们只需要TextChangerListener监听器就足够了 import android.content.Context; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.ut...
Android EditeText格式化手机号输入
wangsheng5454的博客
11-15 281
Android EditeText格式化手机号输入思路代码实现 思路 1.输入数字后获取编辑框内容,做替换操作,把空格替换, 2.根据要求在第四位和第九位添空格 3.把添加空格后的内容重新设置到EditeText 4.把光标移到文本末尾 代码实现 1.添加文本变化监听 mEtPhone!!.addTextChangedListener(this) override fun afterTex...
Android开发---手机号码输入框(满11位自动跳到下个输入框
janeen-jn的博客
10-31 1900
package com.jixiong.teen.view; import android.content.Context; import android.text.Editable; import android.text.Selection; import android.text.TextWatcher; import android.util.AttributeSet; import a
android格式化手机号的功能
OONullPointerAlex的博客
09-14 3742
项目中需要用户输入手机号码,11位的手机号码想要分割成XXX XXXX XXXX的格式。需要给Edittext添加一个监听就行了。 主要代码如下: //给手机号的输入框添加监听phoneNumEdit.addTextChangedListener(watcherPhoneNum); //手机号输入框的文本输入改变的监听 private TextWatcher watcherPhoneNum
Android自定义控件:带动画效果的手机号输入框 (3-4-4格式)
大灰狼的小绵羊哥哥的博客
07-22 1420
点击上方“Android技术杂货铺”,选择“置顶公众号” 干货文章,第一时间送达!   作者:Android草根王 链接:https://www.jianshu.com/p/e538b35c68c3 本文经作者授权推送。 项目中很多地方,使用到了自定义控件。 简单点的,如个性控件的定制,多个组件的组合封装等。 我们需要了解自定义控件的基础知识,即可快速实现; 复杂点的,如各种图...
Android自定义XEditText实现手机号空格输入
你全家都是博客
09-21 1105
Android自定义XEditText实现手机号空格输入。
Android手机号码输入框(满11位自动跳到下个输入框)实例代码
01-04
废话不多说了,直接给大家贴代码了,具体代码如下所示: package com.jixiong.teen.view; import android.content.Context; import android.text.Editable; import android.text.Selection; import android.text.TextWatcher; import android.util.AttributeSet; import android.widget.EditText; /** * Created by christy on 16/12/22. */ public
自定义控件实现344格式的EditText
04-03
自定义EditText实现输入的电话为344格式并自带删除功能
安卓输入框实现电话号码"344"格式
小天的博客
04-07 3964
效果如图所示: 对edittext添加一个 TextWatcher,对应的 3个方法进行重载: private class MyTextWatcher implements TextWatcher { public MyTextWatcher(EditText etPhone) { this.etPhone = etPhone;
Android 输入手机号码(GET网络请求)查询手机号码归属地
Scxioi0的博客
10-03 795
Android 输入手机号码(GET网络请求)查询手机号码归属地 首先在xml文件上界面布局 采用LinearLayout来布局界面,并添加一个按钮点击来进行获取信息,在添加一个EditText来输入我们要进行查询的手机号码,最后添加一个TextView控件来显示手机归属地信息 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andr
Android限制输入框电话号码(纯数字)
jayyuz的专栏
05-16 3792
有需求将一个推荐联系人输入框设置为仅输入手机号码。于是乎,我想到了EditText的inputType属性。 加上之后,很好。自己测试了下没有问题。But,有一天,测试的MM突然对我说,哈哈,你的程序有Bug。我的第一反应是:怎么可能,我都已经设置为电话号码格式的呀。难道是我没有限制住输入的长度?看了下代码,没错呀,设置了android:maxLength=”11”。嗯,还是找她,看看到底是什么问
android EditText输入手机号自动带空格(344格式)
happy++, worry--
05-03 2368
android开发过程中,有时候需要这样展示手机号:186 0000 0000。 案例 代码块 代码块语法遵循标准markdown代码,例如: @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) { if (ch...
android中卡号输入框控件(每四位用空格分隔)(解决输入法跳转的问题)
lintcgirl的博客
12-19 6790
由于项目的需求,需要在卡号输入时,每四位用空间分隔,于是就写了个控件。 该控件支持中间删除,中间增加,粘贴,末尾输入等,光标的位置显示正确。
Android每日范例——电话号码输入框
觅梦云的专栏
10-11 2522
EditText控件自定义的属性并不能包含所有我们需要的限定,因此Android在Java代码中提供了接口,让我们对它进行限定 电话号码输入框实现: 1、在XML布局中添加EditText控件 2、在java代码中获取EditText控件实例,设置监听器
Android怎样实现密码输入框
最新发布
07-28
Android 中,可以通过使用 EditText 组件来实现密码输入框。下面是一个简单的示例代码: ```java android:id="@+id/passwordEditText" android:layout_width="match_parent" android:layout_height="wrap_...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • Android+jacoco实现代码覆盖率最正确的实现方式,没有之一! 99559
  • Java中常见的类加载器及双亲委派机制的原理 83627
  • Android基础编译流程 81912
  • TabLayout与ViewPager配合使用踩坑总结 79442
  • Android+Java知识点总结-持续更新中(为了更好的自己) 69829

分类专栏

  • 闲记 7篇
  • 技术 57篇
  • android开发 50篇
  • 网络 1篇
  • http 1篇
  • RN开发 4篇
  • Redux 1篇
  • 图片 1篇
  • Linux 12篇
  • nginx 1篇
  • hibernate 4篇
  • structs2 4篇
  • spring 8篇
  • mybatis 3篇
  • springmvc 2篇
  • Redis 2篇
  • dubbo 2篇
  • java 11篇
  • ActiveMQ 4篇
  • freemarker 1篇
  • android 2篇
  • SparseArray 1篇
  • Android面试知识点系列 2篇

最新评论

  • Android+jacoco实现代码覆盖率最正确的实现方式,没有之一!

    qq_34194064: 我的连jacoco report都没出现,ec文件没法转换成可视化报告来

  • Android+jacoco实现代码覆盖率最正确的实现方式,没有之一!

    qq_34194064: 你好,有jacoco的demo吗?可否帮传一个? vx:13265442775

  • Android+jacoco实现代码覆盖率最正确的实现方式,没有之一!

    qq_34194064: 你好。有集成了jacoco的demo吗?可否帮忙发个,谢谢。 微信:13265442775 邮箱:2257388818@qq.com

  • 泛型中占位符T和?有什么区别?

    高山流水遇知音_: 麻木了

  • Android+jacoco实现代码覆盖率最正确的实现方式,没有之一!

    阡陌春: 请问,完整版的实现代码有在哪里展示

您愿意向朋友推荐“博客详情页”吗?

  • 强烈不推荐
  • 不推荐
  • 一般般
  • 推荐
  • 强烈推荐
提交

最新文章

  • Android+jacoco实现代码覆盖率最正确的实现方式,没有之一!
  • 阻塞队列实现生产者-消费者模式
  • Android获取桌面启动图标的位置
2021年2篇
2020年8篇
2019年11篇
2018年21篇
2017年23篇
2016年19篇
2015年13篇

目录

目录

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖子爱你520

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

深圳SEO优化公司平顶山建网站公司潜江网络广告推广推荐龙华网站设计价格龙岗高端网站设计报价贵港模板制作多少钱承德网页设计哪家好朝阳百搜标王报价南京百度竞价哪家好伊春百搜标王哪家好山南企业网站建设哪家好茂名外贸网站建设推荐西宁关键词按天计费公司成都网络广告推广哪家好莆田SEO按天扣费报价凉山网站推广工具报价通化关键词按天计费平顶山模板网站建设龙岩网站改版多少钱林芝关键词按天扣费哪家好布吉关键词按天扣费公司大鹏百度竞价价格昆明网站制作设计多少钱凉山建设网站多少钱湖州百搜标王价格铜仁seo网站推广海北品牌网站设计聊城网站优化排名多少钱随州网站开发公司宜宾营销网站和田网站优化按天计费价格歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化