ListView返回对View onClick的重复引用

时间:2014-08-13 19:25:31

标签: android listview android-arrayadapter

我的代码expands LinearLayoutclicked。当列表中有14个或更少项目时,它可以正常工作。一旦有超过14个项目,它会重复参考。点击列表中的第一个项目会扩展第1和第15项。当有300件或更多物品时,它甚至可以随机化。我有一段时间没有运气就麻烦了吗

这是我的自定义适配器

public class Scanvinadapter extends BaseAdapter {

    private Activity activity;
    private ArrayList data;
    private static LayoutInflater inflater = null;
    public Resources res;
    Scanvinmodel model = null;
    int i = 0;
    ScanlistListener mCallback;

    public Scanvinadapter(Activity a, ArrayList d, Resources resLocal){
        activity = a;
        data = d;
        res = resLocal;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        try {
            mCallback = (ScanlistListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement ScanlistListener");
        }


    }

    @Override
    public int getCount() {
        if(data.size()<=0)
            return 1;
        return data.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public static class ViewHolder{
        public TextView scanlistvin;
        public TextView scanlistbay;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        LinearLayout ll = null;
        ViewHolder holder;
        if(convertView == null){
            vi = inflater.inflate(R.layout.scanlistview, null);
            holder = new ViewHolder();

            ll = (LinearLayout) vi.findViewById(R.id.scanlist);
            ll.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,100));
            Log.v("position", String.valueOf(position));
            i = i+1;
            vi.setId(i);
            ll.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    mCallback.scanlistclick(v, 0);
                }
            });

            //vi.setOnClickListener(new OnItemClickListener( position ));

            holder.scanlistvin = (TextView) vi.findViewById(R.id.scanlistvin);
            holder.scanlistbay = (TextView) vi.findViewById(R.id.scanlistbay);
            vi.setTag(holder);
        }else
            holder = (ViewHolder)vi.getTag();

        if(data.size()<=0){
            holder.scanlistvin.setText("No Data");
        }else{
            model = null;
            model = (Scanvinmodel) data.get(position);

            holder.scanlistvin.setText(model.getVin());
            holder.scanlistbay.setText(model.getBay());
            return vi;
        }
        return null;
    }


    public void onClick(View v) {
        Log.v("CustomAdapter", "=====Row button clicked=====");
    }

    private class OnItemClickListener implements OnClickListener{
        private int mPosition;

        OnItemClickListener(int position){
            mPosition = position;
        }
        @Override
        public void onClick(View v) {

            Log.v("CustomAdapter", String.valueOf(mPosition) );
            mCallback.scanlistclick(v, mPosition);
        }
    }

    public interface ScanlistListener{
        public void scanlistclick(View v, int i);
    }
}

这是每次点击时调用的工具覆盖开始。我显示id,它似乎是重复的ID。所有数据都是独一无二的。

@Override
public void scanlistclick(View v, int i) {
    new Animutils().expand(v);
    Log.wtf("wtf", String.valueOf(v.getId()));
}

这是展开视图的动画

public class Animutils {
    private static final long ANIMATION_DURATION = 250;
    protected static final String TAG = "Animutils.java";

    public void expand(final View v) {
        //v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        final int targtetHeight = v.getMeasuredHeight();
        //final int targtetHeight = 500;

        //v.getLayoutParams().height = 114;
//      v.setVisibility(View.VISIBLE);
        Animation a = new Animation(){
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                //v.getLayoutParams().height = interpolatedTime == 1 ? LayoutParams.WRAP_CONTENT : (int)(targtetHeight * interpolatedTime);
                //v.getLayoutParams().height = interpolatedTime == 1 ? 500 : (int)(targtetHeight + 25);
                if(interpolatedTime == 0){
                    v.getLayoutParams().height = targtetHeight + 25;
                }else{
                    if(v.getLayoutParams().height == 500){
                        cancel();
                    }else{
                        v.getLayoutParams().height = v.getLayoutParams().height +25;
                    }
                }
                v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

// 1dp/ms

        a.setDuration(ANIMATION_DURATION);
        // a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }



    public void collapse(final View v) {
        final int initialHeight = v.getMeasuredHeight();

        Animation a = new Animation(){
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if(interpolatedTime == 1){
                    v.setVisibility(View.GONE);
                }else{
                    v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
                    v.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        // 1dp/ms
        a.setDuration(ANIMATION_DURATION);
        // a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }
}

更新适配器

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View vi = convertView;
    LinearLayout ll = null;
    ViewHolder holder;
    if(convertView == null){
        vi = inflater.inflate(R.layout.scanlistview, null);
        ll = (LinearLayout) vi.findViewById(R.id.scanlist);
        ll.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,100));
        holder = new ViewHolder();
        holder.scanlist = (LinearLayout) vi.findViewById(R.id.scanlist);
        holder.scanlistvin = (TextView) vi.findViewById(R.id.scanlistvin);
        holder.scanlistbay = (TextView) vi.findViewById(R.id.scanlistbay);
        Log.v("position", String.valueOf(position));
        vi.setTag(holder);
    }else{
        holder = (ViewHolder)vi.getTag();
        ll = holder.scanlist;
        Log.v("position", String.valueOf(position));

    } 

    ll.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            mCallback.scanlistclick(v, 0);
        }
    });




    if(data.size()<=0){
        holder.scanlistvin.setText("No Data");
    }else{
        model = null;
        model = (Scanvinmodel) data.get(position);

        holder.scanlistvin.setText(model.getVin());
        holder.scanlistbay.setText(model.getBay());

    }
    return vi;
 }

2 个答案:

答案 0 :(得分:3)

试试这个男人:只需从你所有的if - else语句中取出点击作业就可以了,

如下面的代码。那么问题是什么?解决方案是什么?

你说当我点击列表中的第1项后用14个项目填充每个东西都很好但当列表填充更多项目时,当我点击项目1时,项目15也响应。那为什么呢?

这是因为convertView。 convertView是一个通过滚动列表创建和回收的视图。此视图可以减少GC调用并为您节省内存。滚动列表后,它首先由您最早的列表项分配,例如列表中的第一项消失,您看到第15项第一项的convertView再次传递给您。在这个时间它不是null,所以你跳过点击分配给它,它保留了作为第一项的分配的最终点击分配的引用。所以当你点击第1项时,这意味着你也点击第15项,因为它们的点击分配是相同的。所以每一行必须由新的事件监听器分配。

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        LinearLayout ll = null;
        ViewHolder holder;
        if(convertView == null){
            vi = inflater.inflate(R.layout.scanlistview, null);
            holder = new ViewHolder();

            ll = (LinearLayout) vi.findViewById(R.id.scanlist);
            ll.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,100));
            Log.v("position", String.valueOf(position));
            i = i+1;
            vi.setId(i);
            holder.scanlist = (LinearLayout) vi.findViewById(R.id.scanlist);
            holder.scanlistvin = (TextView) vi.findViewById(R.id.scanlistvin);
            holder.scanlistbay = (TextView) vi.findViewById(R.id.scanlistbay);
            vi.setTag(holder);
        }else{
            holder = (ViewHolder)vi.getTag();
            ll= holder.scanlistview;
            ll.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,100));
        } 

         ll.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    mCallback.scanlistclick(v, 0);
                }
            });    
        if(data.size()<=0){
            holder.scanlistvin.setText("No Data");
        }else{
            model = null;
            model = (Scanvinmodel) data.get(position);

            holder.scanlistvin.setText(model.getVin());
            holder.scanlistbay.setText(model.getBay());
            return vi;
        }


        return null;
    }

答案 1 :(得分:3)

将此添加到适配器

@Override
public int getViewTypeCount() {                 
    return getCount();
}

@Override
public int getItemViewType(int position) {
    return position;
}