Android 解決在ListView歷史複用中Edittext數據顯示混亂

若是一個ListView裏面有多套佈局(單個佈局也行)的能夠參考這個帖子:http://blog.csdn.net/fan7983377/article/details/54380588 



有這麼一個需求,就是在ListView中,每一個條目都有Edittext,須要把每一個Edittext輸入的數據保存到對應的bean中,想要的效果是這樣的: 
 android

這裏寫圖片描述 


這樣一看,也沒什麼難度嘛,頂多就是在adapter的getview中對Edittext設置個文本改變監聽嘛,當文本改變就把數據存到bean中,因而,在adapter中寫了這段代碼:ide

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(),就解決了this

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;
    }


效果以下:.net

這裏寫圖片描述

雖然模擬器上解決了,可是真機上測試的時候出現了點擊Edittext輸入框時雖然彈出了輸入法,可是還得再次點擊Edittext才能輸入字符,這樣也有點不利於用戶體驗,通過打log發現,當點擊Edittext時,系統會默認刷新adapter,從新繪製下當前屏幕,致使第一次點擊Edittext輸入框時給清除了Edittext的焦點,因此,咱們須要在清單文件中的當前activity裏配置下彈出輸入框禁止繪製當前屏幕的屬性「Android:windowSoftInputMode=」stateAlwaysHidden|adjustPan」code

<activity android:name=".MainActivity"
            android:windowSoftInputMode="stateAlwaysHidden|adjustPan"
            >

而後再次運行,點擊輸入框就彈出軟鍵盤而當前輸入框也能直接輸入字符了,好了,終於解決了。(因爲手機緣由,沒辦法錄效果圖!)blog

當咱們輸入完一條後,往下滑動時發現,軟鍵盤還在屏幕上,沒有隱藏,咱們還須要最後一步操做,給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;
                }
            }

好了,完美解決,看似很簡單的問題有的時候確實出乎咱們的意料,不過,能解決他未嘗不是一件頗有成就感的事呢!get

 

原始轉載網址:http://blog.csdn.net/fan7983377/article/details/51516155

相關文章
相關標籤/搜索