开源:CloudReader - 一个仿网易云音乐UI

6820505 7年前
   <h2>CloudReader</h2>    <p>一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目。项目采取的是Retrofit + RxJava + MVVM-DataBinding架构开发。</p>    <h3>效果图</h3>    <ul>     <li>部分效果图</li>    </ul>    <p><img src="https://simg.open-open.com/show/1a438dbaa908aa5898b4263ad8075a61.png"></p>    <p style="text-align:center">cloudreader.png</p>    <ul>     <li>gif演示</li>    </ul>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b7376ef4eb089a20d704e5120cb16bdf.gif"></p>    <p style="text-align:center">cloudreader.gif</p>    <h2>Introduction</h2>    <p>网易云音乐于2013年4月23日正式发布,是一款主打发现和分享,带有浓厚社交基因的网络音乐产品。相信用过的人都知道它给人的体验是极好的,我看过了绝大多数仿写的案例,基本UI都不够细致,于是决定自己动手写一个,起初也不知道具体它是怎么布局的,后来使用SDK提供的工具 uiautomatorviewer 慢慢分析后再逐渐完善的,争取效果一致~</p>    <h2>模块分析</h2>    <p>干货(gank.io)</p>    <p>API使用的是动听(轮播图)和代码家的Gank.Io。</p>    <ul>     <li> <p>每日推荐:干货集中营推送的每日内容,包括每天一个妹子图,相关Android、IOS等其他干货。每天第12:30之后更新,因为双休不更新所以内容缓存三天网络取不到就取缓存。</p> </li>     <li> <p>福利:Glide加载图片,点击查看大图,支持双指缩放,一下可查看列表的所有图片,再也不用逐个点击每张图啦。</p> </li>     <li> <p>干货订制:可以筛选自己喜欢干货的类别,有全部、IOS、App、前端、休息视频和拓展资源。</p> </li>     <li> <p>大安卓:显示安卓的全部资讯。支持下拉刷新方便查看最新的资源。</p> </li>    </ul>    <p>电影(豆瓣)</p>    <p>API是豆瓣提供的,因为限制了每个ip每分钟请求的次数,所以请酌情使用,由此带来的不便请见谅。</p>    <ul>     <li><strong>电影热映区:</strong> 每日更新,展示最新上映的电影热度排行榜。</li>     <li><strong>豆瓣电影Top250:</strong> 豆瓣高分电影集锦,让你放心找好片~</li>    </ul>    <p>书籍(豆瓣)</p>    <p>使用的是豆瓣的搜索API。更多订制内容由于时间原因第一版还未添加,第二版会加上。</p>    <ul>     <li><strong>综合:</strong> 检索豆瓣综合类的书籍并展示。</li>     <li><strong>文学:</strong> 检索豆瓣文学类的书籍并展示。</li>     <li><strong>生活:</strong> 检索豆瓣生活类的书籍并展示。</li>    </ul>    <p>抽屉界面</p>    <p>完全仿网易云音乐抽屉界面,包括诸多细节如透明标题栏,背景透明度,水波纹颜色等。</p>    <ul>     <li><strong>项目主页:</strong> 展示项目介绍信息,及内容说明,可以分享给你的好友哦。</li>     <li><strong>扫码下载:</strong> 扫码即可下载App,帮助您快速试用~</li>     <li><strong>问题反馈:</strong> 常见问题归纳,反馈地方,联系方式都在这里哦!</li>     <li><strong>关于云阅:</strong> 更新日志在这里可见,主人是利用工作外时间做的,周期较长,满意的小伙伴给个Star吧,这将是我继续迭代的动力,谢谢~</li>    </ul>    <h2>What can be learned about this project</h2>    <p>那么,从本项目中你能学到哪些知识呢?</p>    <ul>     <li>1、干货集中营内容与豆瓣电影书籍内容。</li>     <li>2、高仿网易云音乐歌单详情页。</li>     <li>3、 NavigationView 搭配 DrawerLayout 的具体使用。</li>     <li>4、MvvM-DataBing的项目应用。</li>     <li>5、RxBus代替EventBus进行组件之间通讯。</li>     <li>6、 ToolBar 及 TabLayout 的使用姿势。</li>     <li>7、 Glide 加载监听,获取缓存,圆角图片,高斯模糊。</li>     <li>8、水波纹点击效果详细使用与适配。</li>     <li>9、 RecyclerView 下拉刷新上拉加载。</li>     <li>10、基于 DataBinding 的 ViewHolder 。</li>     <li>11、基于 DataBinding 的 BaseActivity 和 BaseFragment 。</li>     <li>12、 Fragment 懒加载模式。</li>     <li>13、沉浸式状态栏使用与版本适配。</li>     <li>14、 SwipeRefreshLayout 结合 RecyclerView 下拉刷新上拉加载。</li>     <li>15、 CoordinatorLayout + Behavior 实现标题栏渐变。</li>     <li>16、 NestedScrollView 嵌套 RecyclerView 的使用。</li>    </ul>    <h2>细节分析 - ToolBar 上的按钮点击效果</h2>    <p>仔细研究的人知道,网易云音乐的UI做的很精致,就拿一个 ToolBar 为例,上面的每个按钮的点击操作都有各自的效果。这给了用户一个很好的反馈,就是如下的效果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7e8e21f9916b4c71bc759f93626d78ff.gif"></p>    <p style="text-align:center">toolbar_click.gif</p>    <p>上图是在android 5.1系统下的效果图。在6.0上搜索的点击效果有些许改变,其他基本类似;5.0以下点击则都表现出一般选择器的效果。</p>    <p>然而做到以上的效果并不容易,需要你对 ToolBar 有深入的了解;不仅如此,水波纹的点击效果在不同的主题下是有不同的表现。下面一起来谈谈如何达到以上的效果。</p>    <p>关于ToolBar的布局</p>    <p>看到上图我们了解到一个 ToolBar 上有三种点击效果..</p>    <p>这就有点尴尬了..不急,我们慢慢来分析。利用SDK下的工具 uiautomatorviewer 可得知:左边的 <strong>菜单</strong> 按钮是 ToolBar 内部包裹的一个 Fragment ,其中是一个 ImageView 和一个小红点;然后中间是 HorizontalScrollView ,其中是三个 ImageView ;右边的搜索键则是通过设置 Menu 菜单而来,这样会有长按弹出“搜索”二字的提示。</p>    <p>现总结出两个问题:1、 ToolBar 上按钮的设置;2、不同按钮点击的水波纹效果</p>    <p>对于1: ToolBar 上按钮的设置</p>    <p>些许研究了 ToolBar 的使用后得知,可以直接在其内部包裹 Imageview 外,还可以通过菜单文件设置:</p>    <pre>  <code class="language-xml">@Override      public boolean onCreateOptionsMenu(Menu menu) {          getMenuInflater().inflate(R.menu.main, menu);          return true;      }</code></pre>    <p>其中, main.xml 内容如下:</p>    <pre>  <code class="language-xml"><?xml version="1.0" encoding="utf-8"?>  <menu xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto">      <item          android:id="@+id/action_search"          android:icon="@drawable/actionbar_search"// 显示图标          android:orderInCategory="100"// 菜单显示优先级          android:title="@string/actionbar_search"// Toast文字“搜索”          app:showAsAction="always" />// 总是显示,其中还有"never"点击后弹出显示;``ifRoom``根据空间判断是否显示  </menu></code></pre>    <p>然后再找到菜单相应的 id 处理点击事件:</p>    <pre>  <code class="language-xml">@Override  public boolean onOptionsItemSelected(MenuItem item) {          switch (item.getItemId()) {              case R.id.action_search:  //                Toast.makeText(this, "打开搜索页面", Toast.LENGTH_SHORT).show();                  return true;              default:                  return super.onOptionsItemSelected(item);          }   }</code></pre>    <p>这样就完成了两者点击效果不同的处理。</p>    <p>对于2:不同按钮点击的水波纹效果</p>    <p>这里不是使用 ripple 属性了,而是使用系统自带的点击水波纹选择器,给要产生点击效果的控件设置:</p>    <pre>  <code class="language-xml">android:background="?attr/selectableItemBackgroundBorderless"</code></pre>    <p>然而设置后你会发现所有点击的颜色都是一致的,如果你使用主题:</p>    <pre>  <code class="language-xml">theme="@style/Theme.AppCompat.Light.NoActionBar"</code></pre>    <p>点击效果就会全部是黑灰的,就是中间三个按钮的那种效果,如果想要点击效果是白色的话,需要设置主题:</p>    <pre>  <code class="language-xml">theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"</code></pre>    <p>知道这样后我们给不同的布局设置不同的主题就解决了这个问题。最终布局文件:</p>    <pre>  <code class="language-xml"><android.support.v7.widget.Toolbar          android:id="@+id/toolbar"          android:layout_width="match_parent"          android:layout_height="?attr/actionBarSize"          android:background="@color/colorTheme"          app:contentInsetStart="0.0dp"          app:popupTheme="@style/ThemeOverlay.AppCompat.Light"          app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">            <FrameLayout              android:id="@+id/ll_title_menu"              android:layout_width="wrap_content"              android:layout_height="match_parent"              android:background="?attr/selectableItemBackgroundBorderless"              android:paddingLeft="15dp"              android:paddingRight="15dp">                <ImageView                  android:id="@+id/iv_title_menu"                  android:layout_width="23dp"                  android:layout_height="wrap_content"                  android:layout_gravity="center"                  android:src="@drawable/titlebar_menu" />          </FrameLayout>            <HorizontalScrollView              android:layout_width="wrap_content"              android:layout_height="match_parent"              android:layout_gravity="center">                <LinearLayout                  android:layout_width="wrap_content"                  android:layout_height="match_parent"                  android:background="?attr/selectableItemBackgroundBorderless"                  app:theme="@style/Theme.AppCompat.Light.NoActionBar">                    <ImageView                      android:id="@+id/iv_title_gank"                      android:layout_width="55dp"                      android:layout_height="wrap_content"                      android:layout_gravity="center"                      android:background="?attr/selectableItemBackgroundBorderless"                      android:src="@drawable/titlebar_disco" />                    <ImageView                      android:id="@+id/iv_title_one"                      android:layout_width="55dp"                      android:layout_height="match_parent"                      android:background="?attr/selectableItemBackgroundBorderless"                      android:src="@drawable/titlebar_music" />                    <ImageView                      android:id="@+id/iv_title_dou"                      android:layout_width="55dp"                      android:layout_height="match_parent"                      android:background="?attr/selectableItemBackgroundBorderless"                      android:src="@drawable/titlebar_friends" />                </LinearLayout>            </HorizontalScrollView>     </android.support.v7.widget.Toolbar></code></pre>    <p>这样就得到了我们想要的效果~</p>    <p> </p>    <p> </p>