import android.app.Activity; import android.content.Context; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; /** * * ModifyCountDialog ModifyCountDialog = new ModifyCountDialog.Builder( * Activity.this,2030L).build(); * ModifyCountDialog.setModifyCountListener(new ModifyCountListener(){ * @Override * public void onDelivered(long Count) { * Log.d(TAG, "--------送你"+Count+"朵花"); * } * * }); * ModifyCountDialog.show(); * * */ public class ModifyCountDialog extends popDialog implements OnClickListener ,OnTouchListener{ private static final String TAG = "ModifyCountDialog"; private static final int SCORE_PER_ = 10; // currentScore = totalScore - Count * SCORE_PER_ private Activity mActivity; private String title; // title string, have default // R.string.dialog_deliver__title private long totalScore; // user total score private long mMaxCount = 0; private long mCurrentCount = 0; private long mCurrentScore; private Button mBtnCountSub; private Button mBtnCountAdd; private TextView mTvScore; private EditText mEditCount; // private boolean isButtonCountChange=false; public static class Builder { private final Activity mActivity; private String title; private long score; // user current score /** * @param context * @param score */ public Builder(Activity context, long score) { this.mActivity = context; this.score = score; } public Builder title(String title) { this.title = title; return this; } public ModifyCountDialog build() { return new ModifyCountDialog(this); } } private ModifyCountDialog(Builder builder) { super(builder.mActivity); this.mActivity = builder.mActivity; this.totalScore = builder.score; if (this.totalScore > 0) { this.mMaxCount = (long) (this.totalScore / SCORE_PER_); this.mCurrentScore = this.totalScore; } if (!TextUtils.isEmpty(builder.title)) { this.title = builder.title; } initDialog(); } private void initDialog() { View view = LayoutInflater.from(mActivity).inflate( R.layout.dialog_deliver_, null, false); view.findViewById(R.id.btn_cancle).setOnClickListener(this); view.findViewById(R.id.btn_deliver).setOnClickListener(this); mBtnCountSub = (Button) view .findViewById(R.id.dialog_deliver__count_sub); mBtnCountSub.setOnClickListener(this); mBtnCountAdd = (Button) view .findViewById(R.id.dialog_deliver__count_add); mBtnCountAdd.setOnClickListener(this); mTvScore = (TextView) view .findViewById(R.id.dialog_deliver__score_tv); mTvScore.setText(String.valueOf(totalScore)); mEditCount = (EditText) view .findViewById(R.id.dialog_deliver__count); mEditCount.setOnTouchListener(this); //set keyboard property, the dialog will push up getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); this.build(view, true); } @Override public boolean onTouch(View v, MotionEvent event) { if(v.getId()==R.id.dialog_deliver_flower_count) { mEditFlowerCount.selectAll(); //select all character in EditText showKeyboard(mEditFlowerCount); //without calling this. keyboard hide return true; } return false; } private boolean isCountLegal(long count){ return (count >=0)&&(count <= mMaxCount); } /** * EditText text change watcher * * when user input is illegal, setText to 0 or MaxCount * * warn: call setText() in wrong place, will cause infinite loop and StackOverFlow * */ TextWatcher mTextWatcher = new TextWatcher() { private long mCount; @Override public void onTextChanged(CharSequence s, int start, int before,int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count,int after) { } @Override public void afterTextChanged(Editable s) { String str = s.toString(); // Log.d(TAG, "---myc---afterTextChanged str------" + str); if(!TextUtils.isEmpty(str) && TextUtils.isDigitsOnly(str)){ mCount = Long.parseLong(str); }else{ mCount = 0; } //if user input is illegal, set to legal count if(!isCountLegal(mCount)){ if(mCount < 0){ mCount = 0; }else if(mCount > mMaxFlowerCount){ mCount = mMaxFlowerCount; } mEditFlowerCount.setText(String.valueOf(mCount)); //illegal, set to 0 or maxFlowerCount mEditFlowerCount.selectAll(); } setCurrentFlowerCount(mCount); } }; /** * getter * * @return */ public long getCurrentCount() { return this.mCurrentCount; } /** * setter * * @return */ public void setCurrentCount(long Count) { if(isCountLegal(Count) && Count!=mCurrentCount){ Log.d(TAG, "---setCurrentCount------" + Count); this.mCurrentCount = Count; refreshUI(Count); } } ModifyCountListener mModifyCountListener; public interface ModifyCountListener { //在Activity里弹框获取用户输入,可以通过回调的方法来获取用户输入值 void onModified(long Count); } public void setModifyCountListener(ModifyCountListener listener) { mModifyCountListener = listener; } /** * user press "modify" button * */ private void doModifyCount() { if (mModifyCountListener != null) { mModifyCountListener.onModified(mCurrentCount); //将值回调给Activity } } /** * refresh EditText, current core TextView and so on * * @param Count */ private void refreshUI(long Count) { mCurrentScore = totalScore - Count * SCORE_PER_; if (mCurrentScore >= 0) { mTvScore.setText(String.valueOf(mCurrentScore)); } if (Count <= 0) { setBtnClickable(false, true); } else if (Count >= mMaxCount) { setBtnClickable(true, false); } else { setBtnClickable(true, true); } } /** * hide keyboard * * @param v */ private void hideKeyboard(View v) { // Log.d(TAG, "---hideKeyboard()------"); if(v == null){ return; } InputMethodManager imm = (InputMethodManager) v.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } /** * show keyboard * * @param v */ private void showKeyboard(View v) { // Log.d(TAG, "---showKeyboard()------"); if(v == null){ return; } InputMethodManager imm = (InputMethodManager) v.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(v, 0); } /** * set Button Clickable * * @param canSub * if true, can sub count * @param canAdd * if true, can add count */ private void setBtnClickable(boolean canSub, boolean canAdd) { mBtnCountSub.setClickable(canSub); mBtnCountAdd.setClickable(canAdd); } @Override public void onClick(View view) { if(!view.equals(R.id.dialog_deliver__count)) { hideKeyboard(mEditCount); } switch (view.getId()) { case R.id.btn_cancle: this.dismiss(); break; case R.id.btn_deliver: doModifyCount(); this.dismiss(); break; case R.id.count_sub: if (mCurrentCount > 0) { setCurrentCount(mCurrentCount - 1); mEditCount.setText(String.valueOf(mCurrentCount)); } break; case R.id.count_add: if (getCurrentCount() < mMaxCount) { setCurrentCount(getCurrentCount() + 1); mEditCount.setText(String.valueOf(mCurrentCount)); } break; default: break; } } }
包括
(1)隐藏 和 弹出键盘
1 /** 2 * hide keyboard 3 * 4 * @param v 5 */ 6 private void hideKeyboard(View v) { 7 // Log.d(TAG, "---hideKeyboard()------"); 8 if(v == null){ 9 return; 10 } 11 InputMethodManager imm = (InputMethodManager) v.getContext() 12 .getSystemService(Context.INPUT_METHOD_SERVICE); 13 14 imm.hideSoftInputFromWindow(v.getWindowToken(), 0); 15 } 16 17 18 /** 19 * show keyboard 20 * 21 * @param v 22 */ 23 private void showKeyboard(View v) { 24 // Log.d(TAG, "---showKeyboard()------"); 25 if(v == null){ 26 return; 27 } 28 InputMethodManager imm = (InputMethodManager) v.getContext() 29 .getSystemService(Context.INPUT_METHOD_SERVICE); 30 31 imm.showSoftInput(v, 0); 32 }
(2)防止键盘挡住输入框
1 //set keyboard property, the dialog will push up 防止EditText被挡住, 往上推Dialog 2 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | 3 WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
(3)点击EditText以外的区域,隐藏键盘,注意父view要设置onClickListener
parentView.setOnClickListener(this);
@Override public void onClick(View view) { if(!view.equals(R.id.dialog_deliver__count)) { hideKeyboard(mEditCount); } }
本来想在 EditText OnFocusListener()里监听, 失去焦点后,隐藏键盘. 不起作用
因为对话框弹出的时候, EditText的isFocused是true的。除非点击按钮等,才会失去焦点。但是现在是想点击任何区域都失去焦点。
所以需要通过监听整个父控件
(4) 监听EditText输入
官方文档也指出:千万注意别在三个方法里随意重复调用setText,会死循环
mEditCount.addTextChangedListener(mTextWatcher); //先给EditText设置监听
1 /** 2 * EditText text change watcher 3 * 4 * when user input is illegal, setText to 0 or MaxCount 5 * 6 * warn: call setText() in wrong place, will cause infinite loop and StackOverFlow 7 * 8 */ 9 TextWatcher mTextWatcher = new TextWatcher() { 10 private long mCount; 11 @Override 12 public void onTextChanged(CharSequence s, int start, int before, 13 int count) { 14 15 } 16 17 @Override 18 public void beforeTextChanged(CharSequence s, int start, int count, 19 int after) { 20 21 } 22 23 @Override 24 public void afterTextChanged(Editable s) { 25 String str = s.toString(); 26 // Log.d(TAG, "---afterTextChanged str------" + str); 27 28 if(!TextUtils.isEmpty(str) && TextUtils.isDigitsOnly(str)){ 29 mCount = Long.parseLong(str); 30 }else{ 31 mCount = 0; 32 } 33 34 //if user input is illegal, set to legal count 35 if(!isCountLegal(mCount)){ 36 if(mCount < 0){ 37 mCount = 0; 38 }else if(mCount > mMaxCount){ 39 mCount = mMaxCount; 40 } 41 mEditCount.setText(String.valueOf(mCount)); //illegal, set to 0 or maxCount 42 mEditCount.selectAll(); //如果设置成最大值以后不全选,再点一个数字.s比最大值还大,EditText没反 //应,看起来就像失去焦点了. 但事实上调用 isFocused判断时, 还是有焦点的 43 } 44 setCurrentCount(mCount); 45 } 46 };
(5)全选一个输入框的内容
1 @Override 2 public boolean onTouch(View v, MotionEvent event) { 3 if(v.getId()==R.id.dialog_deliver__count) { 4 mEditCount.selectAll(); //全选EditText的内容 5 showKeyboard(mEditCount); //全选完如果不调用这个,不弹出键盘 6 return true; 7 } 8 return false; 9 }