Anroid(仿虎扑体育)ListView中数据按照时间\日期分组(分类)

     最近笔者在做一个项目。需求里面有一个效果是一个ListView:按带日期标题(格式:yyyy-MM-dd)分类,item为(格式:HH:mm:ss),并且在滑动过程中,当日期标题滑动到顶部的时候,进行悬浮;下一个日期标题到达顶部的时候把前一个header顶上去,废话不多少,先上效果图。


     首先是需求想要实现的效果,仿虎扑体育。


       然后是笔者实现的效果(因为项目还未上线,显示内容涉及到公司一些东西,因此显示的内容就马赛克了一下,不好意思):

      接下来说一下,这种效果需要实现的难点吧:

    1.自定义listview,实现sectionItem和contentItem的区分,并将sectionItemj进行滑动监听,在顶部进行悬浮,并进行悬浮在顶部的阴影绘制(为了有悬浮的视觉效果真实感)。(注:该自定义view参照Github上开源项目PinnedSectionListView。在末尾:笔者会贴出带下拉刷新、上拉加载的listview和不带刷新的listview的demo.在这里自定义控件的细节就不做说明了,demo里面有详细的中文注释,有兴趣的童鞋可以看看,相信大家都能看懂。O(∩_∩)O~)

     这里笔者重点分享一下如何把一个arraylist集合里面的所有数据按照某一固定的类型添加分类(分组),最后将所有数据按照分类进行整理,遍历显示。


     1、ArrayList集合里面的数据:

     因为这边从后台接收到的item的json数据日期格式为:yyyy-MM-dd HH:mm:ss;按照(yyyy-MM-dd为header,滑动到顶部要进行悬浮),(HH:mm:ss为正常的item,滑动到顶部不需要悬浮)进行重新分类。


     2、实现思路:

     其实实现也很简单!这里要利用到Map的特性。没错,猜大家已经想到了。key,String,键值对的形式来实现。具体:ArrayList里面的每条数据都含有yyyy-MM-dd HH:mm:ss因此,我们把yyyy-MM-dd设成Map的key,凡是属于这一天的data都放在这个key下面。那么ArrayList所有的data都按照日期yyyy-MM-dd进行了分类。但是Map没办法在listview里面setAdapter呀。到了这一步就好办了,那就把Map(含Key)所有的数据都遍历出来,重新加入到一个ArrayList里面。

    

    3、关键代码:

     首先,是时间转换为yyyy-MM-ddHH:mm:ss的工具类:


/**
	 * 返回 yyyy-MM-dd
	 * 
	 * @param String 参数为String类型yyyy-MM-dd HH:mm:ss
	 * @return 返回 yyyy-MM-dd
	 * @throws ParseException 
	 */
	public static String exchangeStringDate(String date) throws ParseException {
		if (date != null && date.length() > 10) {
			String result = date.substring(0, 10);
			return result;
		}else{
			return null;
		}

	}

	/**
	 * 返回HH:mm:ss
	 * 
	 * @param String 参数为String类型
	 * @return 返回HH:mm:ss
	 * @throws ParseException 
	 */
	public static String exchangeStringTime(String date) throws ParseException {
		if (date != null && date.length() > 10) {
			String result = date.substring(10, date.length());
			return result;
		}else{
			return null;
		}
	}

    第二个是,通过HashMap键值对的特性,将ArrayList的数据进行分组,返回带有分组Header的ArrayList。

        /**
	 * 通过HashMap键值对的特性,将ArrayList的数据进行分组,返回带有分组Header的ArrayList。
	 * @param details 从后台接受到的ArrayList的数据,其中日期格式为:yyyy-MM-dd HH:mm:ss
	 * @return list  返回的list是分类后的包含header(yyyy-MM-dd)和item(HH:mm:ss)的ArrayList
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static ArrayList<PinnedSectionBean> getData(List<WarnDetail> details){
		//最后我们要返回带有分组的list,初始化
		ArrayList<PinnedSectionBean> list = new ArrayList<PinnedSectionBean>();
		//时间转换的util类
		TimeManagement management = new TimeManagement();
		//WarnDetail作为key是yyyy-MM-dd格式,List<WarnDetail>是对应的值是HH:mm:ss格式
		Map<WarnDetail, List<WarnDetail>> map = new HashMap<WarnDetail, List<WarnDetail>>();
		//按照warndetail里面的时间进行分类
		WarnDetail detail = new WarnDetail();
		for (int i = 0; i < details.size(); i++) {
			try {
				String key = management.exchangeStringDate(details.get(i).getAddtime()) ;
				if (detail.getAddtime() != null && !"".equals(detail.getAddtime())) {
					//判断这个Key对象有没有生成,保证是唯一对象.如果第一次没有生成,那么new一个对象,之后同组的其他item都指向这个key
					boolean b = !key.equals(detail.getAddtime().toString());
					if (b) {
						detail = new WarnDetail();
					}
				}
				detail.setAddtime(key);
				//把属于当天yyyy-MM-dd的时间HH:mm:ss全部指向这个key
				List<WarnDetail> warnDetails = map.get(detail);
				//判断这个key对应的值有没有初始化,若第一次进来,这new一个arryalist对象,之后属于这一天的item都加到这个集合里面
				if (warnDetails == null) {
					warnDetails = new ArrayList<WarnDetail>();
				}
				String time = details.get(i).getAddtime();
				time = management.exchangeStringTime(time);
				details.get(i).setAddtime(time);
				warnDetails.add(details.get(i));
				
				map.put(detail, warnDetails);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		//用迭代器遍历map添加到list里面
		Iterator iterator = map.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry entry = (Entry) iterator.next();
			WarnDetail key = (WarnDetail) entry.getKey();
			//我们的key(yyyy-MM-dd)作为标题.类别属于SECTION
			list.add(new PinnedSectionBean(SECTION, key));
			List<WarnDetail> li = (List<WarnDetail>) entry.getValue();
			for (WarnDetail warnDetail : li) {
				//对应的值(HH:mm:ss)作为标题下的item,类别属于ITEM
				list.add(new PinnedSectionBean(ITEM, warnDetail));
			}
		}
		//把分好类的hashmap添加到list里面便于显示
		return list;
	}

         备注:其中WarnDetail是我们的ListView显示item的实体类,大家可以根据自己具体的项目进行替换.其次,分类的类别是灵活多变的,可以按照时间分类,也可以按照地点分类,或者按照WarnDetail里面某一项数据进行分类.只要掌握Map键值对进行分类的思想,即可进行拓展延伸.

      特别提醒:对于item的点击事件:关于setItemOnclickListener中postion的问题,除了arg2-1 = postion以外,记得数据data是分类转换后的real_data哈.否则会有脚标越界的Exception.和点击item跳转错误的bug.

      最后,是笔者做的另外一个效果图,按照地点分类的list.贴上来给大家参考一下.(*^__^*)

       ;;
    

    最后当然是源码,带下拉刷新、上拉加载的listview,按照日期分类.点击下载

     不带刷新的listview,按照日期分类.点击下载

        demo效果图:      

    ;


          友情提示:如果你还想再对list里面的数据进行排序,可以用Comparator进行排序.笔者就不再重复了,网上有很多相关资料介绍,有需求的童鞋可以Google一下.

        第一次发布博客,稍微有点紧张,如有有纰漏,欢迎各位看官指出,大家一起相互学习,有问题的话,欢迎留言,我会一一给大家回复的.



阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭