项目要求:
登陆界面输入邮箱,自动匹配常用邮箱并自动补全后缀。
比如邮箱为[email protected],当我输入10376129@q时,输入框自动补全后面的q.com且颜色为灰浅色,输入框失去焦点时,补全q.com颜色变为黑色,和前面103796129@q的颜色一致。
解决:
1.通过查看知乎的布局,发现没有用自定义控件,仅仅用了普通的EditText。
2.查看EditTex(继承TextView)t的API,最终想到了用下面这个方法
void android.widget.TextView.setCompoundDrawables(Drawable left,Drawable top, Drawable right,Drawable bottom)
通过绘制EditText右边的Drawable来显示需要自动补全的字符串
3.演示
4.关键代码
package com.lt.autoemailactivity; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.view.View.OnFocusChangeListener; import android.widget.EditText; public class AutoCompleteEditTextActivity extends Activity implements TextWatcher { /** * 邮箱EditText */ private EditText mEmailEditText; /** * 常用的邮箱 */ private HashMap<String, String> mAutoData = new HashMap<String, String>(); /** * 邮箱editText的高度 */ private int mHeight; /** * 邮箱editText的宽度 */ private int mWidth; /** * 输入框中字符的baseLine */ private int baseLine; /** * 画笔 */ private Paint mPaint; private Bitmap mBitmap; /** * 画布 */ private Canvas canvas; private Drawable drawable; /** * 后缀字符串 */ private String mAddedText = ""; /** * 记录是否为空 */ private boolean mFlag; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_auto_complete_edittext); initEmail(); mEmailEditText = (EditText) findViewById(R.id.email); mEmailEditText.addTextChangedListener(this); mEmailEditText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { mEmailEditText.append(mAddedText); } } }); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { String text = s.toString(); mFlag = true; Iterator<Map.Entry<String, String>> iterator = mAutoData.entrySet() .iterator(); // 遍历常用邮箱 while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); if (text.endsWith(entry.getKey())) { drawAddedText(entry.getValue()); mAddedText = entry.getValue(); mFlag = false; break; } } // 如果没有匹配,就画一个空 if (mFlag) { drawAddedText(""); mAddedText = ""; } } /** * 画出后缀字符串 * * @param addedText */ private void drawAddedText(String addedText) { // 如果字符串为空,画空 if (addedText.equals("")) { mEmailEditText.setCompoundDrawables(null, null, null, null); return; } // 只需要初始化一次 if (mBitmap == null) { mHeight = mEmailEditText.getHeight(); mWidth = mEmailEditText.getWidth(); // 初始化画笔 mPaint = new Paint(); mPaint.setColor(Color.GRAY); mPaint.setAntiAlias(true);// 去除锯齿 mPaint.setFilterBitmap(true);// 对位图进行滤波处理 mPaint.setTextSize(mEmailEditText.getTextSize()); } // 计算baseLine Rect rect = new Rect(); int baseLineLocation = mEmailEditText.getLineBounds(0, rect); baseLine = baseLineLocation - rect.top; // 添加的字符窜的长度 int addedTextWidth = (int) (mPaint.measureText(addedText) + 1); // 创建bitmap mBitmap = Bitmap.createBitmap(addedTextWidth, mHeight, Bitmap.Config.ARGB_8888); canvas = new Canvas(mBitmap); // 绘制后缀字符串 canvas.drawText(addedText, 0, baseLine, mPaint); // bitmap转化为Drawable drawable = new BitmapDrawable(mBitmap); String text = mEmailEditText.getText().toString(); // 计算后缀字符串在输入框中的位置 int addedTextLeft = (int) (mPaint.measureText(text) - mWidth + addedTextWidth); int addedTextRight = addedTextLeft + addedTextWidth; int addedTextTop = 0; int addedTextBottom = addedTextTop + mHeight; // 设置后缀字符串位置 drawable.setBounds(addedTextLeft, addedTextTop, addedTextRight, addedTextBottom); // 显示后缀字符串 mEmailEditText.setCompoundDrawables(null, null, drawable, null); } /** * 初始化常用的邮箱 */ private void initEmail() { mAutoData.put("@q", "q.com"); mAutoData.put("@qq", ".com"); mAutoData.put("@qq.", "com"); mAutoData.put("@qq.c", "om"); mAutoData.put("@qq.co", "m"); mAutoData.put("@1", "63.com"); mAutoData.put("@16", "3.com"); mAutoData.put("@163", ".com"); mAutoData.put("@163.", "com"); mAutoData.put("@163.c", "om"); mAutoData.put("@163.co", "m"); mAutoData.put("@s", "ina.cn"); mAutoData.put("@si", "na.cn"); mAutoData.put("@sin", "a.cn"); mAutoData.put("@sina", ".cn"); mAutoData.put("@sina.", "cn"); mAutoData.put("@sina.c", "n"); mAutoData.put("@s", "ina.com"); mAutoData.put("@si", "na.com"); mAutoData.put("@sin", "a.com"); mAutoData.put("@sina", ".com"); mAutoData.put("@sina.", "com"); mAutoData.put("@sina.c", "om"); mAutoData.put("@sina.co", "m"); mAutoData.put("@1", "26.com"); mAutoData.put("@12", "6.com"); mAutoData.put("@126", ".com"); mAutoData.put("@126.", "com"); mAutoData.put("@126.c", "om"); mAutoData.put("@126.co", "m"); } }
=======================================分割线====================================================
修改代码结构,讲邮箱自动补全代码封装到EditText中,更方便使用,代码如下:
AutoCompleteEditText.java:
package com.lt.flowlayoutDemo; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.widget.EditText; public class AutoCompleteEditText extends EditText implements TextWatcher { private Bitmap mBitmap; private int mHeight; private int mWidth; private Paint mPaint; private int mBaseLine; private Canvas mCanvas; private BitmapDrawable mDrawable; private boolean mFlag; private String mAddedText; /** * 常用的邮箱 */ private HashMap<String, String> mAutoData = new HashMap<String, String>(); public AutoCompleteEditText(Context context) { super(context); initEmail(); addTextChangedListener(this); } public AutoCompleteEditText(Context context, AttributeSet attrs) { super(context, attrs); initEmail(); addTextChangedListener(this); } public AutoCompleteEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initEmail(); 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) { } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { if (!focused) { append(mAddedText); } super.onFocusChanged(focused, direction, previouslyFocusedRect); } @Override public void afterTextChanged(Editable s) { String text = s.toString(); mFlag = true; Iterator<Map.Entry<String, String>> iterator = mAutoData.entrySet() .iterator(); // 遍历常用邮箱 while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); if (text.endsWith(entry.getKey())) { drawAddedText(entry.getValue()); mAddedText = entry.getValue(); mFlag = false; break; } } // 如果没有匹配,就画一个空 if (mFlag) { drawAddedText(""); mAddedText = ""; } } /** * 画出后缀字符串 * * @param addedText */ @SuppressWarnings("deprecation") private void drawAddedText(String addedText) { // 如果字符串为空,画空 if (addedText.equals("")) { setCompoundDrawables(null, null, null, null); return; } // 只需要初始化一次 if (mBitmap == null) { mHeight = getHeight(); mWidth = getWidth(); // 初始化画笔 mPaint = new Paint(); mPaint.setColor(Color.GRAY); mPaint.setAntiAlias(true);// 去除锯齿 mPaint.setFilterBitmap(true);// 对位图进行滤波处理 mPaint.setTextSize(getTextSize()); } // 计算baseLine Rect rect = new Rect(); int baseLineLocation = getLineBounds(0, rect); mBaseLine = baseLineLocation - rect.top; // 添加的字符窜的长度 int addedTextWidth = (int) (mPaint.measureText(addedText) + 1); // 创建bitmap mBitmap = Bitmap.createBitmap(addedTextWidth, mHeight, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); // 绘制后缀字符串 mCanvas.drawText(addedText, 0, mBaseLine, mPaint); // bitmap转化为Drawable mDrawable = new BitmapDrawable(mBitmap); String text = getText().toString(); // 计算后缀字符串在输入框中的位置 int addedTextLeft = (int) (mPaint.measureText(text) - mWidth + addedTextWidth); int addedTextRight = addedTextLeft + addedTextWidth; int addedTextTop = 0; int addedTextBottom = addedTextTop + mHeight; // 设置后缀字符串位置 mDrawable.setBounds(addedTextLeft, addedTextTop, addedTextRight, addedTextBottom); // 显示后缀字符串 setCompoundDrawables(null, null, mDrawable, null); } /** * 初始化常用的邮箱 */ private void initEmail() { mAutoData.put("@q", "q.com"); mAutoData.put("@qq", ".com"); mAutoData.put("@qq.", "com"); mAutoData.put("@qq.c", "om"); mAutoData.put("@qq.co", "m"); mAutoData.put("@1", "63.com"); mAutoData.put("@16", "3.com"); mAutoData.put("@163", ".com"); mAutoData.put("@163.", "com"); mAutoData.put("@163.c", "om"); mAutoData.put("@163.co", "m"); mAutoData.put("@s", "ina.cn"); mAutoData.put("@si", "na.cn"); mAutoData.put("@sin", "a.cn"); mAutoData.put("@sina", ".cn"); mAutoData.put("@sina.", "cn"); mAutoData.put("@sina.c", "n"); mAutoData.put("@s", "ina.com"); mAutoData.put("@si", "na.com"); mAutoData.put("@sin", "a.com"); mAutoData.put("@sina", ".com"); mAutoData.put("@sina.", "com"); mAutoData.put("@sina.c", "om"); mAutoData.put("@sina.co", "m"); mAutoData.put("@1", "26.com"); mAutoData.put("@12", "6.com"); mAutoData.put("@126", ".com"); mAutoData.put("@126.", "com"); mAutoData.put("@126.c", "om"); mAutoData.put("@126.co", "m"); } }
主类MainActivity.java:
package com.lt.flowlayoutDemo; import android.app.Activity; import android.os.Bundle; import com.lt.flowlayouttest.R; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
布局文件activity_main.xml:
<LinearLayout 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:orientation="vertical" tools:context="${relativePackage}.${activityClass}" > <com.lt.flowlayoutDemo.AutoCompleteEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:textSize="20sp" android:singleLine="true" /> </LinearLayout>
补充:可以在EditText外面加一个RelativeLayout,设置RelativeLayout背景,即可不同样式的EditText。
5.源码下载(有注释)
http://download.csdn.net/detail/a15501628162/8495663
git地址:https://github.com/heheLT/AutoCompleteEditText