Android之ListView数据错误解决方法

ListView——“点赞”状态屏幕滑动数据解决方法

       我们在使用ListView时候,可能一行数据有名次、头像、昵称、补充文字/数据说明、“点赞”人数及图标,如下图“微信运动界面”所示。


       而当我们有较多行数据,需要滑动屏幕时,这些“点赞”图标的选择状态就会错乱。还是以上图为例,假如当前设备的屏幕可以显示6行数据,总共需要显示9行数据;我们点赞了第1个好友,但是没有显示出来的第7个好友的点赞图标却变“红”了。这就是数据错乱问题,那么我们应该如何解决呢?

     请看我下面的例子(在下面的Demo中,“点赞”图标我换成了可以更换背景色的Button,红色代表已经点赞了)。首先,我们先来看关键代码:

private class PlatformWithStateChangeAdapter extends BaseAdapter{
        LayoutInflater mLayoutInflater = null;
        public PlatformWithStateChangeAdapter(Context context) {
            this.mLayoutInflater = LayoutInflater.from(context);
        }

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

        @Override
        public Object getItem(int position) {
            return null != itemInfoList ? itemInfoList.get(position) : null;
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            final ItemInfo itemInfo = (ItemInfo) getItem(position);
            if (convertView == null){
                holder = new ViewHolder();
                convertView = mLayoutInflater.inflate(R.layout.activity_button_state_change_list,null);

                holder.img = (ImageView) convertView.findViewById(R.id.ivImg_btnstatechange);
                holder.title = (TextView) convertView.findViewById(R.id.tvTitle_btnstatechange);
                holder.info = (TextView) convertView.findViewById(R.id.tvInfo_btnstatechange);
                holder.btnIsSelected = (Button) convertView.findViewById(R.id.btnDetail_btnstatechange);

                final ViewHolder finalHolder = holder;
                holder.btnIsSelected.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ItemInfo itemDetails = (ItemInfo) finalHolder.btnIsSelected.getTag();

                        if (itemDetails.isSelected()){
                            finalHolder.btnIsSelected.setBackgroundResource(R.color.green);
                            itemDetails.setSelected(false);
                        }
                        else {
                            finalHolder.btnIsSelected.setBackgroundResource(R.color.red);
                            itemDetails.setSelected(true);
                        }
                 
                    }
                });
                convertView.setTag(holder);
                holder.btnIsSelected.setTag(itemInfo);             
            }
            else {
                holder = (ViewHolder) convertView.getTag();
                holder.btnIsSelected.setTag(itemInfo);               
            }
            //避免滑屏时出现数据错乱重复
            if (itemInfo.isSelected()){
                holder.btnIsSelected.setBackgroundResource(R.color.red);
            }
            else {
                holder.btnIsSelected.setBackgroundResource(R.color.green);
            }
            holder.img.setImageResource(itemInfo.getImg());
            holder.title.setText(itemInfo.getTitle());
            holder.info.setText(itemInfo.getInfo());
            return convertView;
        }
    }
我们来看一下运行效果:



全部代码:

ButtonStateChangeActivity.java

package com.example.administrator.listviewdemo;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/9/4.
 */
public class ButtonStateChangeActivity extends AppCompatActivity{

    ListView lvPlatforms = null;
    List<ItemInfo> itemInfoList = null;
    PlatformWithStateChangeAdapter platformWithStateChangeAdapter = null;

    @Override
    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_button);

        itemInfoList = getData();
        lvPlatforms = (ListView) findViewById(R.id.lvPlatforms);
        platformWithStateChangeAdapter = new PlatformWithStateChangeAdapter(this);
        lvPlatforms.setAdapter(platformWithStateChangeAdapter);

        ActionBar actionbar = getSupportActionBar();
        actionbar.setTitle(R.string.actionBarTitle_btnstatechange);
        actionbar.setDisplayHomeAsUpEnabled(true);
        actionbar.setDisplayShowHomeEnabled(true);

    }

    private List<ItemInfo> getData(){
        List<ItemInfo> itemInfos = new ArrayList<>();
        ItemInfo itemInfo = new ItemInfo("Android01","I am Android!",R.mipmap.ic_launcher,false);
        itemInfos.add(itemInfo);
        itemInfo = new ItemInfo("Apple01","I am Apple!",R.mipmap.apple02,false);
        itemInfos.add(itemInfo);
        return itemInfos;
    }

    private final class ViewHolder{
        private ImageView img;
        private TextView title;
        private TextView info;
        private Button btnIsSelected;
    }

    private class PlatformWithStateChangeAdapter extends BaseAdapter{
        LayoutInflater mLayoutInflater = null;
        public PlatformWithStateChangeAdapter(Context context) {
            this.mLayoutInflater = LayoutInflater.from(context);
        }

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

        @Override
        public Object getItem(int position) {
            return null != itemInfoList ? itemInfoList.get(position) : null;
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            final ItemInfo itemInfo = (ItemInfo) getItem(position);
            if (convertView == null){
                holder = new ViewHolder();
                convertView = mLayoutInflater.inflate(R.layout.activity_button_state_change_list,null);

                holder.img = (ImageView) convertView.findViewById(R.id.ivImg_btnstatechange);
                holder.title = (TextView) convertView.findViewById(R.id.tvTitle_btnstatechange);
                holder.info = (TextView) convertView.findViewById(R.id.tvInfo_btnstatechange);
                holder.btnIsSelected = (Button) convertView.findViewById(R.id.btnDetail_btnstatechange);

                final ViewHolder finalHolder = holder;
                holder.btnIsSelected.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {                     
                        ItemInfo itemDetails = (ItemInfo) finalHolder.btnIsSelected.getTag();

                        if (itemDetails.isSelected()){
                            finalHolder.btnIsSelected.setBackgroundResource(R.color.green);
                            itemDetails.setSelected(false);
                        }
                        else {
                            finalHolder.btnIsSelected.setBackgroundResource(R.color.red);
                            itemDetails.setSelected(true);
                        }                      
                    }
                });
                convertView.setTag(holder);
                holder.btnIsSelected.setTag(itemInfo);            
            }
            else {
                holder = (ViewHolder) convertView.getTag();
                holder.btnIsSelected.setTag(itemInfo);             
            }

            //避免滑屏时出现数据错乱重复
            if (itemInfo.isSelected()){
                holder.btnIsSelected.setBackgroundResource(R.color.red);
            }
            else {
                holder.btnIsSelected.setBackgroundResource(R.color.green);
            }
            holder.img.setImageResource(itemInfo.getImg());
            holder.title.setText(itemInfo.getTitle());
            holder.info.setText(itemInfo.getInfo());
            return convertView;
        }
    }

    final int updateMenuItemId = 100;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuItem updateMenuItem = menu.add(0,updateMenuItemId,0,"刷新");
        updateMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case updateMenuItemId:
                refresh();
                platformWithStateChangeAdapter.notifyDataSetChanged();
                break;
            case android.R.id.home:
                finish();
                break;
            default:
                break;
        }

        return super.onOptionsItemSelected(item);
    }

    private Context getContext(){
        return this;
    }

    private void refresh(){
        ItemInfo itemInfo = new ItemInfo("Android02","I am Android!02",R.mipmap.ic_launcher,false);
        itemInfoList.add(itemInfo);
        itemInfo = new ItemInfo("Apple02","I am Apple!02",R.mipmap.ic_launcher,false);
        itemInfoList.add(itemInfo);
    }
}


ItemInfo.java
package com.example.administrator.listviewdemo;

/**
 * Created by Administrator on 2016/9/4.
 */
public class ItemInfo {
    private int img;
    private String title;
    private String info;
    private boolean selected;

    public ItemInfo(String title,String info,int img,boolean selected){
        this.title = title;
        this.info = info;
        this.img = img;
        this.selected = selected;
    }

    public int getImg() {
        return img;
    }

    public String getTitle() {
        return title;
    }

    public String getInfo() {
        return info;
    }

    public boolean isSelected() {
        return selected;
    }

    public void setImg(int img) {
        this.img = img;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }
}
 
res/layout/activity_button_state_change_list.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/lvatybtnstatechange"
    xmlns:tools="http://schemas.android.com/tools"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.listviewdemo.ListActivityDemo">


    <ImageView
        android:layout_alignParentLeft="true"
        android:id="@+id/ivImg_btnstatechange"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <!--需要要id,否则app停止运行-->
    <RelativeLayout
        android:layout_toRightOf="@+id/ivImg_btnstatechange"
        android:paddingLeft="10dp"
        android:id="@+id/button_aty_content_btnstatechange"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:textStyle="bold"
            android:textSize="16sp"
            android:id="@+id/tvTitle_btnstatechange"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
        <!--android:maxEms 单位为int类型-->
        <TextView
            android:layout_below="@+id/tvTitle_btnstatechange"
            android:id="@+id/tvInfo_btnstatechange"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    </RelativeLayout>
    <Button
        android:layout_alignParentRight="true"
        android:text="点赞"
        android:background="@drawable/btn_like"
        android:id="@+id/btnDetail_btnstatechange"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>


ListView——CheckBox状态屏幕滑动数据错误解决方法

        之前我们小组在做一个项目,叫信号检测,主要用于检测运营商信号强度、用户可以截屏并查看截屏记录。其中用到ListView来展示截屏结果,我们的app为已经截屏的全部记录的每一行数据(截屏)都提供一个CheckBox,用户可以勾选当前截屏图标删除,先看一下整体的效果:


       在这里也有个坑,当前我们截屏结果较多时(比如9张截屏),我们想删除前3张,勾选了前3张图标的CheckBox,结果第7、8、9张截屏的CheckBox也被勾选了,这当然不是我们希望的。
      解决方法的思路:用一个map来保存每一行选中的状态;我们声明一个HashMap<Integer, View>来保存每一行数据 ,除第一行数据外,其他每行数据都通过getTag()得到已经渲染好的view来重复渲染剩余行的数据。
首先,我们来看一下关键代码:(具体代码实现,可以下载查看我的Github项目: https://github.com/jscly/signal-detection


//通过声明View,表示每一行数据都是一个view
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view;
            ViewHolder holder = null;
            //待查看图片的路径
            final String currentImgFilePath = dirNameToSaveImg + "/" + imgList.get(position);

            if (map.get(position) == null) {
                LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = mInflater.inflate(R.layout.custom_listview_item, null);
                holder = new ViewHolder();
                holder.cbIsSelected = (CheckBox) view.findViewById(R.id.list_cbSelected);
                holder.ivImg = (ImageView) view.findViewById(R.id.list_ivImg);
                holder.tvImgName = (TextView) view.findViewById(R.id.list_tvImgName);
                holder.tvPrtScTime = (TextView) view.findViewById(R.id.list_tvPrtScTime);
                holder.ivNext = (ImageView) view.findViewById(R.id.list_ivNext);
                map.put(position, view);

                view.setTag(holder);
            } else {
                view = map.get(position);
                holder = (ViewHolder) view.getTag();
            }
            holder.cbIsSelected.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    CheckBox cb = (CheckBox) v;
                    //保存当前CheckBox的选中状态
                    currentFileIsCheckedMap.put(currentImgFilePath, cb.isChecked());
                    if (cb.isChecked()) {
                        cb.setFocusable(true);
                        selectedImgList.add(currentImgFilePath);
                        //待删除文件名及其ItemInfo
                        filePath_currentItemInfoMap.put(currentImgFilePath,listItemInfo.get(position));
                    }
                    else {
                        cb.setFocusable(true);
                        selectedImgList.remove(currentImgFilePath);
                        filePath_currentItemInfoMap.remove(currentImgFilePath);
                    }
                }
            });
            holder.ivNext.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ((ImageView)v).setFocusable(true);
                    openPrtSc(currentImgFilePath);
                }
            });

            holder.cbIsSelected.setChecked(currentFileIsCheckedMap.get(currentImgFilePath) != null ? currentFileIsCheckedMap.get(currentImgFilePath) : false);
            holder.ivImg.setImageBitmap(listItemInfo.get(position).getImgBitmap());
            holder.tvImgName.setText(listItemInfo.get(position).getImgName());
            holder.tvPrtScTime.setText(sdf.format(
                    new Date(
                            listItemInfo.get(position).getPrtScTime()
                    )
            ).toString());
            holder.ivNext.setImageResource(listItemInfo.get(position).getImgNextId());
            return view;
        }













  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值