如果一個ListView里面有多套布局(單個布局也行)的可以參考這個帖子:http://blog.csdn.net/fan7983377/article/details/54380588
有這么一個需求,就是在ListView中,每個條目都有Edittext,需要把每個Edittext輸入的數據保存到對應的bean中,想要的效果是這樣的:
這樣一看,也沒什么難度嘛,頂多就是在adapter的getview中對Edittext設置個文本改變監聽嘛,當文本改變就把數據存到bean中,於是,在adapter中寫了這段代碼:
private Context context; private List<Bean> lists; public MyAdapter(Context context, List<Bean> lists) { this.context = context; this.lists = lists; } @Override public int getCount() { return lists.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder vh; if (convertView == null) { convertView = View.inflate(context,R.layout.item,null); vh = new ViewHolder(convertView); convertView.setTag(vh); }else{ vh = (ViewHolder) convertView.getTag(); } Bean bean = lists.get(position); vh.tvname.setText(bean.getName()); vh.mEditText.addTextChangedListener(null); //清除上個item的監聽,防止oom vh.mEditText.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) { bean.setInput(s+""); } @Override public void afterTextChanged(Editable s) { } }); //大部分情況下,getview中有if必須有else if(!TextUtils.isEmpty(bean.getInput())){ vh.mEditText.setText(bean.getInput()); }else{ vh.mEditText.setText(""); } return convertView; } public class ViewHolder{ TextView tvname; EditText mEditText; public ViewHolder(View convertView) { tvname = (TextView) convertView.findViewById(R.id.tv_name); mEditText = (EditText) convertView.findViewById(R.id.et_input); } }
然后很愉快的編譯運行,結果……….
發現運行后想要的效果跟想象中差距太大了,都亂套了,最后猜想應該是文本改變監聽里面設置數據的問題,設置的不是當前控件所在position里面的bean,而是其他的Bean,於是,使用settag(),把bean綁定到當前的Edittext身上,adapter的getView改造如下(添加的是代碼中空隙最大的兩處!):
public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder vh; if (convertView == null) { convertView = View.inflate(context,R.layout.item,null); vh = new ViewHolder(convertView); convertView.setTag(vh); }else{ vh = (ViewHolder) convertView.getTag(); } final Bean bean = lists.get(position); vh.tvname.setText(bean.getName()); //把Bean與輸入框進行綁定 vh.mEditText.setTag(bean); vh.mEditText.addTextChangedListener(null); //清除上個item的監聽,防止oom vh.mEditText.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) { //獲得Edittext所在position里面的Bean,並設置數據 Bean bean = (Bean) vh.mEditText.getTag(); bean.setInput(s+""); } @Override public void afterTextChanged(Editable s) { } }); //大部分情況下,Adapter里面有if必須有else if(!TextUtils.isEmpty(bean.getInput())){ vh.mEditText.setText(bean.getInput()); }else{ vh.mEditText.setText(""); } return convertView; }
於是點擊編譯運行,效果如下:
恩,算是解決了顯示混亂的問題,但模擬器上是好像Edittext的焦點出現了復用條目也跟着獲取了焦點,(如上圖紅色底線代表有焦點),於是加了個清除焦點的屬性EditText.clearFocus(),就解決了
public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder vh; if (convertView == null) { convertView = View.inflate(context,R.layout.item,null); vh = new ViewHolder(convertView); convertView.setTag(vh); }else{ vh = (ViewHolder) convertView.getTag(); } final Bean bean = lists.get(position); vh.tvname.setText(bean.getName()); //把Bean與輸入框進行綁定 vh.mEditText.setTag(bean); //清除焦點 vh.mEditText.clearFocus(); vh.mEditText.addTextChangedListener(null); //清除上個item的監聽,防止oom vh.mEditText.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) { //獲得Edittext所在position里面的Bean,並設置數據 Bean bean = (Bean) vh.mEditText.getTag(); bean.setInput(s+""); } @Override public void afterTextChanged(Editable s) { } }); //大部分情況下,Adapter里面有if必須有else if(!TextUtils.isEmpty(bean.getInput())){ vh.mEditText.setText(bean.getInput()); }else{ vh.mEditText.setText(""); } return convertView; }
效果如下:
雖然模擬器上解決了,但是真機上測試的時候出現了點擊Edittext輸入框時雖然彈出了輸入法,但是還得再次點擊Edittext才能輸入字符,這樣也有點不利於用戶體驗,經過打log發現,當點擊Edittext時,系統會默認刷新adapter,重新繪制下當前屏幕,導致第一次點擊Edittext輸入框時給清除了Edittext的焦點,所以,我們需要在清單文件中的當前activity里配置下彈出輸入框禁止繪制當前屏幕的屬性“Android:windowSoftInputMode=”stateAlwaysHidden|adjustPan””
<activity android:name=".MainActivity" android:windowSoftInputMode="stateAlwaysHidden|adjustPan" >
然后再次運行,點擊輸入框就彈出軟鍵盤而當前輸入框也能直接輸入字符了,好了,終於解決了。(由於手機原因,沒辦法錄效果圖!)
當我們輸入完一條后,往下滑動時發現,軟鍵盤還在屏幕上,沒有隱藏,我們還需要最后一步操作,給ListView設置滾動監聽,當當前狀態為滾動時,隱藏軟鍵盤,代碼如下:
listview.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState){ case AbsListView.OnScrollListener.SCROLL_STATE_IDLE: //當停止滾動時 break; case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: //滾動時 //沒錯,下面這一坨就是隱藏軟鍵盤的代碼 ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); break; case AbsListView.OnScrollListener.SCROLL_STATE_FLING: //手指抬起,但是屏幕還在滾動狀態 break; } }
好了,完美解決,看似很簡單的問題有的時候確實出乎我們的意料,不過,能解決他何嘗不是一件很有成就感的事呢!
原始轉載網址:http://blog.csdn.net/fan7983377/article/details/51516155