【问题标题】:Different layout for the items in the listview列表视图中项目的不同布局
【发布时间】:2011-10-20 14:18:50
【问题描述】:

我有一些扩展的光标适配器,我用列表中项目的上下文和资源布局调用 super,类似这样。

在我的适配器中调用 super:

super(activity, viewResource, c, false);

创建我的适配器:

new MyCursorAdapter(this, null, R.layout.my_list_item, null);

我想要实现的目标类似于我用油漆制作的愚蠢模型。 换句话说,我希望项目具有不同类型的布局,例如,我希望所有偶数项目都具有 layout1,而所有奇数项目都具有 layout2。到目前为止,在这种情况下,我只能提供一种布局 R.layout.my_list_item。是否可以动态更改布局? 是否可以构建适配器以具有不同布局的项目?我的目标是动态选择项目的布局。我不想对我想要的所有项目都只有一个布局,例如两个...

谢谢

【问题讨论】:

    标签: android listview cursor adapter


    【解决方案1】:

    是的,不过你将不得不做两件事。首先,覆盖适配器中的getItemViewType() 方法,这样您就可以确保您的bindView() 只获取适合列表中特定位置的视图,如下所示:

    public int getItemViewType(int position){
      if(correspondsToViewType1(position)){
        return VIEW_TYPE_1;
      }
      else(correspondsToViewType2(position)){
        return VIEW_TYPE_2;
      }
      //and so on and so forth.
    }
    

    一旦你这样做了,只需在你的bindView() 中进行一个简单的测试,检查它应该收到什么类型的视图并相应地设置如下:

    public void bindView(View view, Context context, Cursor cursor){
      if(correspondsToViewType1(cursor)){
        //Now we know view is of a particular type and we can do the 
        //setup for it
      }
      else if(correspondsToViewType2(cursor){
        //Now we know view is of a different type and we can do the 
        //setup for it
      }
    }
    

    请注意,您将不得不为 correpondsToViewType 使用不同的方法,一种采用光标,另一种采用 int(用于位置)。这些的实现将根据您想要执行的操作而有所不同。

    请注意,以这种方式执行操作将允许您重用可能被回收的视图。如果您不这样做,您的应用将会受到巨大的性能影响。滚动会非常不稳定。

    【讨论】:

      【解决方案2】:

      我猜您从自定义适配器的名称扩展 SimpleCursorAdapter。您将需要覆盖适配器中的函数getView,并根据列表中的对象膨胀不同的布局并返回该视图。

      前:

           @Override
           public View getView (int position, View convertView, ViewGroup parent)
           {
                  Object myObject = myList.get(position);
      
                  if(convertView == null)
                  {
                        if( something to determine layout )
                              convertView = inflater.inflate(Layout File);
                        else
                              convertView = inflater.inflate(Some Other Layout File);
                  }
      
                  //Set up the view here, such as setting textview text and such
      
                  return convertView;
           }
      

      这只是一个示例,有点 sudo 代码,因此需要根据您的具体情况进行一些调整。

      【讨论】:

      • 这行不通。他正在扩展已经覆盖了 getView 方法的 CursorAdapter。你不想弄乱这个方法,因为它做了一些特殊的事情,包括获取适当的光标。再加上他得到的回收的 convertView 可能不是正确的类型,因此他将永远无法使用它,他的应用程序将受到巨大的性能影响。
      【解决方案3】:

      只需覆盖 newView 方法:

      public class MyCursorAdapter extends CursorAdapter {
      
      private final LayoutInflater inflater;
          private ContentType type;
      
      public MyCursorAdapter (Context context, Cursor c) {
          super(context, c);
          inflater = LayoutInflater.from(context);
      }
      
      @Override
      public void bindView(View view, Context context, Cursor cursor) {
          if( cursor.getString(cursor.getColumnIndex("type")).equals("type1") ) {
                      // get elements for type1
          } else {
                      // get elements for type1
                  }
      
      }
      
      @Override
      public View newView(Context context, Cursor cursor, ViewGroup parent) {
      
          if( cursor.getString(cursor.getColumnIndex("type")).equals("type1") ) {
              final View view = inflater.inflate(R.layout.item_type1, parent, false);
          } else {
              final View view = inflater.inflate(R.layout.item_type2, parent, false);
          }
          return view;
      }
      

      【讨论】:

      • @Kurtis Nusbaum 的方法看起来更扎实。我建议使用他的。
      • 这不好,因为它不允许他使用在 bindView 中传递的 View 参数,该参数可能已被回收。他每次都必须创建一个新视图,因此他的应用程序的性能会受到巨大影响。
      • 对不起,马克,在我添加我的之后你的评论。谢谢你。我将在那里留下我的评论作为解释。
      • 谢谢,我总是很高兴学习;)这只是我在看到您的代码之前的第一个想法。
      猜你喜欢
      • 1970-01-01
      • 2013-09-22
      • 1970-01-01
      • 1970-01-01
      • 2015-03-08
      • 1970-01-01
      • 2013-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多