【问题标题】:Listitems change position when scrolling in ListView in Android [duplicate]在Android的ListView中滚动时Listitems改变位置[重复]
【发布时间】:2017-10-11 06:08:11
【问题描述】:

我是 Android 新手,我正在使用包含图像和一些文本的 customlistitemsListView,当我向上/向下滚动列表查看位置时发现了一个问题的 listItems 正在发生变化。那么有人可以帮助我吗?我在这里发布我的适配器以供您参考。希望你能帮我弄清楚。

OfferAdapter

public class OfferAdapter extends BaseAdapter {
    private Context mContext;
    private ArrayList<Offer> OfferList;


    public OfferAdapter(Context c, ArrayList<Offer> OfferList) {
        mContext = c;
        this.OfferList = OfferList;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return OfferList.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        View grid;
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if (convertView == null) {

            grid = new View(mContext);
            grid = inflater.inflate(R.layout.raw_offer, null);
            TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
            ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
            TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
            TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
            tv_ofr_desc.setText(OfferList.get(position).getDescription());
            tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
            Date from = new Date();
            Date to = new Date();
            SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
            try {
                from = input.parse(OfferList.get(position).getStart_date());
                to = input.parse(OfferList.get(position).getEnd_date());      // parse input

            } catch (ParseException e) {
                e.printStackTrace();
            }

            tv_date.setText(output.format(from) + " TO " + output.format(to));

            Picasso.with(mContext)
                    .load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
                    .placeholder(R.drawable.ic_no_img)
                    .error(R.drawable.ic_no_img)
                    .into(iv_pic);
        } else {
            grid = (View) convertView;
        }

        return grid;
    }
}

【问题讨论】:

    标签: android listview adapter android-adapter


    【解决方案1】:

    有多个问题:

    1. 代替

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

    你应该写

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

    2. 代替

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View grid;
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
        if (convertView == null) {
    
            grid = new View(mContext);
            grid = inflater.inflate(R.layout.raw_offer, null);
    
            // [all that initializing stuff]
    
        } else {
            grid = (View) convertView;
        }
    
        return grid;
    }
    

    你应该写

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
    
        View grid;
        if (convertView == null) {
            grid = inflater.inflate(R.layout.raw_offer, parent, false);
        } else {
            grid = convertView;
        }
    
        // [all that initializing stuff]
    
        return grid;
    }
    

    您还可以查看 ViewHolder 概念以提高列表的性能:

    【讨论】:

      【解决方案2】:

      更改一些适配器方法,例如 -

      @Override
          public Offer getItem(int position) {
              // TODO Auto-generated method stub
              return OfferList.get(position);
          }
      
          @Override
          public long getItemId(int position) {
              // TODO Auto-generated method stub
              return position;
          }
      

      所以你的适配器将是 -

      public class OfferAdapter extends BaseAdapter {
          private Context mContext;
          private ArrayList<Offer> OfferList;
      
      
          public OfferAdapter(Context c, ArrayList<Offer> OfferList) {
              mContext = c;
              this.OfferList = OfferList;
          }
      
          @Override
          public int getCount() {
              // TODO Auto-generated method stub
              return OfferList.size();
          }
      
          @Override
          public Offer getItem(int position) {
              // TODO Auto-generated method stub
              return OfferList.get(position);
          }
      
          @Override
          public long getItemId(int position) {
              // TODO Auto-generated method stub
              return position;
          }
      
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
              // TODO Auto-generated method stub
              View grid;
              LayoutInflater inflater = (LayoutInflater) mContext
                      .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      
              if (convertView == null) {
      
                  grid = new View(mContext);
                  grid = inflater.inflate(R.layout.raw_offer, null);
                  TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
                  ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
                  TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
                  TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
                  tv_ofr_desc.setText(OfferList.get(position).getDescription());
                  tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
                  Date from = new Date();
                  Date to = new Date();
                  SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
                  SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
                  try {
                      from = input.parse(OfferList.get(position).getStart_date());
                      to = input.parse(OfferList.get(position).getEnd_date());      // parse input
      
                  } catch (ParseException e) {
                      e.printStackTrace();
                  }
      
                  tv_date.setText(output.format(from) + " TO " + output.format(to));
      
                  Picasso.with(mContext)
                          .load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
                          .placeholder(R.drawable.ic_no_img)
                          .error(R.drawable.ic_no_img)
                          .into(iv_pic);
              } else {
                  grid = (View) convertView;
              }
      
              return grid;
          }
      }
      

      【讨论】:

        【解决方案3】:

        您的问题在于您的getView() 实现,并且来自对方法参数的作用以及此方法如何填充ListView 的误解。这是完全可以理解的; ListView 有点复杂。

        要理解的重要一点是ListView 将建立一个视图“池”,然后回收它们,这样就不需要在每次滚动列表时重新创建它们.您之前创建并从getView() 返回的视图可以作为convertView 参数传入;在这些情况下,您需要做的就是更新该视图的 UI。

        考虑到这一点,您可以将getView() 重写如下:

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View grid;
        
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) mContext
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        
                grid = inflater.inflate(R.layout.raw_offer, parent, false);
            } else {
                grid = convertView;
            }
        
            TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
            ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
            TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
            TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
            tv_ofr_desc.setText(OfferList.get(position).getDescription());
            tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
            Date from = new Date();
            Date to = new Date();
            SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
            try {
                from = input.parse(OfferList.get(position).getStart_date());
                to = input.parse(OfferList.get(position).getEnd_date());      // parse input
            } catch (ParseException e) {
                e.printStackTrace();
            }
        
            tv_date.setText(output.format(from) + " TO " + output.format(to));
        
            Picasso.with(mContext)
                    .load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
                    .placeholder(R.drawable.ic_no_img)
                    .error(R.drawable.ic_no_img)
                    .into(iv_pic);
        
            return grid;
        }
        

        您还可以进行其他优化。最简单的就是去掉View grid这个变量;你可以直接使用convertView。更复杂的是使用“视图持有者”模式来缓存各种findViewById() 调用的结果。

        【讨论】:

        【解决方案4】:

        你需要修改你的getView()方法如下-

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            View grid = convertView;
            LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        
            if (grid == null) {
                grid = inflater.inflate(R.layout.raw_offer, parent, false);
            }
            TextView tv_ofr_hdr = (TextView) grid.findViewById(R.id.tv_ofr_hdr);
            ImageView iv_pic = (ImageView) grid.findViewById(R.id.iv_pic);
            TextView tv_ofr_desc = (TextView) grid.findViewById(R.id.tv_ofr_desc);
            TextView tv_date = (TextView) grid.findViewById(R.id.tv_date);
            tv_ofr_desc.setText(OfferList.get(position).getDescription());
            tv_ofr_hdr.setText(OfferList.get(position).getHeadline());
            Date from = new Date();
            Date to = new Date();
            SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
            try {
                    from = input.parse(OfferList.get(position).getStart_date());
                    to = input.parse(OfferList.get(position).getEnd_date());      // parse input
        
            } catch (ParseException e) {
                    e.printStackTrace();
            }
        
            tv_date.setText(output.format(from) + " TO " + output.format(to));
        
            Picasso.with(mContext)
                        .load(OfferList.get(position).getPhoto().replaceAll(" ", "%20"))
                        .placeholder(R.drawable.ic_no_img)
                        .error(R.drawable.ic_no_img)
                        .into(iv_pic);    
            return grid;
        }
        

        你还需要重写这两个方法 -

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

        【讨论】:

        • 我收到一个错误“错误:(62, 42) 错误:变量网格可能尚未初始化”
        • 现在列表来了,但是当我滚动它时,它在 com.abc.allaboutcity.adapter.OfferAdapter.getView(OfferAdapter.java:62) 的 com.abc.allaboutcity.adapter.OfferAdapter.getView(OfferAdapter.java:62) 下崩溃了.widget.AbsListView.obtainView(AbsListView.java:2240) 在 android.widget.ListView.makeAndAddView(ListView.java:1790)
        • 你能帮帮我吗?为此
        • 以这种方式覆盖 getViewTypeCount() 和 getItemViewType() 是错误的。仅包含一种项目的简单列表通常只有一种视图类型。然后 getViewTypeCount() 应该返回 1 并且 getItemViewType(int position) 应该返回 0;
        • 它给 null 因为我忘了初始化网格。检查更新以回答。
        猜你喜欢
        • 1970-01-01
        • 2012-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-29
        • 1970-01-01
        相关资源
        最近更新 更多