listview中item上点击textview改变该itme上textview的值发生混乱

列蒙太奇 2016-03-07 02:00:13
各位大神,我目前做个listview,listview的item上有很多控件,textview就是其中一个。我要实现的功能是,仅仅点击item上的textview,点击listview上任何的item上的textview,该行上的textview就改变值,其他item上的textview就不能改变值。

目前listview中item上点击textview改变该itme上textview的值发生混乱,即点击某一行item的textview,该行textview值不发生改变,反而其他行item发生改变了。

public class ContactFriendAdapter extends BaseAdapter{
private static final String TAG = ContactFriendAdapter.class.getSimpleName();
private List<ContactFreindInfo> dataList;
private Context context;
private LayoutInflater inflater;

private ViewHolder viewholder;
private List<String> listInvited;

private MyClickListener myClickListener = null;

public ContactFriendAdapter(Context context, List<ContactFreindInfo> dataList){
this.dataList = dataList;
this.context = context;
this.inflater = LayoutInflater.from(context);
}

public List<ContactFreindInfo> getDataList() {
return dataList;
}

public void setDataList(List<ContactFreindInfo> dataList) {
this.dataList = dataList;
}

@Override
public int getCount() {
return dataList.size();
}

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

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

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if(convertView==null){
viewholder = new ViewHolder();
convertView = inflater.inflate(R.layout.layout_select_contact_friends, null);
myClickListener = new MyClickListener(position);
viewholder.ivHeader = (ImageView) convertView.findViewById(R.id.iv_head);
viewholder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
viewholder.tvPhone = (TextView) convertView.findViewById(R.id.tv_phone);
viewholder.tvIsInvited = (TextView) convertView.findViewById(R.id.tv_is_invited);

convertView.setTag(viewholder);
}else{
viewholder = (ViewHolder) convertView.getTag();
}

notifyDataSetChanged(); //刷新数据

if(dataList.get(position).getContacNameList().size()>1){
for(int i=0; i<dataList.get(position).getContacNameList().size(); i++){
viewholder.tvName.setText(dataList.get(position).getContacNameList().get(i));
viewholder.tvPhone.setText(dataList.get(position).getPhoneNumList().get(i)); //FIXME
}
}else if(dataList.get(position).getContacNameList().size() == 1){
viewholder.tvName.setText(dataList.get(position).getContacNameList().get(0));
viewholder.tvPhone.setText(dataList.get(position).getPhoneNumList().get(0));
}

viewholder.tvIsInvited.setOnClickListener(myClickListener);

return convertView;
}

/**
* 获取已邀请的联系人的电话列表
* @return
*/
public List<String> getInvitedList(){
return listInvited;
}


public class ViewHolder{
ImageView ivHeader;
TextView tvName;
TextView tvPhone;
TextView tvIsInvited;
}

private class MyClickListener implements OnClickListener{

private int position;

public MyClickListener(int position){
this.position = position;
}

@Override
public void onClick(View v) {
// FIXME
viewholder.tvIsInvited.setText("已发送邀请");
listInvited = new ArrayList<String>();
if(dataList.get(position).getContacNameList().size()>1){
for(int i=0; i<dataList.get(position).getContacNameList().size(); i++){
listInvited.add(dataList.get(position).getPhoneNumList().get(i));
}
}else if(dataList.get(position).getContacNameList().size() == 1){
listInvited.add(dataList.get(position).getPhoneNumList().get(0));
}
Log.d(TAG, "你点击了第"+position+"个人");

}

}
}


我现在贴上代码,看看应该怎么改?

求求大神指点指点。
...全文
856 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
梦游人布拿拿 2017-05-11
  • 打赏
  • 举报
回复
楼主还看的到么?过了一年多了啊~ 在您的代码68行出添加这一句:viewholder.tvIsInvited.setText("邀请"); 即可。 由于listView的缓存机制,你后面的item都会复用之前一屏中的整体的item,如果在后面的item中没有对Item中任何控件重新赋值的话,就会跟之前一样;所以把每项Item所有控件都赋值,这样就把缓存中的初始数据给覆盖掉; 如果看不懂,请不要喷哈,你添加那一句就能解决问题了。
YaphetS_Jo 2017-01-13
  • 打赏
  • 举报
回复
@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder viewholder = null;
        if(convertView==null){
            viewholder = new ViewHolder();
            convertView = inflater.inflate(R.layout.layout_select_contact_friends, null);
            myClickListener = new MyClickListener(position);
            viewholder.ivHeader = (ImageView) convertView.findViewById(R.id.iv_head);
            viewholder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
            viewholder.tvPhone = (TextView) convertView.findViewById(R.id.tv_phone);
            viewholder.tvIsInvited = (TextView) convertView.findViewById(R.id.tv_is_invited);
              
            convertView.setTag(viewholder);
        }else{
            viewholder = (ViewHolder) convertView.getTag();
        }
 
         viewholder.tvName.setText(dataList.get(position).getContacNameList().get(i));
         viewholder.tvPhone.setText(dataList.get(position).getPhoneNumList().get(i)); //FIXME
 
        viewholder.tvIsInvited.setOnClickListener(new OnClickListener{
@Override
        public void onClick(View v) {
viewholder.tvIsInvited.setText("改变");
        }
});
          
        return convertView;
    }
zoulianxiao0526 2017-01-12
  • 打赏
  • 举报
回复
我也遇到这种问题了,不过我是将ViewHolder声明成全局变量了,改成局部变量就好了
dong_junshuai 2016-08-10
  • 打赏
  • 举报
回复
楼主问题解决了么?同样的问题,求助啊。。。。
Ronaldo9999 2016-04-01
  • 打赏
  • 举报
回复
getView 的逻辑有问题 notifyDataSetChange 添加事件监听 都不该在这里出现
卖萌耍宝 2016-03-31
  • 打赏
  • 举报
回复
你应该给MyClickListener传入ContactFreindInfo对象,先修改ContactFreindInfo中的数据,给你需要修改的View修改数据(把你需要修改内容的View也传进去)。 getView中不要有操作数据的或者刷新页面的操作,不然那样维护起来很麻烦的。
列蒙太奇 2016-03-31
  • 打赏
  • 举报
回复
这个帖子,我(13楼)回复得很乱,我本想重新编辑的,但无权限。因此重新回复12楼的。 if(convertView==null){ viewholder = new ViewHolder(); convertView = inflater.inflate(R.layout.layout_select_contact_friends, null); // myClickListener = new MyClickListener(position); //注释掉 viewholder.ivHeader = (ImageView) convertView.findViewById(R.id.iv_head); viewholder.tvName = (TextView) convertView.findViewById(R.id.tv_name); viewholder.tvPhone = (TextView) convertView.findViewById(R.id.tv_phone); viewholder.tvIsInvited = (TextView) convertView.findViewById(R.id.tv_is_invited); convertView.setTag(viewholder); }else{ viewholder = (ViewHolder) convertView.getTag(); } //在下面增加这一句。(我以前都是这样做的) 但是效果没有用! viewholder.tvIsInvited.setOnClickListener(new MyClickListener(position)); 我这样修改也没有用呢! 点击之后text值还是有问题。 无法解决,不知各位大神有没有解决方法!
列蒙太奇 2016-03-31
  • 打赏
  • 举报
回复
[引用 12 楼 xingzhong128 的回复:] if(convertView==null){ viewholder = new ViewHolder(); convertView = inflater.inflate(R.layout.layout_select_contact_friends, null); // myClickListener = new MyClickListener(position); //注释掉都没有用 viewholder.ivHeader = (ImageView) convertView.findViewById(R.id.iv_head); viewholder.tvName = (TextView) convertView.findViewById(R.id.tv_name); viewholder.tvPhone = (TextView) convertView.findViewById(R.id.tv_phone); viewholder.tvIsInvited = (TextView) convertView.findViewById(R.id.tv_is_invited); convertView.setTag(viewholder); }else{ viewholder = (ViewHolder) convertView.getTag(); } //在下面增加这一句。(我以前都是这样做的) 但是效果没有用! viewholder.tvIsInvited.setOnClickListener(new MyClickListener(position)); 这个代码里的 myClickListener 有问题,当复用缓存的时候myClickListener实际上一直都是最后一次实例化的对象,这个new操作大部分情况下不会被执行,只有刚开始展示还没有复用UI的时候被执行过。 所以把这句new 去掉然后在 viewholder.tvIsInvited.setOnClickListener(new MyClickListener(position)); 这样就可以了
xingzhong128 2016-03-15
  • 打赏
  • 举报
回复
if(convertView==null){ viewholder = new ViewHolder(); convertView = inflater.inflate(R.layout.layout_select_contact_friends, null); myClickListener = new MyClickListener(position); viewholder.ivHeader = (ImageView) convertView.findViewById(R.id.iv_head); viewholder.tvName = (TextView) convertView.findViewById(R.id.tv_name); viewholder.tvPhone = (TextView) convertView.findViewById(R.id.tv_phone); viewholder.tvIsInvited = (TextView) convertView.findViewById(R.id.tv_is_invited); convertView.setTag(viewholder); }else{ viewholder = (ViewHolder) convertView.getTag(); } 这个代码里的 myClickListener 有问题,当复用缓存的时候myClickListener实际上一直都是最后一次实例化的对象,这个new操作大部分情况下不会被执行,只有刚开始展示还没有复用UI的时候被执行过。 所以把这句new 去掉然后在 viewholder.tvIsInvited.setOnClickListener(new MyClickListener(position)); 这样就可以了
列蒙太奇 2016-03-15
  • 打赏
  • 举报
回复
这个问题依然没有解决,这些天出差去了,现在回来对着这个问题,依然头疼。
public class ContactFriendAdapter extends BaseAdapter{
    private static final String TAG = ContactFriendAdapter.class.getSimpleName();
    private List<ContactFreindInfo> dataList;
    private Context context;
    private LayoutInflater inflater;
    private  MyClickListener myClickListener;
     
    public ContactFriendAdapter(Context context, List<ContactFreindInfo> dataList){
        this.dataList = dataList;
        this.context = context;
        this.inflater = LayoutInflater.from(context);
    }
     
    public List<ContactFreindInfo> getDataList() {
        return dataList;
    }
 
    public void setDataList(List<ContactFreindInfo> dataList) {
        this.dataList = dataList;
    }
 
    @Override
    public int getCount() {
        return dataList.size();
    }
 
    @Override
    public Object getItem(int position) {
        return dataList.get(position);
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
 
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewholder = null;
        if(convertView==null){
            viewholder = new ViewHolder();
            convertView = inflater.inflate(R.layout.layout_select_contact_friends, null);
            myClickListener = new MyClickListener(position);
            viewholder.ivHeader = (ImageView) convertView.findViewById(R.id.iv_head);
            viewholder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
            viewholder.tvPhone = (TextView) convertView.findViewById(R.id.tv_phone);
            viewholder.tvIsInvited = (TextView) convertView.findViewById(R.id.tv_is_invited);
             
            convertView.setTag(viewholder);
        }else{
            viewholder = (ViewHolder) convertView.getTag();
        }

         viewholder.tvName.setText(dataList.get(position).getContacNameList().get(i));
         viewholder.tvPhone.setText(dataList.get(position).getPhoneNumList().get(i)); //FIXME

        viewholder.tvIsInvited.setOnClickListener(myClickListener);
         
        return convertView;
    }
      
    public class ViewHolder{
        ImageView ivHeader;
        TextView tvName;
        TextView tvPhone;
        TextView tvIsInvited;
    }
     
    private class MyClickListener implements OnClickListener{
         
        private int position;
         
        public MyClickListener(int position){
            this.position = position;
        }
 
        @Override
        public void onClick(View v) {
            // FIXME
            viewholder.tvIsInvited.setText("已发送邀请");  //  点击哪里一行的item上的textview也改变值了,但是,如果滑动,新出来的i对应被复用的item上textview也改变了值, 这里有问题啊!像大家说的,viewholder的缓存机制错乱的问题,但是我不理解缓存机制,因此不懂得如何去修复这个问题。大神,再次拜托了。 
            Log.d(TAG, "你点击了第"+position+"个人");  // 这里永远都是没有错误的。点击了哪个position的item,就toast哪一行
             
        }
         
    }
}
三月三对半 2016-03-15
  • 打赏
  • 举报
回复
个人拙见。是不是识图用非UI线程更新UI的问题? 我有一次放了一个Listview,点击一个按钮以后会往Listview的数据源里面添加新的数据,但是一直没有显示,我拖动一下Listview就显示出来了。 后来发现是安卓有UI和非UI线程的说法的。如果非UI线程要改变UI的话,必须通过比如Handler等方法传递消息过去,让UI线程来做出相应的改动。 可以搜搜看这方面的东西试试看
wei220000 2016-03-10
  • 打赏
  • 举报
回复
你代码写的太乱了,你有一个List<String> listInvited,那你在点击的txt时候,只需要listInvited.set(position,"已经邀请了");然后做一些逻辑,不要listInvited = new ArrayList<String>();再ContactFriendAdapter.this.notifyDataSetChanged();ViewHolder千万不要设置成全局变量啊。。。。 geiview中的 notifyDataSetChanged(); //刷新数据 要去掉
列蒙太奇 2016-03-10
  • 打赏
  • 举报
回复
按照5楼和6楼的方法,依然存在这个问题。还是没有解决掉。能否给个代码片段呢?
浅笑_JIE 2016-03-08
  • 打赏
  • 举报
回复
ViewHolder 不要用全局 不要在 getView 使用 notify 在你的TextView的监听事件里 把list里面对应的Item的值改成已发送/邀请状态 然后再notify
ganshenml 2016-03-08
  • 打赏
  • 举报
回复
我改了一下之前自己的实例,结果每次都是最后一个Item上面的 值发生改变。 于是,我想了一下,可能是缓存机制导致在装载ListView的时候,最终获取的ViewHolder就是最后一项,那么无论点击哪一个ListView上面的控件都会是对最后一个装载的ViewHolder造成影响。既然这里只是将最后一个ViewHolder进行改变,那么突破点就是要获取到所有装载的ViewHolder的对象, 解决办法是:在该Adapter中自定义Lsit<ViewHolder>,然后在getView方法中于每次实例化ViewHolder对象时就将该ViewHolder实例后的对象加入到List中去。 最后在ViewHolder.textView的单击监听方法中通过list.get(positon).textview.setText(...)方法来达到目的。 这种方式耗内存多少不太清楚,楼主可以试试。
  • 打赏
  • 举报
回复
我感觉可能是listview中的adapter的convertiew的复用问题,你百度一下listview的缓存机制,还有listview的item混乱,有很多这种讲解的,不知道能不能帮助你
列蒙太奇 2016-03-08
  • 打赏
  • 举报
回复


死循环就不会出现,但是就是listview上的textview点击后出现错乱。我注释了第57行notifyDataSetChanged(),结果都一样。还是没有解决掉。你有什么方法吗?
z790020590 2016-03-08
  • 打赏
  • 举报
回复
private List<String> listInvited; 把String改为一个对象 加一个状态0 点击修改状态1 在调用notifyDataSetChanged();
ken哥 2016-03-07
  • 打赏
  • 举报
回复
建议你,赋值给实体(或集合元素),notifyDataSetChanged 在getview里再把这值赋给TextView. PS.你在57行notifyDataSetChanged,确定不会导致死循环?
列蒙太奇 2016-03-07
  • 打赏
  • 举报
回复
自己顶一下,希望这个帖子不要这样就沉下去~~~

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧