Android ListView GridView 错位

在做Android开发的时候很多地方都要用ListView和GridView, 要快速的加载一个列表并且让它滑动起来非常的流畅我们是一定要做到的,那我会用一些常用的异步加载框架,比如Imageloader,fresco等等。但是我又遇到了问题,使用异步加载的时候经常出现item错位的现象,本来要显示的下一条数据的位置竟然出现了上一条的数据,我当时很费解。对于为什么会出现这样的情况网上也有很多的答案,是因为复用了convertView造成的,这里我写一下我的一些解决方案,本人亲测,解决了我的问题:

一 在Adapter的getView的时候如果你是用的 if 语句,那就一定要有相应的else语句,如果只有if那是很容易错位的。

二 如果上述方法试过了还是错位那还有另一种方法,不让ListView或者GridView自己滚动,自己自定义一个, 然后在ListView的布局外面加一层ScrollView就可以了

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.GridView;

/**
 * Created by yue on 2016/1/6.
 * 自定义不滑动不错位的 GirdView
 */
public class MyCustomGridView extends GridView {

    public MyCustomGridView(Context context) {
        super(context);
    }

    public MyCustomGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyCustomGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

    public boolean dispatchTouchEvent(MotionEvent ev) {
        if(ev.getAction() == MotionEvent.ACTION_MOVE){
            return true;//禁止Gridview进行滑动
        }
        return super.dispatchTouchEvent(ev);
    }
}

三 加tag

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.adapter_follow_list_item, parent,false);
        }

        ImageView img = AdapterUtils.getAdapterView(convertView, R.id.stay_mask_img);
        img.setTag(url.toString);
        if(img.getTag()!=null&&img.getTag().equals(url.toString)){
            img.setImageURI(Uri.parse(url));
        }
    }

另外我在写adapter的时候每次都要写一个ViewHolder, 写的我这个累挺, so 发现了一个封装版的使用了泛型的通用工具方法, 本质当然也是ViewHolder, 这里我贴出代码大家一起研究:

 /**
     * 用于自定义adapter if (convertView == null) { convertView
     * =LayoutInflater.from(context).inflate(R.layout.layout_item,parent,
     * false); } ImageView imageView =
     * getAdapterView(convertView,R.id.imageView);
     *
     * @param convertView
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public static  T getAdapterView(View convertView, int id) {
        SparseArray viewHolder = (SparseArray) convertView.getTag();
        if (viewHolder == null) {
            viewHolder = new SparseArray();
            convertView.setTag(viewHolder);
        }
        View childView = viewHolder.get(id);
        if (childView == null) {
            childView = convertView.findViewById(id);
            viewHolder.put(id, childView);
        }
        return (T) childView;
    }

使用方法:

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.adapter_follow_list_item, parent,false);
        }

        TextView nickName = AdapterUtils.getAdapterView(convertView, R.id.nickname);
        TextView signature = AdapterUtils.getAdapterView(convertView, R.id.signature);
        Button button = AdapterUtils.getAdapterView(convertView, R.id.cancel);
        return convertView;
    }

你可能感兴趣的:(技术文章)