【问题标题】:Different row layouts in ListViewListView 中的不同行布局
【发布时间】:2012-03-28 16:15:18
【问题描述】:

这篇文章与这个ViewHolder not working有关。在那篇文章中,我正在关注如何在ListView 上使用ViewHolder 的教程。我现在想要的是让ListView 上的最后一项具有与其他项不同的布局。这是我的代码:

int lastpos = mList.size()-1;
          System.out.println("position: "+position+" mlist: "+lastpos);

          if(position==lastpos){
           view = vi.inflate(R.layout.list_item_record, null);
           holder.textView = (TextView)view.findViewById(R.id.record_view);
          }else{
           view = vi.inflate(R.layout.list_item_bn, null);
           holder.textView = (TextView)view.findViewById(R.id.tv_name);
          }
          view.setTag(holder);

我只是得到ListView 的大小减去1 并有一个条件来检查当前位置是否等于最后一项。但是,此代码将最后一项的布局设置为与其余项相同。 getView方法完整代码:

private class CustomListAdapter extends ArrayAdapter { 
    private ArrayList mList;
    private Context mContext;

    public CustomListAdapter(Context context, int textViewResourceId,
            ArrayList list) {
        super(context, textViewResourceId, list);
        this.mList = list;
        this.mContext = context;
    }   

    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;

        final ToggleButton tb;

         if (view == null) {
          ViewHolder holder = new ViewHolder();
          LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

          int lastpos = mList.size()-1;
          System.out.println("position: "+position+" mlist: "+lastpos);

          if(position==lastpos){
           view = vi.inflate(R.layout.list_item_record, null);
           holder.textView = (TextView)view.findViewById(R.id.record_view);
          }else{
           view = vi.inflate(R.layout.list_item_bn, null);
           holder.textView = (TextView)view.findViewById(R.id.tv_name);
          }
          view.setTag(holder);
         }

         final ItemsDisplay listItem = (ItemsDisplay) mList.get(position);
            if (listItem != null) {
             ViewHolder holder1 = (ViewHolder)view.getTag();
             holder1.textView.setText(listItem.getTag());

             view.setOnClickListener(new OnClickListener() {
                    public void onClick(View arg0) { //--clickOnListItem
                     Toast.makeText(getBaseContext(),
                       "Button is "+position+" "+listItem.getTag(),
                       Toast.LENGTH_LONG).show();
                    }
                });

                tb  = (ToggleButton) view.findViewById(R.id.toggleButton);
                tb.setOnClickListener(new View.OnClickListener() {
              public void onClick(View v) {

               if(tb.isChecked()){
                Toast.makeText(getBaseContext(),
                           "Button is "+position+" checked:"+tb.isChecked()+" "+listItem.getTag(),
                           Toast.LENGTH_LONG).show();
               }else{
                Toast.makeText(getBaseContext(),
                  "Button is "+position+" checked:"+tb.isChecked()+" "+listItem.getTag(),
                           Toast.LENGTH_LONG).show();
               }
              }
                });
            }



        return view;  
    }

}

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 粘贴您的完整适配器代码...
  • if 循环调用 check like if(...){Syso("in if loop")}
  • 请在打印的任何位置检查`System.out.println("position: "+position+" mlist: "+lastpos);`。

标签: android android-layout android-listview android-adapter


【解决方案1】:

为您的适配器实现getItemViewType()getViewTypeCount()

@Override
public int getViewTypeCount() {
   return 2; //return 2, you have two types that the getView() method will return, normal(0) and for the last row(1)
}

和:

@Override
public int getItemViewType(int position) {
    return (position == this.getCount() - 1) ? 1 : 0; //if we are at the last position then return 1, for any other position return 0
}

然后在getView() 方法中找出要膨胀的视图类型:

public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;
        int theType = getItemViewType(position); 
        if (view == null) {
          ViewHolder holder = new ViewHolder();
          LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          if (theType == 0) {
              // inflate the ordinary row
              view = vi.inflate(R.layout.list_item_bn, null);
              holder.textView = (TextView)view.findViewById(R.id.tv_name);      
          } else if (theType == 1){
             // inflate the row for the last position
              view = vi.inflate(R.layout.list_item_record, null);
              holder.textView = (TextView)view.findViewById(R.id.record_view);
          } 
          view.setTag(holder);
         }
 //other stuff here, keep in mind that you have a different layout for your last position so double check what are trying to initialize
}

来自 cmets 的示例:http://pastebin.com/gn65240B(或 https://gist.github.com/2641914

【讨论】:

  • 我试过了,但还是不行。我试图打印位置和类型的值。 position 仅在 theType=0 时给了我 0-5。这是为什么? mList 由 26 个项目组成。我只是想知道为什么职位有 6 个值只与我列表中的 26 个项目相反。
  • @user1263567 您是否向下滚动了列表?我觉得只得到5-6的位置是正常的,可能是因为这些是屏幕上可以看到的位置,对于还没有看到的位置调用getView方法会很浪费。如果您滚动列表,您还应该看到其他位置。
  • 我明白了。但是,最后一行仍然与其余行相同。我试图将最后一行转移到第一行,看看它是否有效。它有效,但每第 7 行与第一行相同。只有第一个应该是唯一一个与其他布局不同的。
  • @user1263567 你在getView 方法中做错了,行被回收。我在这里做了一个简单的例子(pastebin.com/gn65240B)所以你可以看到一个工作的例子。
  • 我试图解决这个问题,但不知何故我无法遵循它,尤其是当我的布局不只处理 textview 时。我在您的示例中注意到它是 Listactivity。有关系吗?我将它实现为仅作为活动,活动的组件是列表视图。
【解决方案2】:

问题在于,一旦您膨胀了视图,它就可以在任何位置多次重复使用。我建议采用以下方法:您像往常一样膨胀除最后一项之外的所有项目(包括视图持有者),但对于最后一项,您将引用作为 CustomListAdapter 的字段并在每次请求最后一项时返回它:

private class CustomListAdapter extends ArrayAdapter { 
    ...
    private View mLastItem; 

    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;
        ...
        int lastpos = mList.size()-1;

        if (view == null) {
            ViewHolder holder = new ViewHolder();
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            if (position == lastpos) {
                view = vi.inflate(R.layout.list_item_record, null);
                holder.textView = (TextView)view.findViewById(R.id.record_view);
                mLastItem = view;
            }
            else {
                view = vi.inflate(R.layout.list_item_bn, null);
                holder.textView = (TextView)view.findViewById(R.id.tv_name);
            }
            view.setTag(holder);
        }

        if (position == lastpos) {
            ... // Update the last item here
            return mLastItem; 
        }
        ...
    }

}

【讨论】:

  • 这也不起作用。它将最后一项设置为与其余项相同。不过谢谢。
猜你喜欢
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-12
  • 2011-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多