EditText監聽輸入完成和設定點選事件時與父控制元件的衝突問題
最近在做專案時,發現一個問題,最後找到了解決辦法,特在此記錄一下,便於以後自己回憶以及和大家分享
問題描述:我在專案的頁面B放了一個線性佈局,裡面有EditText,本意是從A頁面跳轉到B頁面時,可能會先做別的操作,在修改EditText裡面的內容(闡述一下:我是修改完EditText內容後,過幾秒自動請求網路更改內容),但是當跳轉到B頁面時會彈出軟鍵盤,這顯然不好,最後在xml佈局裡面找到EditText的父控制元件(也就是線性佈局)加了兩個屬性
android:focusable="true"
android:focusableInTouchMode="true"
這樣一來進入B頁面後就不會載入軟鍵盤
但是想修改EditText裡面內容的時候發現一個問題,點選線性佈局時會彈出軟鍵盤,最後修改成功(這裡採用了一個方法讓點選線性佈局時彈出軟鍵盤並把焦點設定給EditText,寫在程式碼① 裡面),但是點選EditText時鍵盤是彈出來了,但是沒有響應線性佈局的點選事件,自然也就沒修改成功,所以找了好多辦法,最後採用分別監聽線性佈局的OnClickListener和EditText的OnTouchListener方法,分別設定相同的方法給兩個監聽,最後解決辦法
(注:我發現EditText使用OnClickListener時有問題,因為EditText的setOnClickListener事件響應中,只有獲取焦點的時候才會響應,如當焦點在別的控制元件上時,只能先點選獲取焦點,第二次點選才會響應,解決辦法改用setOnTouchListener監聽)
一、先是線性佈局的監聽:
LinearLayout llname = findViewById(R.id.ll_name);
llname.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alterName();
}
});
二、再是EditText的監聽
EditText etname = findViewById(R.id.et_name);
//設定etname的點選事件
etname.setOnTouchListener(new View.OnTouchListener() {
//按住和鬆開的標識
int touch_flag=0;
@Override
public boolean onTouch(View v, MotionEvent event) {
touch_flag++;
if(touch_flag==2){
alterName();
}
return false;
}
});
程式碼①
(描述:進入B頁面後當點選線性佈局時,彈出鍵盤,讓線性佈局下面的EditText獲取焦點,然後當鍵盤彈出時,監聽EditText的輸入狀態,當5秒內連續輸入的時候移除上次的延時任務,5秒內不輸入時,執行延時任務,我這裡是請求網路,更改內容)
// 先彈出鍵盤,讓焦點在輸入框上
alterName(){
etMyUsername.requestFocus();// 獲取焦點
imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
if(imm.isActive()){
// 獲取焦點,先設定游標遇到最後,然後監聽輸入框的動態變化
etMyUsername.setSelection(etMyUsername.length());
listenetMyUsername();
}
}
/**監聽輸入框的動態變化*/
private void listenetMyUsername() {
etMyUsername.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (delayRun != null) {
//每次editText有變化的時候,則移除上次發出的延遲執行緒
handler.removeCallbacks(delayRun);
}
}
@Override
public void afterTextChanged(Editable s) {
newName = s.toString();
//延遲5s,如果不再輸入字元,則執行該執行緒的run方法,取消輸入框的焦點
handler.postDelayed(delayRun, 2000);
}
});
}
/**
* 延遲執行緒,看是否還有下一個字元輸入
*/
private Runnable delayRun = new Runnable() {
@Override
public void run() {
//uploadName();
//這裡寫自己的邏輯
}
};
/**上傳名字*/
private void uploadName() {
String url = Urls.Url_My_Name;
Map<String, String> params = new HashMap<>();
params.put("uid", uid);
params.put("name", newName);
OkHttpUtils.post()//
.url(url)//
.params(params)//
.build()//
.execute(new MyStringCallback2());
}
/**上傳名字*/
class MyStringCallback2 extends StringCallback {
@Override
public void onError(Call call, Exception e) {
ToastUtils.showToast(mActivity, "網路有問題,請檢查");
}
@Override
public void onResponse(String response) {
//System.out.println("PersonMsgActivity+介面修改使用者名稱" + response);
MyAlterNameBean bean = new Gson().fromJson(response, MyAlterNameBean.class);
if (bean != null) {
int code = bean.code;
String msg = bean.msg;
if (code != 0) {
ToastUtils.showToast(mActivity, msg);
}else {
//ToastUtils.showToast(mActivity, "修改成功");
// 每次更改成功後要通知我的介面也要改變顯示內容
Intent intent = new Intent();
intent.putExtra(Keys.NEWNAME, newName);
setResult(2, intent);
}
}
}
}