1. 程式人生 > >ListView,GridView,RecyclerView滑動錯位的終極解決辦法

ListView,GridView,RecyclerView滑動錯位的終極解決辦法

直接講重點!

假如你的item佈局裡面包含但不限於這些東西:textView,ImageView,CheckBox,Button...


你一定遇到過滑動列表時item裡面的控制元件錯位,該出現的地方不出現,不該出現的地方反而蹦出來的情況。

我也在網上看過很多解決辦法,很多說給什麼控制元件設定一個tag呀之類的,看著我都覺得麻煩,其實解決滑動錯位並不需要設定什麼tag,就一個if-else就能解決。

下面正片!

問題的所在就是你的adapter裡面,這裡我們直接看一個最簡單ListView 的Adapter,其他的GridView,RecyclerView原理也是一模一樣,就不多贅述。

直接看adapter裡面的getView方法:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item_layout, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.title = (TextView) convertView.findViewById(R.id.title);
            viewHolder.image = (ImageView) convertView.findViewById(R.id.image);
            viewHolder.check = (CheckBox) convertView.findViewById(R.id.check);
            viewHolder.button = (Button) convertView.findViewById(R.id.button);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        ListViewBean listViewBean = mList.get(position);
        viewHolder.title.setText(listViewBean.getTitle());
        //繫結資料

        //重點!!!

        //滑動導致item裡面的控制元件錯位

        //第一種情況
        // 資料繫結之後滑動錯位
        //很多情況我們會寫如下程式碼
        //根據image的路徑是否為空來給ImageView賦值
        //你可能認為邏輯沒錯,如果iamgePath有路徑那麼才給圖片賦值
        //但是執行之後,全TM亂了
        if (!"".equals(listViewBean.getImagePath())) {
            viewHolder.image.setImageURI(Uri.parse(listViewBean.getImagePath()));
        }

        //解決方案:只需要再加上一個else就夠了
        //為什麼加上一個else就不會錯位了?
        //我也懶得給你們講快取什麼的(我也不會講)
        //通俗易懂的來說:
        // 當進入listViewBean.getImagePath()有路徑的時候,
        // 程式進了if裡面,裡面明確規定了我要把路徑賦值給imageView,程式就照著我規定的做
        // 但是,如果listViewBean.getImagePath()是空的時候,程式不會進入if,
        // 不僅沒進if,而且你也沒在任何地方給他規定路徑是空的時候他應該做什麼
        // 那他就只能胡亂給你填資料咯
        if (!"".equals(listViewBean.getImagePath())) {
            viewHolder.image.setImageURI(Uri.parse(listViewBean.getImagePath()));
        } else {
            //所以當路徑為空時,也必須規定該控制元件應該怎麼做
            viewHolder.image.setImageResource(R.mipmap.ic_launcher);
        }

        // 第二種情況:
        //設定某一控制元件顯示或者隱藏

        //下面的程式碼,我定義了一個boolean型別的屬性,用來判斷我的checkBox是否顯示
        //單當你執行之後就會發現,checkBox錯位了
        if (listViewBean.isDisPlayCheck()) {
            viewHolder.check.setVisibility(View.VISIBLE);
        }

        //解決方案:同樣也只需要加上一個else
        //程式碼修改如下,button也同樣
        if (listViewBean.isDisPlayCheck()) {
            viewHolder.check.setVisibility(View.VISIBLE);
        } else {
            viewHolder.check.setVisibility(View.GONE);
        }
        if (listViewBean.isDisPlayButton()) {
            viewHolder.button.setVisibility(View.VISIBLE);
        } else {
            viewHolder.button.setVisibility(View.GONE);
        }
        return convertView;
    }


總結:只要是在ViewHolder裡面聲明瞭的控制元件,要麼不賦值,要麼在所有分支都賦值,有if,就一定要有else,要讓控制元件無論進入哪一個分支都明白自己應該做什麼事