热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android之MaterialDesign使用(三)——SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+CollapsingT…

前面两篇对Material Design的基本控件做了介绍,但是那些相对来说都是比较孤立的,而且我们知道实践才是硬道理,所以,今天我们就利用前面学习到了简单的实现一个比较炫酷的效果,废话不多说,直

前面两篇对Material Design的基本控件做了介绍,但是那些相对来说都是比较孤立的,而且我们知道实践才是硬道理,所以,今天我们就利用前面学习到了简单的实现一个比较炫酷的效果,废话不多说,直接上效果图。

Android之MaterialDesign使用(三)—— SwipeRefreshLayout + CoordinatorLayout + AppBarLayout + CollapsingT...
滚动悬停.gif

这个效果如果在不知道Material Design之前,可能实现起来会很麻烦,至少对于我来说会一时间感觉无从下手,很多人会说,可以使用事件分发来实现,但是看到这个效果我觉得光想想里面到底要触发多少事件头就大了,但是如果我们使用Material Design来实现的话不仅速度快,而且代码量很少,下面我们一起来看看吧。

效果分析

1.有一个下拉刷新的功能
2.书籍、乌托邦、播客是可以滑动切换的
3.上面背景图滑动到看不见的时候我的字眼会出来,而且整个View的背景会变成纯白
4.继续向上滑动最近、收藏、下载、订阅会悬停,而且将滑动事件交给底部的控件执行
5.向下滑动的时候会慢慢复原到之前的状态

大致分析后基本的效果就是这些,下面我们一个一个来实现

功能一:实现下拉刷新的功能

实现这个功能非常简单,利用系统提供的SwipeRefreshLayout就可以了,但是需要注意的是,在使用SwipeRefreshLayout的过程中,特别是在滑动的过程中,如果子View里面包含了AppBarLayout会产生滑动冲突,因为两者都支持滑动;同时需要注意的是如果子View里面包含了ViewPager,你在滑动的过程中同样会产生滑动冲突,因为系统会无法判断事件交给谁处理,针对这两个滑动冲突,解决的办法为:

AppBarLayout与SwipeRefreshLayout刷新滑动冲突解决

appbarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, final int verticalOffset) { mSwipeRefreshLayout.setEnabled(verticalOffset >= 0);//页面滑动到顶部,才可以下拉刷新 } });

ViewPager与SwipeRefreshLayout刷新滑动冲突解决
在SwipeRefreshLayout处理事件的监听

/** * author: zhoufan * data: 2021/4/28 17:34 * content: 解决ViewPager与SwipeRefreshLayout的滑动冲突 */ public class VpSwipeRefreshLayout extends SwipeRefreshLayout { private float startY; private float startX; // 记录viewPager是否拖拽的标记 private boolean mIsVpDragger; private final int mTouchSlop; public VpSwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // 记录手指按下的位置 startY = ev.getY(); startX = ev.getX(); // 初始化标记 mIsVpDragger = false; break; case MotionEvent.ACTION_MOVE: // 如果viewpager正在拖拽中,那么不拦截它的事件,直接return false; if(mIsVpDragger) { return false; } // 获取当前手指位置 float endY = ev.getY(); float endX = ev.getX(); float distanceX = Math.abs(endX - startX); float distanceY = Math.abs(endY - startY); // 如果X轴位移大于Y轴位移,那么将事件交给viewPager处理。 if(distanceX > mTouchSlop && distanceX > distanceY) { mIsVpDragger = true; return false; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 初始化标记 mIsVpDragger = false; break; } // 如果是Y轴位移大于X轴,事件交给swipeRefreshLayout处理。 return super.onInterceptTouchEvent(ev); } }

功能二:书籍、乌托邦、播客是可以滑动切换的

滑动切换也是比较简单的,我们可以利用TabLayout+ViewPager来实现,具体的实现方式为:

定义布局:

代码实现:

String[] mTabList = new String[]{getString(R.string.book), getString(R.string.utopia), getString(R.string.podcast)}; ArrayList mTabFragmentList = new ArrayList(); mMineBookFragment = new MineBookFragment(); mMinePodCastFragment = new MinePodCastFragment(); mMineUtopiaFragment = new MineUtopiaFragment(); mTabFragmentList.add(mMineBookFragment); mTabFragmentList.add(mMineUtopiaFragment); mTabFragmentList.add(mMinePodCastFragment); mAdapter = new DynamicFragmentAdapter(getChildFragmentManager(), mTabFragmentList, mTabList); mMineViewPager.setAdapter(mAdapter); mMineTab.setViewPager(mMineViewPager); mMineViewPager.setOffscreenPageLimit(3);

功能三:上面背景图滑动到看不见的时候 我的 字眼会出来,而且整个View的背景会变成纯白。

我的 字眼的出现是由于手指在屏幕上面不断向上滑动,将背景图移出了整个屏幕,所以对于这种嵌套滑动而言,上面的那一部分一定是被AppBarLayout包裹的内容,所以我们只需要监听AppBarLayout的滑动事件就可以了

appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { // 解决AppBarLayout与SwipeRefreshLayout滑动冲突 mSwipeRefreshLayout.setEnabled(verticalOffset >= 0); // 判断appBarLayout被滑动的距离是否超过appBarLayout总高度的一半 if (-verticalOffset >= appBarLayout.getTotalScrollRange() / 2) { // 修改Toolbar的背景颜色 toolbar.setBackgroundColor(getResources().getColor(R.color.windowBackground)); // 设置 我的 透明度从而实现 我的 显示与隐藏 mTypeMine.setAlpha(1); } else { toolbar.setBackgroundColor(getResources().getColor(R.color.transparent)); mTypeMine.setAlpha(0); } });

功能四:继续向上滑动最近、收藏、下载、订阅会悬停,而且将滑动事件交给底部的控件执行

要实现上下滚动的嵌套配合,则需要使用到CoordinatorLayout控件,从前面两篇的分析可知,要实现这种滚动效果,我们的布局文件应该对应的结构是这样的

// 设置整个背景图 // 设置Toolbar(我的、以及右边设置等3个图标) // 设置最近、收藏、下载、订阅

整个结构虽然看起来像是挺复杂的,但是其实如果你仔细分析一下就会发现还是挺好懂的,基于上述的结构就可以实现滑动嵌套的效果啦,当然,向下滑动的时候也会慢慢呈现出初始的状态,最后看下整个XML的布局的效果。

代码实现

基于上面的XML布局文件,其实需要我们硬编码的就不是很多了

第一步:实现书籍、乌托邦、播客的滑动切换

String[] mTabList = new String[]{getString(R.string.book), getString(R.string.utopia), getString(R.string.podcast)}; ArrayList mTabFragmentList = new ArrayList(); mMineBookFragment = new MineBookFragment(); mMinePodCastFragment = new MinePodCastFragment(); mMineUtopiaFragment = new MineUtopiaFragment(); mTabFragmentList.add(mMineBookFragment); mTabFragmentList.add(mMineUtopiaFragment); mTabFragmentList.add(mMinePodCastFragment); mAdapter = new DynamicFragmentAdapter(getChildFragmentManager(), mTabFragmentList, mTabList); mMineViewPager.setAdapter(mAdapter); mMineTab.setViewPager(mMineViewPager); mMineViewPager.setOffscreenPageLimit(3);

第二步:实现AppBarLayout的滑动监听和SwipeRefreshLayout的监听

appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { mSwipeRefreshLayout.setEnabled(verticalOffset >= 0); if (-verticalOffset >= appBarLayout.getTotalScrollRange() / 2) { toolbar.setBackgroundColor(getResources().getColor(R.color.windowBackground)); mTypeMine.setAlpha(1); } else { toolbar.setBackgroundColor(getResources().getColor(R.color.transparent)); mTypeMine.setAlpha(0); } }); mSwipeRefreshLayout.setColorSchemeResources(R.color.colorE6B536); mSwipeRefreshLayout.setOnRefreshListener(() -> requestData());

就这两步就可以了,其他的效果在XML文件里面本身就已经实现了。哈哈哈,看来有了Material Design,实现嵌套滑动就容易多了。

推荐阅读
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了Java集合库的使用方法,包括如何方便地重复使用集合以及下溯造型的应用。通过使用集合库,可以方便地取用各种集合,并将其插入到自己的程序中。为了使集合能够重复使用,Java提供了一种通用类型,即Object类型。通过添加指向集合的对象句柄,可以实现对集合的重复使用。然而,由于集合只能容纳Object类型,当向集合中添加对象句柄时,会丢失其身份或标识信息。为了恢复其本来面貌,可以使用下溯造型。本文还介绍了Java 1.2集合库的特点和优势。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • React项目中运用React技巧解决实际问题的总结
    本文总结了在React项目中如何运用React技巧解决一些实际问题,包括取消请求和页面卸载的关联,利用useEffect和AbortController等技术实现请求的取消。文章中的代码是简化后的例子,但思想是相通的。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 本文介绍了Java中Hashtable的clear()方法,该方法用于清除和移除指定Hashtable中的所有键。通过示例程序演示了clear()方法的使用。 ... [详细]
  • 本文介绍了GregorianCalendar类的基本信息,包括它是Calendar的子类,提供了世界上大多数国家使用的标准日历系统。默认情况下,它对应格里高利日历创立时的日期,但可以通过调用setGregorianChange()方法来更改起始日期。同时,文中还提到了GregorianCalendar类为每个日历字段使用的默认值。 ... [详细]
author-avatar
HuPangpang_
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有