From a0d9c84e9a2a35a4389aedd898839a627248a00a Mon Sep 17 00:00:00 2001 From: huanghaibin Date: Tue, 5 Dec 2017 10:14:08 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E5=81=9Ademo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendarviewproject/ArticleAdapter.java | 162 +++++----- .../base/adapter/BaseRecyclerAdapter.java | 22 +- .../colorful/ColorfulActivity.java | 16 +- .../group/GroupItemDecoration.java | 277 ++++++++++++++++++ .../group/GroupRecyclerAdapter.java | 135 +++++++++ .../group/GroupRecyclerView.java | 88 ++++++ .../index/IndexActivity.java | 16 +- .../meizu/MeiZuActivity.java | 17 +- .../simple/SimpleActivity.java | 11 +- app/src/main/res/layout/activity_colorful.xml | 188 +----------- app/src/main/res/layout/activity_index.xml | 188 +----------- app/src/main/res/layout/activity_meizu.xml | 187 +----------- app/src/main/res/layout/activity_simple.xml | 10 +- app/src/main/res/values/attrs.xml | 14 + 14 files changed, 695 insertions(+), 636 deletions(-) create mode 100644 app/src/main/java/com/haibin/calendarviewproject/group/GroupItemDecoration.java create mode 100644 app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerAdapter.java create mode 100644 app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerView.java create mode 100644 app/src/main/res/values/attrs.xml diff --git a/app/src/main/java/com/haibin/calendarviewproject/ArticleAdapter.java b/app/src/main/java/com/haibin/calendarviewproject/ArticleAdapter.java index cf8b0d68..51bd6435 100644 --- a/app/src/main/java/com/haibin/calendarviewproject/ArticleAdapter.java +++ b/app/src/main/java/com/haibin/calendarviewproject/ArticleAdapter.java @@ -9,9 +9,10 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.RequestManager; -import com.haibin.calendarviewproject.base.adapter.BaseRecyclerAdapter; +import com.haibin.calendarviewproject.group.GroupRecyclerAdapter; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; /** @@ -19,54 +20,40 @@ * Created by huanghaibin on 2017/12/4. */ -public class ArticleAdapter extends BaseRecyclerAdapter
{ +public class ArticleAdapter extends GroupRecyclerAdapter { + - private static final int TYPE_ARTICLE_GROUP = 1; - private static final int TYPE_ARTICLE = 2; private RequestManager mLoader; public ArticleAdapter(Context context) { super(context); mLoader = Glide.with(context.getApplicationContext()); - mItems.addAll(create()); - mItems.addAll(create()); + LinkedHashMap> map = new LinkedHashMap<>(); + List titles = new ArrayList<>(); + map.put("今日推荐", create(0)); + map.put("每周热点", create(1)); + map.put("最高评论", create(2)); + titles.add("今日推荐"); + titles.add("每周热点"); + titles.add("最高评论"); + resetGroups(map,titles); } - @Override - public int getItemViewType(int position) { - Article article = mItems.get(position); - if (article.getType() == TYPE_ARTICLE) - return TYPE_ARTICLE; - else - return TYPE_ARTICLE_GROUP; - } @Override protected RecyclerView.ViewHolder onCreateDefaultViewHolder(ViewGroup parent, int type) { - if (type == TYPE_ARTICLE) - return new ArticleViewHolder(mInflater.inflate(R.layout.item_list_article, parent, false)); - else - return new GroupViewHolder(mInflater.inflate(R.layout.item_list_article_group, parent, false)); + return new ArticleViewHolder(mInflater.inflate(R.layout.item_list_article, parent, false)); } @Override protected void onBindViewHolder(RecyclerView.ViewHolder holder, Article item, int position) { - int type = getItemViewType(position); - switch (type) { - case TYPE_ARTICLE_GROUP: - GroupViewHolder groupHolder = (GroupViewHolder) holder; - groupHolder.mTextGroup.setText(item.getTitle()); - break; - case TYPE_ARTICLE: - ArticleViewHolder h = (ArticleViewHolder) holder; - h.mTextTitle.setText(item.getTitle()); - h.mTextContent.setText(item.getContent()); - mLoader.load(item.getImgUrl()) - .asBitmap() - .centerCrop() - .into(h.mImageView); - break; - } + ArticleViewHolder h = (ArticleViewHolder) holder; + h.mTextTitle.setText(item.getTitle()); + h.mTextContent.setText(item.getContent()); + mLoader.load(item.getImgUrl()) + .asBitmap() + .centerCrop() + .into(h.mImageView); } private static class ArticleViewHolder extends RecyclerView.ViewHolder { @@ -82,67 +69,72 @@ private ArticleViewHolder(View itemView) { } } - private static class GroupViewHolder extends RecyclerView.ViewHolder { - private TextView mTextGroup; - - private GroupViewHolder(View itemView) { - super(itemView); - mTextGroup = (TextView) itemView.findViewById(R.id.tv_group); - } - } private static Article create(String title, String content, String imgUrl) { Article article = new Article(); article.setTitle(title); article.setContent(content); article.setImgUrl(imgUrl); - article.setType(TYPE_ARTICLE); return article; } - private static Article create(String title, int type) { - Article article = new Article(); - article.setTitle(title); - article.setType(type); - return article; - } - - private static List
create() { + private static List
create(int p) { List
list = new ArrayList<>(); - list.add(create("今日推荐",TYPE_ARTICLE_GROUP)); - list.add(create("新西兰克马德克群岛发生5.7级地震 震源深度10千米", - "#地震快讯#中国地震台网正式测定:12月04日08时08分在克马德克群岛(南纬32.82度,西经178.73度)发生5.7级地震,震源深度10千米。", - "http://cms-bucket.nosdn.127.net/catchpic/2/27/27e2ce7fd02e6c096e21b1689a8a3fe9.jpg?imageView&thumbnail=550x0")); - list.add(create("俄罗斯喊冤不当\"背锅侠\" 俄美陷入\"后真相\"旋涡", - "“差到令人震惊”,但不怪特朗普。俄罗斯总理德米特里·梅德韦杰夫近日在谈到俄美关系时这样说。俄罗斯近来连遭美国“恶毒”指责和西方国家连环出击。一些国际舆论认为,俄罗斯成了“背锅侠”,俄罗斯自己也公开喊冤斥责美国。在俄美你来我往的互掐中,真相似乎变得已不那么重要了。", - "http://cms-bucket.nosdn.127.net/catchpic/c/c8/c8b0685089258b82f3ca1997def78d8d.png?imageView&thumbnail=550x0")); - list.add(create("中企投资巴西获支持 英媒:巴西人感激\"保住饭碗\"", - "参考消息网12月4日报道 英媒称,里约热内卢附近的阿苏港曾被埃克·巴蒂斯塔称为“通往中国的公路”,10多年前,这位现已名誉扫地的巴西前首富创建了这个超级港,大宗商品热潮结束后,他在巴西的商业帝国几乎无一幸存并于2014年破产,但此后至今有一个项目仍蓬勃发展,那就是阿苏港。", - "http://cms-bucket.nosdn.127.net/catchpic/8/8b/8ba2d19b7f63efc5cf714960d5edd2c3.jpg?imageView&thumbnail=550x0")); - list.add(create("本周最热",TYPE_ARTICLE_GROUP)); - list.add(create("美电视台记者因误报有关弗林新闻被停职四周", - "【环球网报道】据俄罗斯卫星网12月3日报道,美国ABC电视台记者布莱恩·罗素因在有关美国总统前国家安全顾问迈克尔·弗林的新闻报道中的失误,临时被停职。", - "http://cms-bucket.nosdn.127.net/5d18566fde70407b9cc3a728822115c320171203133214.jpeg?imageView&thumbnail=550x0")); - list.add(create("预计明年3月上市 曝全新奥迪Q5L无伪谍照", - "随着之前全新一代国产奥迪Q5L在工信部目录亮相,最近曝光的测试车也都基本褪去了伪装,不过正式上市还是要等到2018年3月份。从最新曝光的内饰来看,轴距的加长令后排的空间有着非常明显的提升。", - "http://cms-bucket.nosdn.127.net/eda9ca222352470190c4f0d6b9a8c29420171201160854.jpeg?imageView&thumbnail=550x0")); - list.add(create( - "2019年投产 电咖整车生产基地落户浙江绍兴", - "网易汽车11月30日报道 两周前的广州车展上,电咖发布了其首款电动汽车EV10,官方指导价为13.38万-14.18万,扣除补贴后的零售价为5.98万元-6.78万元,性价比很高。抛开车辆本身,引起业界关注的是这家新势力造车企业的几位核心成员,当年上汽大众团队的三位老兵--张海亮、向东平、牛胜福携手用了957天造了一辆可以上市的车。", - "http://cms-bucket.nosdn.127.net/674c392123254bb69bdd9227442965eb20171129203658.jpeg?imageView&thumbnail=550x0")); - list.add(create("最高评论",TYPE_ARTICLE_GROUP)); - list.add(create( - "2017年进入尾声,苹果大笔押注的ARkit还好么?", - "谷歌推出了AR眼镜、ARCore平台和应用在手机上的Project Tango,Facebook也上线了AR开发平台和工具。至于苹果,更是把AR当做发展的重中之重。在新品iPhone8和iPhoneX中,后置摄像头专为AR进行校准,前置摄像头还添加了可以带来更好AR效果的深度传感器。", - "http://cms-bucket.nosdn.127.net/catchpic/7/76/76135ac5d3107a1d5ba11a8ee2fc7e27.jpg?imageView&thumbnail=550x0")); - list.add(create( - "亚马逊CTO:我们要让人类成为机器人的中心!", - "那些相信应用下载会让世界变得更美好的智能手机布道者和应用爱好者们,会在AWS re:Invent大会上感到不自在。亚马逊网络服务首席技术官Werner Vogels表示,所有这些都未能实现信息的民主化。", - "http://cms-bucket.nosdn.127.net/ddb758f16a7d4aa3aa422ec385fc3e5020171204081818.jpeg?imageView&thumbnail=550x0")); - list.add(create( - "有特斯拉车主想用免费的充电桩挖矿,但这可能行不通", - "在社交网络 Facebook 上的一个特斯拉车主群组中,有人开脑洞说可以尝试自己组装矿机放在特斯拉后备箱中,接入车载电池的电源,然后将车停到超级充电桩附近,就能用免费获得的电力挖矿了。", - "http://crawl.nosdn.127.net/nbotreplaceimg/4ce9c743e6c02f6777d22278e2ef8bc3/2b33e32532db204fe207693c82719660.jpg")); + if (p == 0) { + list.add(create("新西兰克马德克群岛发生5.7级地震 震源深度10千米", + "#地震快讯#中国地震台网正式测定:12月04日08时08分在克马德克群岛(南纬32.82度,西经178.73度)发生5.7级地震,震源深度10千米。", + "http://cms-bucket.nosdn.127.net/catchpic/2/27/27e2ce7fd02e6c096e21b1689a8a3fe9.jpg?imageView&thumbnail=550x0")); + list.add(create("俄罗斯喊冤不当\"背锅侠\" 俄美陷入\"后真相\"旋涡", + "“差到令人震惊”,但不怪特朗普。俄罗斯总理德米特里·梅德韦杰夫近日在谈到俄美关系时这样说。俄罗斯近来连遭美国“恶毒”指责和西方国家连环出击。一些国际舆论认为,俄罗斯成了“背锅侠”,俄罗斯自己也公开喊冤斥责美国。在俄美你来我往的互掐中,真相似乎变得已不那么重要了。", + "http://cms-bucket.nosdn.127.net/catchpic/c/c8/c8b0685089258b82f3ca1997def78d8d.png?imageView&thumbnail=550x0")); + list.add(create("中企投资巴西获支持 英媒:巴西人感激\"保住饭碗\"", + "参考消息网12月4日报道 英媒称,里约热内卢附近的阿苏港曾被埃克·巴蒂斯塔称为“通往中国的公路”,10多年前,这位现已名誉扫地的巴西前首富创建了这个超级港,大宗商品热潮结束后,他在巴西的商业帝国几乎无一幸存并于2014年破产,但此后至今有一个项目仍蓬勃发展,那就是阿苏港。", + "http://cms-bucket.nosdn.127.net/catchpic/8/8b/8ba2d19b7f63efc5cf714960d5edd2c3.jpg?imageView&thumbnail=550x0")); + list.add(create("美电视台记者因误报有关弗林新闻被停职四周", + "【环球网报道】据俄罗斯卫星网12月3日报道,美国ABC电视台记者布莱恩·罗素因在有关美国总统前国家安全顾问迈克尔·弗林的新闻报道中的失误,临时被停职。", + "http://cms-bucket.nosdn.127.net/5d18566fde70407b9cc3a728822115c320171203133214.jpeg?imageView&thumbnail=550x0")); + list.add(create("预计明年3月上市 曝全新奥迪Q5L无伪谍照", + "随着之前全新一代国产奥迪Q5L在工信部目录亮相,最近曝光的测试车也都基本褪去了伪装,不过正式上市还是要等到2018年3月份。从最新曝光的内饰来看,轴距的加长令后排的空间有着非常明显的提升。", + "http://cms-bucket.nosdn.127.net/eda9ca222352470190c4f0d6b9a8c29420171201160854.jpeg?imageView&thumbnail=550x0")); + } else if (p == 1) { + list.add(create( + "2019年投产 电咖整车生产基地落户浙江绍兴", + "网易汽车11月30日报道 两周前的广州车展上,电咖发布了其首款电动汽车EV10,官方指导价为13.38万-14.18万,扣除补贴后的零售价为5.98万元-6.78万元,性价比很高。抛开车辆本身,引起业界关注的是这家新势力造车企业的几位核心成员,当年上汽大众团队的三位老兵--张海亮、向东平、牛胜福携手用了957天造了一辆可以上市的车。", + "http://cms-bucket.nosdn.127.net/674c392123254bb69bdd9227442965eb20171129203658.jpeg?imageView&thumbnail=550x0")); + list.add(create( + "2017年进入尾声,苹果大笔押注的ARkit还好么?", + "谷歌推出了AR眼镜、ARCore平台和应用在手机上的Project Tango,Facebook也上线了AR开发平台和工具。至于苹果,更是把AR当做发展的重中之重。在新品iPhone8和iPhoneX中,后置摄像头专为AR进行校准,前置摄像头还添加了可以带来更好AR效果的深度传感器。", + "http://cms-bucket.nosdn.127.net/catchpic/7/76/76135ac5d3107a1d5ba11a8ee2fc7e27.jpg?imageView&thumbnail=550x0")); + list.add(create( + "亚马逊CTO:我们要让人类成为机器人的中心!", + "那些相信应用下载会让世界变得更美好的智能手机布道者和应用爱好者们,会在AWS re:Invent大会上感到不自在。亚马逊网络服务首席技术官Werner Vogels表示,所有这些都未能实现信息的民主化。", + "http://cms-bucket.nosdn.127.net/ddb758f16a7d4aa3aa422ec385fc3e5020171204081818.jpeg?imageView&thumbnail=550x0")); + list.add(create( + "有特斯拉车主想用免费的充电桩挖矿,但这可能行不通", + "在社交网络 Facebook 上的一个特斯拉车主群组中,有人开脑洞说可以尝试自己组装矿机放在特斯拉后备箱中,接入车载电池的电源,然后将车停到超级充电桩附近,就能用免费获得的电力挖矿了。", + "http://crawl.nosdn.127.net/nbotreplaceimg/4ce9c743e6c02f6777d22278e2ef8bc3/2b33e32532db204fe207693c82719660.jpg")); + } else if (p == 2) { + list.add(create( + "2017年进入尾声,苹果大笔押注的ARkit还好么?", + "谷歌推出了AR眼镜、ARCore平台和应用在手机上的Project Tango,Facebook也上线了AR开发平台和工具。至于苹果,更是把AR当做发展的重中之重。在新品iPhone8和iPhoneX中,后置摄像头专为AR进行校准,前置摄像头还添加了可以带来更好AR效果的深度传感器。", + "http://cms-bucket.nosdn.127.net/catchpic/7/76/76135ac5d3107a1d5ba11a8ee2fc7e27.jpg?imageView&thumbnail=550x0")); + list.add(create( + "亚马逊CTO:我们要让人类成为机器人的中心!", + "那些相信应用下载会让世界变得更美好的智能手机布道者和应用爱好者们,会在AWS re:Invent大会上感到不自在。亚马逊网络服务首席技术官Werner Vogels表示,所有这些都未能实现信息的民主化。", + "http://cms-bucket.nosdn.127.net/ddb758f16a7d4aa3aa422ec385fc3e5020171204081818.jpeg?imageView&thumbnail=550x0")); + list.add(create("中企投资巴西获支持 英媒:巴西人感激\"保住饭碗\"", + "参考消息网12月4日报道 英媒称,里约热内卢附近的阿苏港曾被埃克·巴蒂斯塔称为“通往中国的公路”,10多年前,这位现已名誉扫地的巴西前首富创建了这个超级港,大宗商品热潮结束后,他在巴西的商业帝国几乎无一幸存并于2014年破产,但此后至今有一个项目仍蓬勃发展,那就是阿苏港。", + "http://cms-bucket.nosdn.127.net/catchpic/8/8b/8ba2d19b7f63efc5cf714960d5edd2c3.jpg?imageView&thumbnail=550x0")); + list.add(create("美电视台记者因误报有关弗林新闻被停职四周", + "【环球网报道】据俄罗斯卫星网12月3日报道,美国ABC电视台记者布莱恩·罗素因在有关美国总统前国家安全顾问迈克尔·弗林的新闻报道中的失误,临时被停职。", + "http://cms-bucket.nosdn.127.net/5d18566fde70407b9cc3a728822115c320171203133214.jpeg?imageView&thumbnail=550x0")); + list.add(create( + "2019年投产 电咖整车生产基地落户浙江绍兴", + "网易汽车11月30日报道 两周前的广州车展上,电咖发布了其首款电动汽车EV10,官方指导价为13.38万-14.18万,扣除补贴后的零售价为5.98万元-6.78万元,性价比很高。抛开车辆本身,引起业界关注的是这家新势力造车企业的几位核心成员,当年上汽大众团队的三位老兵--张海亮、向东平、牛胜福携手用了957天造了一辆可以上市的车。", + "http://cms-bucket.nosdn.127.net/674c392123254bb69bdd9227442965eb20171129203658.jpeg?imageView&thumbnail=550x0")); + } + + return list; } } diff --git a/app/src/main/java/com/haibin/calendarviewproject/base/adapter/BaseRecyclerAdapter.java b/app/src/main/java/com/haibin/calendarviewproject/base/adapter/BaseRecyclerAdapter.java index 5b04fe40..1b759412 100644 --- a/app/src/main/java/com/haibin/calendarviewproject/base/adapter/BaseRecyclerAdapter.java +++ b/app/src/main/java/com/haibin/calendarviewproject/base/adapter/BaseRecyclerAdapter.java @@ -35,7 +35,7 @@ public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter { private OnItemClickListener onItemClickListener; private OnClickListener onClickListener; - public BaseRecyclerAdapter(Context context) { + public BaseRecyclerAdapter(Context context) { this.mItems = new ArrayList<>(); mInflater = LayoutInflater.from(context); onClickListener = new OnClickListener() { @@ -115,4 +115,24 @@ public void onClick(View v) { interface OnItemClickListener { void onItemClick(int position, long itemId); } + + public final void removeItem(T item) { + if (this.mItems.contains(item)) { + int position = mItems.indexOf(item); + this.mItems.remove(item); + notifyItemRemoved(position); + } + } + + protected final void removeItem(int position) { + if (this.getItemCount() > position) { + this.mItems.remove(position); + notifyItemRemoved(position); + } + } + + protected final void clear(){ + mItems.clear(); + notifyDataSetChanged(); + } } diff --git a/app/src/main/java/com/haibin/calendarviewproject/colorful/ColorfulActivity.java b/app/src/main/java/com/haibin/calendarviewproject/colorful/ColorfulActivity.java index ce106858..7f071634 100644 --- a/app/src/main/java/com/haibin/calendarviewproject/colorful/ColorfulActivity.java +++ b/app/src/main/java/com/haibin/calendarviewproject/colorful/ColorfulActivity.java @@ -3,14 +3,19 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; import com.haibin.calendarview.Calendar; import com.haibin.calendarview.CalendarView; +import com.haibin.calendarviewproject.Article; +import com.haibin.calendarviewproject.ArticleAdapter; import com.haibin.calendarviewproject.R; import com.haibin.calendarviewproject.base.activity.BaseActivity; +import com.haibin.calendarviewproject.group.GroupItemDecoration; +import com.haibin.calendarviewproject.group.GroupRecyclerView; import com.haibin.calendarviewproject.index.IndexActivity; import com.haibin.calendarviewproject.meizu.MeiZuActivity; import com.haibin.calendarviewproject.simple.SimpleActivity; @@ -36,6 +41,8 @@ public class ColorfulActivity extends BaseActivity implements RelativeLayout mRelativeTool; private int mYear; + GroupRecyclerView mRecyclerView; + public static void show(Context context) { context.startActivity(new Intent(context, ColorfulActivity.class)); } @@ -97,10 +104,11 @@ protected void initData() { schemes.add(getSchemeCalendar(year, month, 25, 0xFF13acf0,"假")); mCalendarView.setSchemeDate(schemes); - findViewById(R.id.ll_flyme).setOnClickListener(this); - findViewById(R.id.ll_simple).setOnClickListener(this); - findViewById(R.id.ll_colorful).setOnClickListener(this); - findViewById(R.id.ll_index).setOnClickListener(this); + mRecyclerView = (GroupRecyclerView) findViewById(R.id.recyclerView); + mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + mRecyclerView.addItemDecoration(new GroupItemDecoration()); + mRecyclerView.setAdapter(new ArticleAdapter(this)); + mRecyclerView.notifyDataSetChanged(); } diff --git a/app/src/main/java/com/haibin/calendarviewproject/group/GroupItemDecoration.java b/app/src/main/java/com/haibin/calendarviewproject/group/GroupItemDecoration.java new file mode 100644 index 00000000..14b63e94 --- /dev/null +++ b/app/src/main/java/com/haibin/calendarviewproject/group/GroupItemDecoration.java @@ -0,0 +1,277 @@ +package com.haibin.calendarviewproject.group; + +import android.annotation.SuppressLint; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; + +import java.util.HashMap; +import java.util.Map; + +/** + * 分组浮动的ItemDecoration + * Created by haibin on 2017/5/15. + */ +@SuppressWarnings("all") +public class GroupItemDecoration extends RecyclerView.ItemDecoration { + protected int mGroupHeight; + protected int mGroutBackground; + protected Paint mBackgroundPaint; + protected Paint mTextPaint; + protected float mTextBaseLine; + protected int mPaddingLeft, mPaddingRight; + protected boolean isCenter; + protected boolean isHasHeader; + @SuppressLint("UseSparseArrays") + protected Map mGroup = new HashMap<>(); + + public GroupItemDecoration() { + super(); + init(); + } + + private void init() { + mBackgroundPaint = new Paint(); + mBackgroundPaint.setColor(0xFFf5f7f8); + mBackgroundPaint.setStyle(Paint.Style.FILL); + mBackgroundPaint.setAntiAlias(true); + + mTextPaint = new Paint(); + mTextPaint.setColor(0xFF353535); + mTextPaint.setAntiAlias(true); + } + + /** + * 先于RecyclerView的Item onDraw调用 + * + * @param c RecyclerView canvas + * @param parent RecyclerView + * @param state stare + */ + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + super.onDraw(c, parent, state); + onDrawGroup(c, parent); + } + + /** + * 绘制分组Group + * + * @param c Canvas + * @param parent RecyclerView + */ + protected void onDrawGroup(Canvas c, RecyclerView parent) { + int paddingLeft = parent.getPaddingLeft(); + int right = parent.getWidth() - parent.getPaddingRight(); + int top, bottom; + int count = parent.getChildCount(); + for (int i = 0; i < parent.getChildCount(); i++) { + View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + int key = params.getViewLayoutPosition(); + if (mGroup.containsKey(key)) { + top = child.getTop() - params.topMargin - mGroupHeight; + bottom = top + mGroupHeight; + c.drawRect(paddingLeft, top, right, bottom, mBackgroundPaint); + String group = mGroup.get(params.getViewLayoutPosition()).toString(); + float x; + float y = top + mTextBaseLine; + if (isCenter) { + x = parent.getMeasuredWidth() / 2 - getTextX(group); + } else { + x = mPaddingLeft; + } + c.drawText(group, x, y, mTextPaint); + } + } + } + + /** + * 后于RecyclerView的Item onDraw调用 + * + * @param c RecyclerView canvas + * @param parent RecyclerView + * @param state stare + */ + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + super.onDrawOver(c, parent, state); + onDrawOverGroup(c, parent); + } + + /** + * 绘制悬浮组 + * + * @param c Canvas + * @param parent RecyclerView + */ + protected void onDrawOverGroup(Canvas c, RecyclerView parent) { + int firstVisiblePosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); + if (firstVisiblePosition == RecyclerView.NO_POSITION) { + return; + } + Group group = getCroup(firstVisiblePosition); + if (group == null) + return; + String groupTitle = group.toString(); + if (TextUtils.isEmpty(groupTitle)) { + return; + } + boolean isRestore = false; + Group nextGroup = getCroup(firstVisiblePosition + 1); + if (nextGroup != null && !group.equals(nextGroup)) { + //说明是当前组最后一个元素,但不一定碰撞了 + View child = parent.findViewHolderForAdapterPosition(firstVisiblePosition).itemView; + if (child.getTop() + child.getMeasuredHeight() < mGroupHeight) { + //进一步检测碰撞 + c.save();//保存画布当前的状态 + isRestore = true; + c.translate(0, child.getTop() + child.getMeasuredHeight() - mGroupHeight); + } + } + int left = parent.getPaddingLeft(); + int right = parent.getWidth() - parent.getPaddingRight(); + int top = parent.getPaddingTop(); + int bottom = top + mGroupHeight; + c.drawRect(left, top, right, bottom, mBackgroundPaint); + float x; + float y = top + mTextBaseLine; + if (isCenter) { + x = parent.getMeasuredWidth() / 2 - getTextX(groupTitle); + } else { + x = mPaddingLeft; + } + c.drawText(groupTitle, x, y, mTextPaint); + if (isRestore) { + //还原画布为初始状态 + c.restore(); + } + } + + /** + * 设置item的上下左右偏移量 + * + * @param outRect rect + * @param view item + * @param parent RecyclerView + * @param state stare + */ + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + getItemOffsets(outRect, view, parent, parent.getChildViewHolder(view).getAdapterPosition()); + } + + /** + * 设置item的上下左右偏移量,不做任何处理就是默认状态 + * + * @param outRect outRect + * @param view view + * @param parent RecyclerView + * @param adapterPosition position + */ + protected void getItemOffsets(Rect outRect, View view, RecyclerView parent, int adapterPosition) { + if (mGroup.containsKey(adapterPosition)) { + outRect.set(0, mGroupHeight, 0, mGroup.containsKey(adapterPosition + 1) ? 0 : 20); + } else { + outRect.set(0, 0, 0, mGroup.containsKey(adapterPosition + 1) ? 0 : 20); + } + } + + /** + * 获得当前ViewPosition所在的组 + * + * @param position 当前View的position + * @return 当前ViewPosition所在的组 + */ + protected Group getCroup(int position) { + while (position >= 0) { + if (mGroup.containsKey(position)) { + return mGroup.get(position); + } + position--; + } + return null; + } + + /** + * 通知更新分组信息 + * + * @param adapter GroupRecyclerAdapter + */ + public void notifyDataSetChanged(GroupRecyclerAdapter adapter) { + mGroup.clear(); + if (adapter == null) return; + int key = 0; + for (int i = 0; i < adapter.getGroupCount(); i++) { + if (i == 0) { + mGroup.put(isHasHeader ? 1 : 0, adapter.getGroup(i)); + key += adapter.getChildCount(i) + (isHasHeader ? 1 : 0); + ; + } else { + mGroup.put(key, adapter.getGroup(i)); + key += adapter.getChildCount(i); + } + } + } + + public void setBackground(int groupBackground) { + mBackgroundPaint.setColor(groupBackground); + } + + public void setTextColor(int textColor) { + mTextPaint.setColor(textColor); + } + + public void setTextSize(float textSize) { + mTextPaint.setTextSize(textSize); + Paint.FontMetrics metrics = mTextPaint.getFontMetrics(); + mTextBaseLine = mGroupHeight / 2 - metrics.descent + (metrics.bottom - metrics.top) / 2; + } + + public void setGroupHeight(int groupHeight) { + mGroupHeight = groupHeight; + Paint.FontMetrics metrics = mTextPaint.getFontMetrics(); + mTextBaseLine = mGroupHeight / 2 - metrics.descent + (metrics.bottom - metrics.top) / 2; + } + + public void setPadding(int mPaddingLeft, int mPaddingRight) { + this.mPaddingLeft = mPaddingLeft; + this.mPaddingRight = mPaddingRight; + } + + public void setCenter(boolean isCenter) { + this.isCenter = isCenter; + } + + public void setHasHeader(boolean hasHeader) { + isHasHeader = hasHeader; + } + + /** + * 获取文本的x坐标起点 + * + * @param str 文本 + * @return x + */ + protected float getTextX(String str) { + Rect bounds = new Rect(); + mTextPaint.getTextBounds(str, 0, str.length(), bounds); + return bounds.width() / 2; + } + + /** + * 获取文本的长度像素 + * @param str 文本 + * @return px + */ + protected float getTextLenghtPx(String str) { + Rect bounds = new Rect(); + mTextPaint.getTextBounds(str, 0, str.length(), bounds); + return bounds.width(); + } +} diff --git a/app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerAdapter.java b/app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerAdapter.java new file mode 100644 index 00000000..e710332f --- /dev/null +++ b/app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerAdapter.java @@ -0,0 +1,135 @@ +package com.haibin.calendarviewproject.group; + +import android.content.Context; + + +import com.haibin.calendarviewproject.base.adapter.BaseRecyclerAdapter; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + + +/** + * 分组的RecyclerAdapter + * Created by haibin on 2017/5/15. + */ +@SuppressWarnings("unused") +public abstract class GroupRecyclerAdapter extends BaseRecyclerAdapter { + private LinkedHashMap> mGroups; + private List mGroupTitles; + + public GroupRecyclerAdapter(Context context) { + super(context); + mGroups = new LinkedHashMap<>(); + mGroupTitles = new ArrayList<>(); + } + + /** + * 返回特定的标题 + */ + Parent getGroup(int groupPosition) { + return mGroupTitles.get(groupPosition); + } + + /** + * 获得分组的数量 + * + * @return 组的数量 + */ + int getGroupCount() { + return mGroupTitles.size(); + } + + /** + * 获取某一组的数量 + * + * @param groupPosition groupPosition + * @return 某一组的数量 + */ + int getChildCount(int groupPosition) { + if (mGroupTitles == null || mGroups.size() == 0) + return 0; + if (mGroups.get(mGroupTitles.get(groupPosition)) == null) + return 0; + return mGroups.get(mGroupTitles.get(groupPosition)).size(); + } + + /** + * 重置分组数据 + * + * @param groups groups + * @param titles titles + */ + protected void resetGroups(LinkedHashMap> groups, List titles) { + if (groups == null || titles == null) { + return; + } + mGroups.clear(); + mGroupTitles.clear(); + mGroups.putAll(groups); + mGroupTitles.addAll(titles); + mItems.clear(); + for (Parent key : mGroups.keySet()) { + mItems.addAll(mGroups.get(key)); + } + notifyDataSetChanged(); + } + + /** + * 清除分组数据 + */ + public final void clearGroup() { + mGroupTitles.clear(); + mGroups.clear(); + clear(); + } + + /** + * 从分组移除数据 + * + * @param position 下标 + * @return 分组是否为空,要移除分组 + */ + public boolean removeGroupItem(int position) { + int group = getGroupIndex(position); + removeGroupChildren(group); + int count = getChildCount(group); + removeItem(position); + if (count <= 0) { + mGroupTitles.remove(group); + return true; + } + return false; + } + + /** + * 获取所在分组 + * + * @param position 下标 + * @return 获取所在分组 + */ + private int getGroupIndex(int position) { + int count = 0; + if (position <= count) + return 0; + int i = 0; + for (Parent parent : mGroups.keySet()) { + count += mGroups.get(parent).size(); + if (position < count) { + return i; + } + i++; + } + return 0; + } + + private void removeGroupChildren(int groupPosition) { + if (groupPosition >= mGroupTitles.size()) + return; + List childList = mGroups.get(mGroupTitles.get(groupPosition)); + if (childList != null && childList.size() != 0) { + childList.remove(childList.size() - 1); + } + } +} diff --git a/app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerView.java b/app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerView.java new file mode 100644 index 00000000..79597e4f --- /dev/null +++ b/app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerView.java @@ -0,0 +1,88 @@ +package com.haibin.calendarviewproject.group; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +import com.haibin.calendarviewproject.R; + + +/** + * 带分组浮动的RecyclerView + * Created by haibin on 2017/5/15. + */ +@SuppressWarnings("all") +public class GroupRecyclerView extends RecyclerView { + private GroupItemDecoration mItemDecoration; + private int mGroupHeight; + private int mGroutBackground, mTextColor; + private int mTextSize; + private int mPaddingLeft, mPaddingRight; + private boolean isCenter; + private boolean isHasHeader; + private OnGroupChangeListener mListener; + + public GroupRecyclerView(Context context) { + super(context); + } + + public GroupRecyclerView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.GroupRecyclerView); + mTextSize = array.getDimensionPixelSize(R.styleable.GroupRecyclerView_group_text_size, 16); + mGroupHeight = (int) array.getDimension(R.styleable.GroupRecyclerView_group_height, 52); + mTextColor = array.getColor(R.styleable.GroupRecyclerView_group_text_color, 0xFFFFFFFF); + mGroutBackground = array.getColor(R.styleable.GroupRecyclerView_group_background, 0x80000000); + isCenter = array.getBoolean(R.styleable.GroupRecyclerView_group_center, false); + isHasHeader = array.getBoolean(R.styleable.GroupRecyclerView_group_has_header, true); + mPaddingLeft = (int) array.getDimension(R.styleable.GroupRecyclerView_group_padding_left, 16); + mPaddingRight = (int) array.getDimension(R.styleable.GroupRecyclerView_group_padding_right, 16); + array.recycle(); + } + + + @Override + public void setAdapter(Adapter adapter) { + if (adapter instanceof GroupRecyclerAdapter) { + super.setAdapter(adapter); + } else { + throw new IllegalStateException("Adapter must instanceof " + + "GroupRecyclerAdapter or extends GroupRecyclerAdapter"); + } + } + + @Override + public void addItemDecoration(ItemDecoration decor) { + if (decor instanceof GroupItemDecoration) + super.addItemDecoration(decor); + else + throw new IllegalStateException("ItemDecoration must instanceof " + + "GroupItemDecoration or extends GroupItemDecoration"); + mItemDecoration = (GroupItemDecoration) decor; + mItemDecoration.setTextSize(mTextSize); + mItemDecoration.setBackground(mGroutBackground); + mItemDecoration.setTextColor(mTextColor); + mItemDecoration.setGroupHeight(mGroupHeight); + mItemDecoration.setPadding(mPaddingLeft, mPaddingRight); + mItemDecoration.setCenter(isCenter); + mItemDecoration.setHasHeader(isHasHeader); + //mItemDecoration.notifyDataSetChanged((GroupRecyclerAdapter) getAdapter()); + } + + public void notifyDataSetChanged() { + mItemDecoration.notifyDataSetChanged((GroupRecyclerAdapter) getAdapter()); + } + + public void setOnGroupChangeListener(OnGroupChangeListener listener) { + this.mListener = listener; + } + + /** + * 分组最上面改变通知 + */ + public interface OnGroupChangeListener { + void onGroupChange(int groupPosition, String group); + } +} diff --git a/app/src/main/java/com/haibin/calendarviewproject/index/IndexActivity.java b/app/src/main/java/com/haibin/calendarviewproject/index/IndexActivity.java index 4999bf89..a29d616e 100644 --- a/app/src/main/java/com/haibin/calendarviewproject/index/IndexActivity.java +++ b/app/src/main/java/com/haibin/calendarviewproject/index/IndexActivity.java @@ -3,15 +3,20 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; import com.haibin.calendarview.Calendar; import com.haibin.calendarview.CalendarView; +import com.haibin.calendarviewproject.Article; +import com.haibin.calendarviewproject.ArticleAdapter; import com.haibin.calendarviewproject.R; import com.haibin.calendarviewproject.base.activity.BaseActivity; import com.haibin.calendarviewproject.colorful.ColorfulActivity; +import com.haibin.calendarviewproject.group.GroupItemDecoration; +import com.haibin.calendarviewproject.group.GroupRecyclerView; import com.haibin.calendarviewproject.meizu.MeiZuActivity; import com.haibin.calendarviewproject.simple.SimpleActivity; @@ -36,6 +41,8 @@ public class IndexActivity extends BaseActivity implements RelativeLayout mRelativeTool; private int mYear; + GroupRecyclerView mRecyclerView; + public static void show(Context context) { context.startActivity(new Intent(context, IndexActivity.class)); } @@ -96,10 +103,11 @@ protected void initData() { schemes.add(getSchemeCalendar(year, month, 25, 0xFF13acf0, "假")); mCalendarView.setSchemeDate(schemes); - findViewById(R.id.ll_flyme).setOnClickListener(this); - findViewById(R.id.ll_simple).setOnClickListener(this); - findViewById(R.id.ll_colorful).setOnClickListener(this); - findViewById(R.id.ll_index).setOnClickListener(this); + mRecyclerView = (GroupRecyclerView) findViewById(R.id.recyclerView); + mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + mRecyclerView.addItemDecoration(new GroupItemDecoration()); + mRecyclerView.setAdapter(new ArticleAdapter(this)); + mRecyclerView.notifyDataSetChanged(); } diff --git a/app/src/main/java/com/haibin/calendarviewproject/meizu/MeiZuActivity.java b/app/src/main/java/com/haibin/calendarviewproject/meizu/MeiZuActivity.java index 21a617eb..7142f924 100644 --- a/app/src/main/java/com/haibin/calendarviewproject/meizu/MeiZuActivity.java +++ b/app/src/main/java/com/haibin/calendarviewproject/meizu/MeiZuActivity.java @@ -4,17 +4,19 @@ import android.content.Context; import android.content.Intent; import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; import com.haibin.calendarview.Calendar; import com.haibin.calendarview.CalendarView; +import com.haibin.calendarviewproject.Article; import com.haibin.calendarviewproject.ArticleAdapter; -import com.haibin.calendarviewproject.base.activity.BaseActivity; import com.haibin.calendarviewproject.R; +import com.haibin.calendarviewproject.base.activity.BaseActivity; import com.haibin.calendarviewproject.colorful.ColorfulActivity; +import com.haibin.calendarviewproject.group.GroupItemDecoration; +import com.haibin.calendarviewproject.group.GroupRecyclerView; import com.haibin.calendarviewproject.index.IndexActivity; import com.haibin.calendarviewproject.simple.SimpleActivity; @@ -39,7 +41,7 @@ public class MeiZuActivity extends BaseActivity implements RelativeLayout mRelativeTool; private int mYear; - RecyclerView mRecyclerView; + GroupRecyclerView mRecyclerView; public static void show(Context context) { context.startActivity(new Intent(context, MeiZuActivity.class)); @@ -102,14 +104,11 @@ protected void initData() { schemes.add(getSchemeCalendar(year, month, 25, 0xFF13acf0,"假")); mCalendarView.setSchemeDate(schemes); -// findViewById(R.id.ll_flyme).setOnClickListener(this); -// findViewById(R.id.ll_simple).setOnClickListener(this); -// findViewById(R.id.ll_colorful).setOnClickListener(this); -// findViewById(R.id.ll_index).setOnClickListener(this); - - mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); + mRecyclerView = (GroupRecyclerView) findViewById(R.id.recyclerView); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + mRecyclerView.addItemDecoration(new GroupItemDecoration()); mRecyclerView.setAdapter(new ArticleAdapter(this)); + mRecyclerView.notifyDataSetChanged(); } diff --git a/app/src/main/java/com/haibin/calendarviewproject/simple/SimpleActivity.java b/app/src/main/java/com/haibin/calendarviewproject/simple/SimpleActivity.java index 4936c49d..5c48c5d4 100644 --- a/app/src/main/java/com/haibin/calendarviewproject/simple/SimpleActivity.java +++ b/app/src/main/java/com/haibin/calendarviewproject/simple/SimpleActivity.java @@ -11,10 +11,13 @@ import com.haibin.calendarview.Calendar; import com.haibin.calendarview.CalendarView; +import com.haibin.calendarviewproject.Article; import com.haibin.calendarviewproject.ArticleAdapter; import com.haibin.calendarviewproject.R; import com.haibin.calendarviewproject.base.activity.BaseActivity; import com.haibin.calendarviewproject.colorful.ColorfulActivity; +import com.haibin.calendarviewproject.group.GroupItemDecoration; +import com.haibin.calendarviewproject.group.GroupRecyclerView; import com.haibin.calendarviewproject.index.IndexActivity; import com.haibin.calendarviewproject.meizu.MeiZuActivity; @@ -38,7 +41,7 @@ public class SimpleActivity extends BaseActivity implements RelativeLayout mRelativeTool; - RecyclerView mRecyclerView; + GroupRecyclerView mRecyclerView; private int mYear; public static void show(Context context) { @@ -84,9 +87,11 @@ public void onClick(View v) { mTextMonthDay.setText(mCalendarView.getCurMonth() + "月" + mCalendarView.getCurDay() + "日"); mTextLunar.setText("今日"); mTextCurrentDay.setText(String.valueOf(mCalendarView.getCurDay())); - mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); + mRecyclerView = (GroupRecyclerView) findViewById(R.id.recyclerView); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); - mRecyclerView.setAdapter(new ArticleAdapter(SimpleActivity.this)); + mRecyclerView.addItemDecoration(new GroupItemDecoration()); + mRecyclerView.setAdapter(new ArticleAdapter(this)); + mRecyclerView.notifyDataSetChanged(); } @Override diff --git a/app/src/main/res/layout/activity_colorful.xml b/app/src/main/res/layout/activity_colorful.xml index 6832039b..b385cf3a 100644 --- a/app/src/main/res/layout/activity_colorful.xml +++ b/app/src/main/res/layout/activity_colorful.xml @@ -95,7 +95,7 @@ android:layout_height="match_parent" android:background="#fff" android:orientation="vertical" - app:calendar_content_view_id="@+id/linearView"> + app:calendar_content_view_id="@+id/recyclerView"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:background="@color/content_background" /> diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index be9e8f2f..2c0685a0 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -95,7 +95,7 @@ android:layout_height="match_parent" android:orientation="vertical" android:background="#fff" - app:calendar_content_view_id="@+id/linearView"> + app:calendar_content_view_id="@+id/recyclerView"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:background="@color/content_background" /> diff --git a/app/src/main/res/layout/activity_meizu.xml b/app/src/main/res/layout/activity_meizu.xml index 63bca2c1..878dc0bf 100644 --- a/app/src/main/res/layout/activity_meizu.xml +++ b/app/src/main/res/layout/activity_meizu.xml @@ -117,188 +117,21 @@ app:week_background="#fff" app:week_text_color="#111" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/app/src/main/res/layout/activity_simple.xml b/app/src/main/res/layout/activity_simple.xml index c377e92c..349af927 100644 --- a/app/src/main/res/layout/activity_simple.xml +++ b/app/src/main/res/layout/activity_simple.xml @@ -117,8 +117,16 @@ app:week_text_color="#111" app:week_view="com.haibin.calendarviewproject.simple.SimpleWeekView" /> - diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 00000000..acbc60a3 --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file