Android-部分可编辑的EditText

有一个需求是这样的,页面上有一个输入框,供用户输入手机号码,如果通讯录里面存在这个号码,会自动把名字追加到号码后面。这个需求变态的地方在于,假如用一个EditText+TextView,那么不好控制二者之间的距离,就算是做了各种适配,但是用户可以设置系统的字体,仍然显示很难看!没办法,之好在一个EditText里面来做,让号码是可编辑的,名字是自动追加上的。

MainActivity.java:

public class MainActivity extends Activity {

	private EditText edittext;
	private Button button;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	    final View rootView = this.findViewById(R.id.rootview);
		edittext = (EditText) this.findViewById(R.id.edittext1);
		//限定只能输入数字
		edittext.setInputType(EditorInfo.TYPE_CLASS_NUMBER);
		//可以获取焦点
		button = (Button)this.findViewById(R.id.button1);
		button.setFocusable(true);
		button.setFocusableInTouchMode(true);
		
		// 空白处点击,隐藏软键盘
		rootView.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				hideSoftInput();
			}
		});

		// 一旦获取焦点,设置光标位置
		edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				if (hasFocus) {
					String mobile = getMobile(edittext.getText().toString());
					setCursorPosition(mobile.length());
				}
			}
		});
		
		// 返回true,手动处理touch事件,即使edittext获取了焦点,也不会自动弹出软键盘,要手动弹出
		// http://stackoverflow.com/questions/10263384/android-how-to-get-text-position-from-touch-event
		edittext.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					Layout layout = ((EditText) v).getLayout();
					float x = event.getX() + edittext.getScrollX(); 
					int offset = layout.getOffsetForHorizontal(0, x);
					if(offset >= 0 && offset < 11){
						edittext.setSelection(offset);
					}else if(offset >= 11){
						edittext.setSelection(11);
					}
					showSoftInput();
				}
				return true;
			}
		});
		
		edittext.addTextChangedListener(new TextWatcher() {
			private String preText;
			@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 mobile = getMobile(s.toString());
				String nowtext = buildEditTextContent(mobile);
				if (nowtext.equals(preText)) {
					return;
				}
				// 计算当前的光标位置
				int offset = calCursorOffset(preText, nowtext);
				// 一定要在setTest之前设置preText,否则会StackOverflow
				preText = nowtext;
				edittext.setText(nowtext);
				// 文字发生变化,重新设置光标,否则会跑到最前面
				setCursorPosition(offset);
				if (mobile.length() == 11) {
					hideSoftInput();
				} 
			}
		});

		edittext.setText("15012341234");
	}

	private void hideSoftInput(){
		edittext.requestFocus();
		hideKeyboard();
		button.requestFocus();
	}
	
	private void showSoftInput(){
		edittext.requestFocus();
		showKeyboard(edittext);
	}
	
	private void setCursorPosition(int offset){
		edittext.setSelection(offset);
	}
	
	private String getMobile(String text){
		if(text == null || text.length() <= 0){
			return "";
		}
		String arr[] = text.split("\\s");
		String mobile = arr[0];
		return mobile;
	}
	
	private String buildEditTextContent(String mobile){
		String name = getName(mobile);
		String text = mobile + (name == null ? "" : " " + name);
		return text;
	}
	
	private int calCursorOffset(String pre, String now){
		if(isBlank(pre) && isBlank(now)){
			return 0;
		}else if(!isBlank(pre) && !isBlank(now)){
			for(int i=0; i<pre.length() && i<now.length(); i++){
				int prechar = pre.charAt(i);
				int nowchar = now.charAt(i);
				if(prechar != nowchar){
					return i;
				}
			}
		}
		return now.length() > 11 ? 11 : now.length();
	}

	// 业务方法,联系人数据
	private Map<String, String> data;

	private String getName(String mobile) {
		if (data == null) {
			data = contactData();
		}
		return data.get(mobile);
	}

	private Map<String, String> contactData() {
		Map<String, String> data = new HashMap<String, String>();
		data.put("15012341234", "张三");
		data.put("15112341234", "李四");
		data.put("15212341234", "王五");
		return data;
	}
	
	// util方法
	public void showKeyboard(View focusView) {
		Object showing = focusView.getTag();
		if (showing != null) {
			return;
		}
		try {
			InputMethodManager imm = (InputMethodManager) this
					.getSystemService(Context.INPUT_METHOD_SERVICE);
			imm.showSoftInput(focusView, 0);
			focusView.setTag(new Object());
		} catch (Exception e) {
			Log.e("SoftInput:Showing had a wrong.", e.toString());
		}
	}

	public void hideKeyboard() {
		View focusView = this.getCurrentFocus();
		if (focusView == null || focusView.getTag() == null) {
			return;
		}
		try {
			InputMethodManager imm = ((InputMethodManager) this
					.getSystemService(Activity.INPUT_METHOD_SERVICE));
			imm.hideSoftInputFromWindow(focusView.getWindowToken(),
					InputMethodManager.HIDE_NOT_ALWAYS);
			focusView.setTag(null);
		} catch (Exception e) {
			Log.e("SoftInput:Hiding had a wrong.", e.toString());
		}
	}

	public boolean isBlank(String str){
		if(str == null || str.length() <= 0){
			return true;
		}
		return false;
	}
}
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"
    android:id="@+id/rootview">

    <EditText 
        android:id="@+id/edittext1"
        android:layout_width="300dp"
        android:layout_height="wrap_content"/>
    
     <Button 
        android:id="@+id/button1"
        android:layout_width="0dp"
        android:layout_height="0dp"/>
     
</LinearLayout>

此外,为了防止在进入页面的时候自动弹出软键盘,可以在manifest的activity元素添加<activity  android:windowSoftInputMode="stateAlwaysHidden|adjustPan">

源码:http://download.csdn.net/download/goldenfish1919/6941249

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。