开发有标题的ListView

第一步:  老生常谈, 首先定义相关的布局文件, 和普通的ListView一样, 不再赘述;
第二步:  定义一个实体类, 用该实体类来存储一个标题以及该标题下的所有Item的数据,具体示例代码如下;

public class MealCategoryEntity {
          private String mCategoryName;

           // Item列表, 不含标题
          private List<ShakedListItemEntity> mCategoryItem = new ArrayList<ShakedListItemEntity>();

          public MealCategoryEntity(String mCategroyName) {
              // 设置标题
              mCategoryName = mCategroyName;
          }
 
          public String getmCategoryName() {
               return mCategoryName;
          }

          public void addItem(ShakedListItemEntity pItemName) {
              mCategoryItem.add(pItemName);
          }


         /**
           *  获取Item内容 
           * @param pPosition
           * @return
           */
         public Object getItem(int pPosition) {
             // 标题排在第一位
             if (pPosition == 0) {
                 return mCategoryName;
             }  else  {
                 return mCategoryItem.get(pPosition - 1);
             }
         }
 
        /**
          * 当前类别Item总数。标题也需要占用一个Item
          * @return
          */
        public int getItemCount() {
            return mCategoryItem.size() + 1;
        }

}


/** 这是ShakedListItemEntity类的定义 **/
public class ShakedListItemEntity  {
            private String vegetable_name;
            private int vegetable_num;
            private double vegetable_cost;
 
            public String getVegetable_name() {
                return vegetable_name;
            }

            public void setVegetable_name(String vegetable_name) {
                this.vegetable_name = vegetable_name;
            }

            public int getVegetable_num() {
                return vegetable_num;
            }

            public void setVegetable_num(int vegetable_num) {
                this.vegetable_num = vegetable_num;
            }

            public double getVegetable_cost() {
                return vegetable_cost;
            }

            public void setVegetable_cost(float vegetable_cost) {
                this.vegetable_cost = vegetable_cost;
            }
}

 

第三步:  实例化上述定义的实体类,根据自己的需要可以实例化一个或多个,并将它们添加到List集合当中;

第四步:  定义自己Adapter并集成BaseAdapter, 重写其中的方法。这是最关键的一步,也是难度最大的一步, 具体示例代码及其注释(不要着急,请细细看其中的注释)如下:

public class MealCategoryAdapter extends BaseAdapter {
 // 标题类型
 private static final int TYPE_CATEGORY_ITEM = 0;
 // 子项类型
 private static final int TYPE_ITEM = 1;
 // 类别集合
 private List<MealCategoryEntity> mListData;
 // 布局填充器
 private LayoutInflater mInflater;

 public MealCategoryAdapter(Context context, List<MealCategoryEntity> pData) {
  mListData = pData;
  mInflater = LayoutInflater.from(context);
 }

 /**
  * 获取所有分类的Item的总数
  */
 @Override
 public int getCount() {
  int count = 0;

  if (null != mListData) {
   // 所有分类中item的总和是ListVIew Item的总个数
   for (MealCategoryEntity category : mListData) {
    count += category.getItemCount();
   }
  }
  return count;
 }

 /**
  * 获取Item
  */
 @Override
 public Object getItem(int position) {

  // 异常情况处理
  if (null == mListData || position < 0 || position > getCount()) {
   return null;
  }

  // 同一分类内,第一个元素的索引值
  int categroyFirstIndex = 0;

  for (MealCategoryEntity category : mListData) {
   int size = category.getItemCount();
   // 在当前分类中的索引值
   int categoryIndex = position - categroyFirstIndex;
   // item在当前分类内
   if (categoryIndex < size) {
    return category.getItem(categoryIndex);
   }

   // 索引移动到当前分类结尾,即下一个分类第一个元素索引
   categroyFirstIndex += size;
  }
  return null;
 }

 /**
  * 获取Item的类别,也即确定是子项还是标题项
  */
 @Override
 public int getItemViewType(int position) {
  // 异常情况处理
  if (null == mListData || position < 0 || position > getCount()) {
   return TYPE_ITEM;
  }

  // 初始遍历位置
  int categroyFirstIndex = 0;
  // 遍历实体类集合
  for (MealCategoryEntity category : mListData) {
   int size = category.getItemCount();
   // 在当前分类中的索引值
   int categoryIndex = position - categroyFirstIndex;
   // 如果是首项返回标题类型
   if (categoryIndex == 0) {
    return TYPE_CATEGORY_ITEM;
   }

   //如果是子项返回子项类型
   if (categoryIndex > 0
     && categoryIndex < category.getItemCount() - 1) {
    return TYPE_ITEM;
   }
   categroyFirstIndex += size;
  }
  return TYPE_ITEM;
 }


//返回标题的数目, 该方法不能删除,标题数目根据自己程序的需要返回不同的值,这里我的例子中只有两个标题

@Override
 public int getViewTypeCount() {
  return 2;
 }


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

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {

  //获取指定位置的Item的类型
  int itemViewType = getItemViewType(position);
  switch (itemViewType) {
  //如果是标题类型, 则填充标题布局
  case TYPE_CATEGORY_ITEM:
   if (null == convertView) {
    convertView = mInflater.inflate(
      R.layout.category_listview_item_header, null);
   }

   TextView textView = (TextView) convertView
     .findViewById(R.id.header);
   textView.setTypeface(MyApplication.getInstance().getTypeface());
   String itemValue = (String) getItem(position);
   textView.setText(itemValue);
   break;

     //如果是子项类型则填充子项的布局
  case TYPE_ITEM:
   ViewHolder viewHolder = null;
   if (null == convertView) {
    convertView = mInflater.inflate(
      R.layout.category_listview_item, null);
    viewHolder = new ViewHolder();
    viewHolder.vegeName = (TextView) convertView
      .findViewById(R.id.vegeName_id);
    viewHolder.vegeName.setTypeface(MyApplication.getInstance()
      .getTypeface());
    viewHolder.orderNum = (TextView) convertView
      .findViewById(R.id.orderNum_id);
    viewHolder.vegeCost = (TextView) convertView
      .findViewById(R.id.mealCost_id);
    viewHolder.arrow_right = (ImageView) convertView
      .findViewById(R.id.arrow_id);
    convertView.setTag(viewHolder);
   } else {
    viewHolder = (ViewHolder) convertView.getTag();
   }

   // 绑定数据
   viewHolder.vegeName
     .setText(((ShakedListItemEntity) getItem(position))
       .getVegetable_name());
   viewHolder.vegeName.setTypeface(MyApplication.getInstance()
     .getTypeface());
   viewHolder.orderNum.setText("x "
     + String.valueOf(((ShakedListItemEntity) getItem(position))
       .getVegetable_num()));
   viewHolder.vegeCost.setText("¥"
     + String.valueOf(((ShakedListItemEntity) getItem(position))
       .getVegetable_cost()));
   break;
  }
  return convertView;
 }

 @Override
 public boolean areAllItemsEnabled() {
  return false;
 }

 @Override
 public boolean isEnabled(int position) {
  return getItemViewType(position) != TYPE_CATEGORY_ITEM;
 }

 private class ViewHolder {
  TextView vegeName;
  TextView orderNum;
  TextView vegeCost;
  ImageView arrow_right;
 }

}

 

第五步:  根据具体的业务数据遍历第三步中定义的List集合并为其存储的实体类实例填充相应的数据;

第六步:  在程序当中根剧当前上下文及List集合实例化我们自己写的Adapter并将Adapter绑定到指定的ListView控件上;
第七步:  到此开发带标题的ListView算是告一段落, 接下来大家可以试着按以上流程走一遍了,若有任何不明白的地方可以给我留言,我会尽力帮助大家。

最后附几张效果图供大家参考:

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值