在 Android 中格式化 EditText 的电话号码

我正在制作一个简单的地址簿应用程序(目标4.2) ,采取姓名,地址,城市,国家,邮政编码和电话。

我想格式化的电话号码输入为电话号码(XXX) XXX-XXXX,但我需要提取出的值作为一个字符串,这样我就可以存储在我的数据库时,我保存。我怎么能这么做? 我将 EditText 设置为“电话号码”输入,但这显然没有太大作用。

160298 次浏览

只需使用 电话号码格式,只需拨打:

editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

加法
需要说明的是,PhoneNumberFormattingTextWatcher 的 脊梁骨是 PhoneNumberUtils 类。区别在于 TextWatcher 维护 EditText,而您必须在每次更改其内容时调用 PhoneNumberUtils.formatNumber()

有一个名为 电话号码实用程序的库可以帮助您处理电话号码转换和比较。例如,使用..。

EditText text = (EditText) findViewById(R.id.editTextId);
PhoneNumberUtils.formatNumber(text.getText().toString())

把你的号码格式化成标准格式。

PhoneNumberUtils.compare(String a, String b);

... 有助于模糊比较。还有很多。查看 http://developer.android.com/reference/android/telephony/PhoneNumberUtils.html了解更多。

将 EditText 设置为 phone已经是一个很好的选择; 最终,添加 digits可能会有所帮助,例如,在您的布局中,它看起来像..。

<EditText
android:id="@+id/editTextId"
android:inputType="phone"
android:digits="0123456789+"
/>

可以使用带模式匹配的正则表达式从字符串中提取数字。

    String s="";
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("(1111)123-456-789"); //editText.getText().toString()
while (m.find()) {
s=s+m.group(0);
}
System.out.println("............"+s);


Output : ............1111123456789

我最近为 Android EditText 做了一个类似的格式,比如1(XXX) XXX-XXXX。请找到下面的代码。只需使用 TextWatcher 子类作为文本更改的侦听器: ....

UsPhoneNumberFormatter addLineNumberFormatter = new UsPhoneNumberFormatter(
new WeakReference<EditText>(mYourEditText));
mYourEditText.addTextChangedListener(addLineNumberFormatter);

...

private class UsPhoneNumberFormatter implements TextWatcher {
//This TextWatcher sub-class formats entered numbers as 1 (123) 456-7890
private boolean mFormatting; // this is a flag which prevents the
// stack(onTextChanged)
private boolean clearFlag;
private int mLastStartLocation;
private String mLastBeforeText;
private WeakReference<EditText> mWeakEditText;


public UsPhoneNumberFormatter(WeakReference<EditText> weakEditText) {
this.mWeakEditText = weakEditText;
}


@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
if (after == 0 && s.toString().equals("1 ")) {
clearFlag = true;
}
mLastStartLocation = start;
mLastBeforeText = s.toString();
}


@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO: Do nothing
}


@Override
public void afterTextChanged(Editable s) {
// Make sure to ignore calls to afterTextChanged caused by the work
// done below
if (!mFormatting) {
mFormatting = true;
int curPos = mLastStartLocation;
String beforeValue = mLastBeforeText;
String currentValue = s.toString();
String formattedValue = formatUsNumber(s);
if (currentValue.length() > beforeValue.length()) {
int setCusorPos = formattedValue.length()
- (beforeValue.length() - curPos);
mWeakEditText.get().setSelection(setCusorPos < 0 ? 0 : setCusorPos);
} else {
int setCusorPos = formattedValue.length()
- (currentValue.length() - curPos);
if(setCusorPos > 0 && !Character.isDigit(formattedValue.charAt(setCusorPos -1))){
setCusorPos--;
}
mWeakEditText.get().setSelection(setCusorPos < 0 ? 0 : setCusorPos);
}
mFormatting = false;
}
}


private String formatUsNumber(Editable text) {
StringBuilder formattedString = new StringBuilder();
// Remove everything except digits
int p = 0;
while (p < text.length()) {
char ch = text.charAt(p);
if (!Character.isDigit(ch)) {
text.delete(p, p + 1);
} else {
p++;
}
}
// Now only digits are remaining
String allDigitString = text.toString();


int totalDigitCount = allDigitString.length();


if (totalDigitCount == 0
|| (totalDigitCount > 10 && !allDigitString.startsWith("1"))
|| totalDigitCount > 11) {
// May be the total length of input length is greater than the
// expected value so we'll remove all formatting
text.clear();
text.append(allDigitString);
return allDigitString;
}
int alreadyPlacedDigitCount = 0;
// Only '1' is remaining and user pressed backspace and so we clear
// the edit text.
if (allDigitString.equals("1") && clearFlag) {
text.clear();
clearFlag = false;
return "";
}
if (allDigitString.startsWith("1")) {
formattedString.append("1 ");
alreadyPlacedDigitCount++;
}
// The first 3 numbers beyond '1' must be enclosed in brackets "()"
if (totalDigitCount - alreadyPlacedDigitCount > 3) {
formattedString.append("("
+ allDigitString.substring(alreadyPlacedDigitCount,
alreadyPlacedDigitCount + 3) + ") ");
alreadyPlacedDigitCount += 3;
}
// There must be a '-' inserted after the next 3 numbers
if (totalDigitCount - alreadyPlacedDigitCount > 3) {
formattedString.append(allDigitString.substring(
alreadyPlacedDigitCount, alreadyPlacedDigitCount + 3)
+ "-");
alreadyPlacedDigitCount += 3;
}
// All the required formatting is done so we'll just copy the
// remaining digits.
if (totalDigitCount > alreadyPlacedDigitCount) {
formattedString.append(allDigitString
.substring(alreadyPlacedDigitCount));
}


text.clear();
text.append(formattedString.toString());
return formattedString.toString();
}


}

简单使用:

在 Java 代码中:

editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

在 XML 代码中:

<EditText
android:id="@+id/etPhoneNumber"
android:inputType="phone"/>

这个代码对我很有用。当编辑文本中的文本发生变化时,它会自动格式化。

按照本答案中的说明格式化 EditText 掩码。

Https://stackoverflow.com/a/34907607/1013929

在那之后,你可以用以下方法捕获蒙面字符串的原始数字:

String phoneNumbers = maskedString.replaceAll("[^\\d]", "");

也许下面的示例项目对你有帮助;

Https://github.com/reinaldoarrosi/maskededittext

该项目包含一个称为 MaskedEditText的视图类。

然后在项目的 res/value/attrs.xml 文件中添加 xml 部分;

<resources>
<declare-styleable name="MaskedEditText">
<attr name="mask" format="string" />
<attr name="placeholder" format="string" />
</declare-styleable>
</resources>

然后就可以使用 MaskedEditText视图了。

最后,您应该在 xml 文件中添加如下所示的 MaskedEditText;

<packagename.currentfolder.MaskedEditText
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/maskedEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="5"
app:mask="(999) 999-9999"
app:placeholder="_" >

当然,您可以通过编程方式使用它。

在这些步骤之后,添加 MaskedEditText将如下所示;

enter image description here

以编程方式,如果您希望取消对它的文本值的屏蔽,可以使用下面的行;

maskedEditText.getText(true);

要获取掩码值,可以在 getText方法中发送 false值而不是 true值。

//(123) 456 7890  formate set


private int textlength = 0;


public class MyPhoneTextWatcher implements 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) {




String text = etMobile.getText().toString();
textlength = etMobile.getText().length();


if (text.endsWith(" "))
return;


if (textlength == 1) {
if (!text.contains("(")) {
etMobile.setText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
etMobile.setSelection(etMobile.getText().length());
}


} else if (textlength == 5) {


if (!text.contains(")")) {
etMobile.setText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
etMobile.setSelection(etMobile.getText().length());
}


} else if (textlength == 6 || textlength == 10) {
etMobile.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
etMobile.setSelection(etMobile.getText().length());
}


}
@Override
public void afterTextChanged(Editable editable) {
}
}

不要担心。我已经为你做了一个最好的解决方案。你可以看到下面这个简单的应用程序链接。

private EditText mPasswordField;
public int textLength = 0;


@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


mPasswordField = (EditText) findViewById(R.id.password_field);
mPasswordField.addTextChangedListener(this);
}


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


}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {




String text = mPasswordField.getText().toString();
textLength = mPasswordField.getText().length();


if (text.endsWith("-") || text.endsWith(" ") || text.endsWith(" "))
return;


if (textLength == 1) {
if (!text.contains("(")) {
mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
mPasswordField.setSelection(mPasswordField.getText().length());
}


} else if (textLength == 5) {


if (!text.contains(")")) {
mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
mPasswordField.setSelection(mPasswordField.getText().length());
}


} else if (textLength == 6) {
mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
mPasswordField.setSelection(mPasswordField.getText().length());


} else if (textLength == 10) {
if (!text.contains("-")) {
mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
mPasswordField.setSelection(mPasswordField.getText().length());
}
} else if (textLength == 15) {
if (text.contains("-")) {
mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
mPasswordField.setSelection(mPasswordField.getText().length());
}
}else if (textLength == 18) {
if (text.contains("-")) {
mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
mPasswordField.setSelection(mPasswordField.getText().length());
}
} else if (textLength == 20) {
Intent i = new Intent(MainActivity.this, Activity2.class);
startActivity(i);


}






}


@Override
public void afterTextChanged(Editable s) {


}

不要: 不要忘记“实现 TextWatcher”与您的活动类。

链接: https://drive.google.com/open?id=0B-yo9VvU7jyBMjJpT29xc2k5bnc

希望你觉得这个解决方案很酷。

使用 Java 代码,您只能接受数字和电话号码类型

 EditText number1 = (EditText) layout.findViewById(R.id.edittext);
number1.setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_CLASS_PHONE);
number1.setKeyListener(DigitsKeyListener.getInstance("0123456789”));
number1.setFilters(new InputFilter[] {new InputFilter.LengthFilter(14)}); // 14 is max digits

这段代码将避免读取输入后的大量验证

更像是干净:

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


String text = etyEditText.getText();
int textlength = etyEditText.getText().length();


if (text.endsWith("(") ||text.endsWith(")")|| text.endsWith(" ") || text.endsWith("-")  )
return;


switch (textlength){
case 1:
etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
etyEditText.setSelection(etyEditText.getText().length());
break;
case 5:
etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
etyEditText.setSelection(etyEditText.getText().length());
break;
case 6:
etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
etyEditText.setSelection(etyEditText.getText().length());
break;
case 10:
etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
etyEditText.setSelection(etyEditText.getText().length());
break;
}


}

您可以使用衍生格式的电话号码在 Android。此解决方案比其他解决方案更好,因为它不更改输入文本。格式保持纯粹的视觉效果。

implementation 'com.googlecode.libphonenumber:libphonenumber:7.0.4'

格式化类:

open class PhoneNumberFormatter : TransformationMethod {
private val mFormatter: AsYouTypeFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(Locale.getDefault().country)


override fun getTransformation(source: CharSequence, view: View): CharSequence {
val formatted = format(source)
if (source is Spannable) {
setSpans(source, formatted)
return source
}
return formatted
}
override fun onFocusChanged(view: View?, sourceText: CharSequence?, focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) = Unit


private fun setSpans(spannable: Spannable, formatted: CharSequence): CharSequence {


spannable.clearSpawns()


var charterIndex = 0
var formattedIndex = 0
var spawn = ""
val spawns: List<String> = spannable
.map {
spawn = ""
charterIndex = formatted.indexOf(it, formattedIndex)
if (charterIndex != -1){
spawn = formatted.substring(formattedIndex, charterIndex-1)
formattedIndex = charterIndex+1
}
spawn
}


spawns.forEachIndexed { index, sequence ->
spannable.setSpan(CharterSpan(sequence), index, index + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}


return formatted
}


private fun Spannable.clearSpawns() =
this
.getSpans(0, this.length, CharterSpan::class.java)
.forEach { this.removeSpan(it) }


private fun format(spannable: CharSequence): String {
mFormatter.clear()
var formated = ""
for (i in 0 until spannable.length) {
formated = mFormatter.inputDigit(spannable[i])
}
return formated
}


private inner class CharterSpan(private val charters: String) : ReplacementSpan() {


var space = 0


override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
space = Math.round(paint.measureText(charters, 0, charters.length))
return Math.round(paint.measureText(text, start, end)) + space
}


override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
space = Math.round(paint.measureText(charters, 0, charters.length))
canvas.drawText(text, start, end, x + space, y.toFloat(), paint)
canvas.drawText(charters, x, y.toFloat(), paint)
}
}


}

用法:

editText.transformationMethod = formatter

您需要创建一个类:

public class PhoneTextFormatter implements TextWatcher {


private final String TAG = this.getClass().getSimpleName();


private EditText mEditText;


private String mPattern;


public PhoneTextFormatter(EditText editText, String pattern) {
mEditText = editText;
mPattern = pattern;
//set max length of string
int maxLength = pattern.length();
mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
}


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


}


@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
StringBuilder phone = new StringBuilder(s);


Log.d(TAG, "join");


if (count > 0 && !isValid(phone.toString())) {
for (int i = 0; i < phone.length(); i++) {
Log.d(TAG, String.format("%s", phone));
char c = mPattern.charAt(i);


if ((c != '#') && (c != phone.charAt(i))) {
phone.insert(i, c);
}
}


mEditText.setText(phone);
mEditText.setSelection(mEditText.getText().length());
}
}


@Override
public void afterTextChanged(Editable s) {


}


private boolean isValid(String phone)
{
for (int i = 0; i < phone.length(); i++) {
char c = mPattern.charAt(i);


if (c == '#') continue;


if (c != phone.charAt(i)) {
return false;
}
}


return true;
}
}

使用方法如下:

phone = view.findViewById(R.id.phone);
phone.addTextChangedListener(new PhoneTextFormatter(phone, "+7 (###) ###-####"));

如果您只对国际数字感兴趣,并且希望能够显示与输入中的国家代码相匹配的国家的国旗,我为此编写了一个小型库:

Https://github.com/tfcporciuncula/phonemoji

看起来是这样的:

library demo

这个代码是我的工作(216)555-5555

etphonenumber.addTextChangedListener(new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
// TODO Auto-generated method stub
}


@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s)
{
String text = etphonenumber.getText().toString();
int  textLength = etphonenumber.getText().length();
if (text.endsWith("-") || text.endsWith(" ") || text.endsWith(" "))
return;
if (textLength == 1) {
if (!text.contains("("))
{
etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
etphonenumber.setSelection(etphonenumber.getText().length());
}
}
else if (textLength == 5)
{
if (!text.contains(")"))
{
etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
etphonenumber.setSelection(etphonenumber.getText().length());
}
}
else if (textLength == 6)
{
etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
etphonenumber.setSelection(etphonenumber.getText().length());
}
else if (textLength == 10)
{
if (!text.contains("-"))
{
etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
etphonenumber.setSelection(etphonenumber.getText().length());
}
}
}
});