首先先上效果图:

首先我们先考虑这个界面有什么难点:

1.日期悬停。

2.今日和其他日期在悬停布局上的处理

3.首次进入时,自动滑动到今日比赛

4.向上滑动向下滑动一定距离后,出现向上向下的图标,并滚动到今日的比赛界面

5.向上加载更多,向下加载更多,当然这个并不算是难点,只是比较新颖~。

好了,首先我们一项一项的开始解决这几个难点,首先这样的列表布局,强烈推荐大家使用RecyclerView,谷歌粑粑真的是赋予了它无穷的潜力。观看本文前依然推荐一波博客地址:点击打开链接 一个头像狂魔的博客。

如果你已经看过了上篇博客,你可能会对这个界面已经有一定的了解,那么首先我们实现ItemDecoration的编写,首先我们应该考虑后台与我们交互时给出来的数据,一般为List或者Map格式,所以我们在编写时应充分考虑两种格式写法上的差异(其实也没什么差异的地方)。

public class HuPuItemDecoration<T extends HuPuBaseBean> extends RecyclerView.ItemDecoration {private int todayPosition;private List<T> mData;private Map<String, List<T>> mapData;private Paint mPaint;private int itemHeight;private int background;private int textSize;private int textColor;private Context context;private Rect outBounds = new Rect();public HuPuItemDecoration(Context context, int todayPosition, List<T> mData) {this.context = context;this.todayPosition = todayPosition;this.mData = mData;mPaint = new Paint();itemHeight = dip2px(context, 25);background = ContextCompat.getColor(context, android.R.color.darker_gray);textSize = sp2px(context, 15);textColor = ContextCompat.getColor(context, android.R.color.black);}public HuPuItemDecoration(Context context, int todayPosition, Map<String, List<T>> mapData) {this.context = context;this.todayPosition = todayPosition;this.mapData = mapData;mPaint = new Paint();itemHeight = dip2px(context, 25);background = ContextCompat.getColor(context, android.R.color.darker_gray);textSize = sp2px(context, 15);textColor = ContextCompat.getColor(context, android.R.color.black);for (Map.Entry<String, List<T>> entry : mapData.entrySet()) {mData.addAll(entry.getValue());}}

这里的HuPuBaseBean是一个bean类,内部实现了getDayType的方法,这里是基于封装而写出的基类,如果在实际项目中可以直接引入我们所需要的实体类来进行赋值。

初始化完成后,我们开始一步一步实现:代码很简单,一梭子给出来一部分先:

关于这部分方法的意义,推荐大家去鸿洋sama的博客去充值信仰!!!:点击打开链接

 @Overridepublic void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {super.getItemOffsets(outRect, view, parent, state);int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();if (null != mData && null != mapData) {throw new IllegalArgumentException("这里不会走到的,只是判断一下");}if (position > -1) {if (position == 0) {outRect.set(0, itemHeight, 0, 0);} else {if (!mData.get(position).getDayType().equals(mData.get(position - 1).getDayType())) {outRect.set(0, itemHeight, 0, 0);} else {outRect.set(0, 0, 0, 0);}}}}

这里的代码逻辑比较简单,就是当position==0时,我们必然会有一个divider去标识日期,而后当前的type不等于它所在位置的上一个position的type时,这时两个position所在的view中间应有一个divider来进行标识!这部分代码非常的简单,我们继续一梭子撸下面的代码:

  @Overridepublic void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {super.onDraw(c, parent, state);int left = parent.getPaddingLeft();int right = parent.getRight() - parent.getPaddingRight();int count = parent.getChildCount();for (int i = 0; i < count; i++) {View child = parent.getChildAt(i);RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams();int position = lp.getViewLayoutPosition();if (position == 0) {mPaint.setColor(background);c.drawRect(left, child.getTop() - itemHeight - lp.topMargin, right, child.getTop() - lp.topMargin, mPaint);mPaint.setColor(textColor);mPaint.setTextSize(textSize);String type = mData.get(position).getDayType();mPaint.getTextBounds(type, 0, type.length(), outBounds);c.drawText(type, child.getRight() / 2 - outBounds.width() / 2, child.getTop() - lp.topMargin -
  (itemHeight / 2 - outBounds.height() / 2), mPaint);} else {if (!mData.get(position).getDayType().equals(mData.get(position - 1).getDayType())) {mPaint.setColor(background);c.drawRect(left, child.getTop() - itemHeight - lp.topMargin, right, child.getTop() - lp.topMargin, mPaint);if (position == todayPosition) {mPaint.setColor(Color.RED);c.drawRect(left, child.getTop() - itemHeight - lp.topMargin, 15, child.getTop() - lp.topMargin, mPaint);}mPaint.setColor(background);mPaint.setTextSize(textSize);mPaint.setColor(textColor);String type = mData.get(position).getDayType();mPaint.getTextBounds(type, 0, type.length(), outBounds);c.drawText(type, child.getRight() / 2 - outBounds.width() / 2, child.getTop() -
  lp.topMargin - (itemHeight / 2 - outBounds.height() / 2), mPaint);} else {}}}}

这部分代码其实跟上面的代码在逻辑上非常接近,如果你已经看了最上面的博客链接,这里的逻辑你应该也能看得懂,这里和推荐博客在这里并没有什么不同,如果这里有任何疑问,我强烈大家去推荐博客那里去看详细的解释,(什么是甩锅,这就叫甩锅)。

最后一段代码:

  @Overridepublic void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {super.onDrawOver(c, parent, state);int position = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();View itemView = parent.findViewHolderForAdapterPosition(position).itemView;if (mData.size() - 1 >= position) {if (!mData.get(position).getDayType().equals(mData.get(position + 1).getDayType())) {if (itemView.getHeight() + itemView.getTop() < itemHeight) {c.translate(0, itemView.getHeight() + itemView.getTop() - itemHeight);}}}mPaint.setColor(background);c.drawRect(parent.getPaddingLeft(), parent.getPaddingTop(), parent.getRight() - parent.getPaddingRight(), 
parent.getPaddingTop() + itemHeight, mPaint);if (position >= todayPosition && mData.get(todayPosition).getDayType().equals(mData.get(position).getDayType())) {mPaint.setColor(Color.RED);c.drawRect(parent.getPaddingLeft(), parent.getPaddingTop(), 15, parent.getPaddingTop() + itemHeight, mPaint);}mPaint.setColor(textColor);mPaint.setTextSize(textSize);String dayType = mData.get(position).getDayType();mPaint.getTextBounds(dayType, 0, dayType.length(), outBounds);c.drawText(dayType, (parent.getRight() - parent.getPaddingRight() - parent.getPaddingLeft() - outBounds.width()) / 2,
 parent.getPaddingTop() + itemHeight - (itemHeight / 2 - outBounds.height() / 2), mPaint);}

这里就是做悬停部分的代码,这里唯一需要注意的就是我们对于今日比赛悬停界面的处理。

 if (position >= todayPosition && mData.get(todayPosition).getDayType().equals(mData.get(position).getDayType())) {mPaint.setColor(Color.RED);c.drawRect(parent.getPaddingLeft(), parent.getPaddingTop(), 15, parent.getPaddingTop() + itemHeight, mPaint);}

如果当前的position大于等于我们传过来的todayPos,然后type相等,既判定为今日比赛。其他则无视之。

写完了这部分代码后,我们就简单写一个RecyclerView出来:

 rv = (RecyclerView) findViewById(R.id.rv);top= (ImageView) findViewById(R.id.top);bottom= (ImageView) findViewById(R.id.bottom);for (int i = 0; i < 10; i++) {HuPuBean bean = new HuPuBean("雷霆", "火箭", "早上8:00", 124, 100, "昨日", false);mData.add(bean);}for (int i = 0; i < 10; i++) {HuPuBean bean = new HuPuBean("雷霆", "火箭", "早上8:00", 124, 100, "今日", true);mData.add(bean);}for (int i = 0; i < 10; i++) {HuPuBean bean = new HuPuBean("雷霆", "火箭", "早上8:00", 124, 100, "明日", true);mData.add(bean);}rv.addItemDecoration(new HuPuItemDecoration<HuPuBean>(MainActivity.this, Utils.getTodayPosition("今日", mData), mData));final LinearLayoutManager manger = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false);rv.setLayoutManager(manger);rv.setAdapter(new RecyclerView.Adapter<Holder>() {@Overridepublic Holder onCreateViewHolder(ViewGroup parent, int viewType) {View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item, parent, false);return new Holder(itemView);}@Overridepublic void onBindViewHolder(Holder holder, int position) {HuPuBean bean = mData.get(position);holder.teamOne.setText(bean.getTeamOne());holder.teamTwo.setText(bean.getTeamTwo());holder.teamOnePoint.setText("" + bean.getTeamOnePoint());holder.teamOnePoint.setText("" + bean.getTeamTwoPoint());}@Overridepublic int getItemCount() {return mData.size();}});

这里代码写得比较粗糙,勿怪。

然后我们来看一下效果图。

我们来看一下utils方法,也非常简单,因为涉及到加载刷新的逻辑,todayPostion的位置会发生改变,不建议使用赋值,

public class Utils {public static int getTodayPosition(String type, List<? extends HuPuBaseBean> mData) {for (int i = 0; i < mData.size(); i++) {if (mData.get(i).getDayType().equals(type)) {return i;}}return 0;}}

最后我们来处理上滑下滑时top bottom图片的显示隐藏:

首先我们看MianActivity的布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.v7.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/rv"></android.support.v7.widget.RecyclerView><ImageViewandroid:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="right"android:layout_marginTop="20dp"android:layout_marginRight="20dp"android:id="@+id/bottom"android:background="@mipmap/ic_launcher"android:visibility="gone"/><ImageViewandroid:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="bottom|right"android:layout_marginBottom="20dp"android:layout_marginRight="20dp"android:id="@+id/top"android:background="@mipmap/ic_launcher"android:visibility="gone"/>
</FrameLayout>

然后通过RecyclerView的对滑动监听来实现两张图片的显示和隐藏:

 rv.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);int position = manger.findFirstVisibleItemPosition();if(position-Utils.getTodayPosition("今日",mData)>=10){bottom.setVisibility(View.GONE);top.setVisibility(View.VISIBLE);}else if(position-Utils.getTodayPosition("今日",mData)<=-10){bottom.setVisibility(View.VISIBLE);top.setVisibility(View.GONE);}else {bottom.setVisibility(View.GONE);top.setVisibility(View.GONE);}}});

当然这种实现方式是最常见的,不过我们还可以通过自定义behavior这种方式来实现滑动的联动效果,但是本篇就不在这里实现了。

最后首次加载滑动到今日比赛,和点击图片滑动到今日比赛,其实非常简单,一行代码搞定:

  manger.scrollToPositionWithOffset(Utils.getTodayPosition("今日", mData), 0);

至此,基本的虎扑看球页面的效果就已经实现了,是不是非常简单,当然虎扑的页面更加复杂,itemType有数种,这里就不再实现了。最后去愉快的水群了。临走前在发一张我老婆的美图:

写一写虎扑APP首页效果,jrs都进来看一眼!相关推荐

  1. 虎扑APP遭全网下架 原因未知

    [TechWeb]3月25日消息,据众多网友反映,虎扑APP在苹果App Store被下架,仅能搜索到虎扑旗下另一款应用"识货".目前,虎扑APP在各大安卓市场也无法搜索到. 此外 ...

  2. 产品分析|虎扑APP

    不同于传统的体育新闻门户网站,虎扑以篮球社区起家,在经历了从体育论坛到体育新闻网站的发展后,又逐渐回归社区发展. 目前,虎扑汇聚了大量的男性用户,俨然成为了"互联网直男的自留地". ...

  3. 爬取虎扑NBA首页主干道推荐贴的一只小爬虫,日常爬不冷笑话解闷

    虎扑是广大jrs的家园,步行街是这个家园里最繁华的地段.据称广大jrs平均学历985,步行街街薪30w起步. 大学时经舍友安利,开始了解虎扑,主要是看看NBA的一些资讯. 偶尔也上上这个破街,看看jr ...

  4. 虎扑《不冷笑话》爬虫实战,顺带说说最近学写爬虫的经历(一)

    前言 楼主16年毕业,工作内容目前主要以ETL开发为主.有一段时间逛知乎,经常看到有人分享一些数据分析的文章,比如美团上的点餐分析.豆瓣的评分分析,还有网易云音乐热评分析之类的.感觉这些文章都是有实打 ...

  5. 产品分析报告—年轻人的体育社区—虎扑

    虎扑的前身是hoopCHINA篮球论坛,而hoop的中文意思就是篮圈,蓝框.毫无疑问,虎扑就是围绕"篮球"而慢慢展开各种业务的体育门户网站,其中包括各类体育新闻资讯,各大体育赛事直 ...

  6. 虎扑球员数据爬取+球员能力分布雷达图

    虎扑数据爬取+球员能力分布雷达图 学了一阵子python后,心痒痒想爬个网站试试,但得找个自己感兴趣的啊,那必然是篮球了.想了想平时看篮球的也就腾讯和虎扑,细心的jrs可能会发现腾讯体育点进球员个人主 ...

  7. 仿造虎扑步行街首页。

    原网站 https://bbs.hupu.com/all-gambia 我非常喜欢虎扑,所以我打算仿造一个虎扑论坛,这是仿造的第一个网页,也是虎扑步行街的首页,我仿造这个页面并对这个页面进行了优化,比 ...

  8. 社区产品如何搭建内容体系?看看懂球帝与虎扑如何做

    来源:新媒之家 对社区类产品来说,做好"内容"是一件尤其重要的事.好内容能够直接为用户带来价值,进而有效实现用户的拉新.留存,提升用户的粘度. 但是,如何做好内容却并不是一件容易的 ...

  9. SKR!虎扑66万JRS大战3300万吴亦凡护卫队,别逼我拿Python

    不甘现状的上海土著                                                                                  插画师 /小胖 编 ...

最新文章

  1. Mssql 之 定期备份数据库
  2. 关于软件外包的一些看法(转)
  3. WijmoJS 使用Web Workers技术,让前端 PDF 导出效率更高效
  4. Xmpp实现简单聊天系列 --- ②用户注册和登陆
  5. UA MATH563 概率论的数学基础 中心极限定理5 Renyi定理
  6. python中的 descriptor
  7. hadoop2.2.0 分布式存储hdfs完全分布式搭建及功能测试记录(一)----架构及原理介绍...
  8. poj3422 Kaka's Matrix Travels(最小费用最大流问题)
  9. eolinker使用初体验(一)
  10. C++中如何使用大整数__int 128
  11. python开发网络程序教程_python3编写C/S网络程序实例教程
  12. 语音识别,搜狗的下一个大梦想?
  13. Linux基本操作笔记
  14. JAVA_WEB程序设计教程 pdf
  15. 虽然不舍但是事实 —— 纪念下 JavaEye
  16. html设置尖角,CSS为div添加尖角样式
  17. vn.py源码解读(八、回测结果计算代码解析)
  18. 几种混沌系统混沌模型
  19. 周受资将兼任TikTok CEO;默沙东中国总裁罗万里将出任美国总裁 | 高管变动2021年4月26日-5月2日
  20. Quick BI可以帮助我们大大提升响应速度

热门文章

  1. sqlite与mysql的区别
  2. 共享单车双寡头时代背后,ofo戴威的执念与博弈
  3. 聆思 CSK6 PWM使用说明
  4. 白高兴一场鸿蒙,白高兴一场的歇后语
  5. 3个空间互不平行的平面,其交点推导公式
  6. 光模块的核心器件包含哪些?
  7. 极少人知道手机还有这么多的隐密功能!
  8. 『摄影欣赏』20幅精美的秋天落叶风景欣赏【组图】
  9. Delphi/XE2 使用TIdHttp控件下载Https协议服务器文件[转]
  10. 用selenium制作爬虫爬取教务课程信息