CloudReader

An open source project based on NetEase Cloud Music UI, developed using GankIo and Douban API in line with Google Material Desgin reading class. The project adopts Retrofit + RxJava + MVVM-Databinding architecture development. The various problems encountered during development are summarized here.

Github address: CloudReader

rendering

  • Partial renderings

cloudreader.png

  • GIF demo

cloudreader.gif

Introduction

Officially released on April 23, 2013, NetEase Cloud Music is an online music product featuring discovery and sharing and strong social gene. Believe that used the experience of people know it is very good, I have seen most of the copy writing case, basic UI is not enough careful, then decided to write a myself, at first, also don’t know how to layout of the specific it is, then use the SDK provides the tools uiautomatorviewer slowly analysis and then gradually perfect, strive for the same ~

Module analysis

Dry goods (gank.io)

The API uses sound (rotation map) and the coders’ gank. Io.

  • Daily recommendation: Dry goods concentration camp push daily content, including a girl picture every day, related Android, IOS and other dry goods. Update after 12:30 every day, because the double day does not update so the content cache three days network can not get cache.

  • Benefit: Glide load picture, click to view the larger picture, support double finger zoom, view all the pictures in the list, no longer need to click each picture one by one.

  • Dry goods customized: you can select the category of dry goods you like, with all, IOS, App, front-end, rest video and development resources.

  • Big Android: Displays all information about Android. Supports drop-down refresh to view the latest resources.

Movie (Douban)

The API is provided by Douban, because the number of requests per minute per IP is limited, so please use it accordingly, and we apologize for the inconvenience caused.

  • Hot movie section: updated daily, showing the hot list of the latest released movies.
  • Top250: Douban high score movie collection, let you rest assured to find a good movie ~

Book (Douban)

Douban’s search API is used. More customized content was not added in the first edition due to time constraints, but will be added in the second edition.

  • Comprehensive: Search douban comprehensive books and display them.
  • Literature: Search douban literature books and display them.
  • Life: Search douban life books and display them.

Drawer interface

Completely imitated NetEase Cloud Music drawer interface, including many details such as transparent title bar, background transparency, water ripple color, etc.

  • Project home page: display project introduction information, and content description, you can share with your friends oh.
  • Scan code download: scan code to download the App to help you quickly try ~
  • Problem feedback: FAQ induction, feedback place, contact information are here oh!
  • About Cloud reading: the update log can be seen here, the owner made it in his/her spare time, and the cycle is long. If you are satisfied, please give me a Star, which will be the motivation for me to continue to iterate. Thank you ~

What can be learned about this project

So, what can you learn from this project?

  • 1. Content of dry goods concentration camp and douban film and book.
  • 2. High imitation NetEase Cloud Music playlist details page.
  • 3,NavigationViewcollocationDrawerLayoutThe specific use of.
  • 4. Project application of MVVM-Databing.
  • 5. RxBus replaces EventBus for communication between components.
  • 6,ToolBarandTabLayoutThe use of posture.
  • 7,GlideLoad listener, get cache, rounded image, Gaussian blur.
  • 8, water ripple click effect detailed use and adaptation.
  • 9,RecyclerViewPull-down refresh pull-up load.
  • 10, is based onDataBindingtheViewHolder.
  • 11, based onDataBindingtheBaseActivityandBaseFragment.
  • 12,FragmentLazy loading mode.
  • Immersive status bar use and version adaptation.
  • 14,SwipeRefreshLayoutIn combination withRecyclerViewPull-down refresh pull-up load.
  • 15,CoordinatorLayout + BehaviorImplement title bar gradient.
  • 16,NestedScrollViewnestedRecyclerViewThe use of.

Detail Analysis – ToolBar button click effect

Those who study carefully know that NetEase Cloud Music’s UI is very delicate, take a ToolBar for example, each button click operation above has its own effect. This gives the user a good feedback, which is as follows:


toolbar_click.gif

This is an example of what it looks like in Android 5.1. The click effect of search on 6.0 has changed slightly, otherwise it is similar. Any click below 5.0 behaves like a normal selector.

However, doing this is not easy and requires a deep understanding of the ToolBar; Not only that, the water ripple click effect in different themes is different performance. Here’s how to do it.

About the layout of the ToolBar

Looking at the image above we see that there are three click effects on a ToolBar..

This is a little awkward.. No rush. Let’s take our time. Using the tool UIAutomatorViewer under SDK, we can know that: the menu button on the left is a Fragment wrapped inside the ToolBar, which contains an ImageView and a small red dot. And then in the middle is the HorizontalScrollView, which has three ImageViews; The search key on the right is through setting the Menu Menu, so there will be a long press pop-up “search” two word prompt.

Two problems are summarized: 1. Setup of the ToolBar button; 2, different button click water ripple effect

Settings for buttons on 1: ToolBar

After a little research into the ToolBar’s use, we learned that we can wrap Imageview directly inside it and also set it in a menu file:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }Copy the code

The main.xml content is as follows:

<? 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"// Display ICONS
        android:orderInCategory="100"// Menu displays priority
        android:title="@string/actionbar_search"// Toast text "search"
        app:showAsAction="always" />// always display "never"; IfRoom determines whether to display according to space
</menu>Copy the code

Then find the corresponding id of the menu to handle the click event:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_search:
Toast.maketext (this, "open search page ", toast.length_short).show();
                return true;
            default:
                return super.onOptionsItemSelected(item); }}Copy the code

This completes the processing of the difference between the two clicks.

For 2: water ripple effect of different button clicks

Instead of using the ripple property, use the system’s own click ripple selector to set the control that you want to click on:

android:background="? attr/selectableItemBackgroundBorderless"Copy the code

However, after setting it you will see that all the clicks are the same color if you use the theme:

theme="@style/Theme.AppCompat.Light.NoActionBar"Copy the code

Click and the effect will be all black and grey, which is the effect of the middle three buttons. If you want the effect to be white, you need to set the theme:

theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"Copy the code

With that in mind we solved the problem by giving different layouts different themes. Final layout file:

<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.0 dp"
        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>Copy the code

This gives us the look we want. For more details I will slowly sort out in the Wiki documentation, or you can view the source code directly.

DownLoad

Rushing to jump


download.png

Precious opinion

If you have any questions, please go to the Github issue and write down what you don’t understand. You can also contact me through the way provided below. I will help you in time. Other common problems are summarized here.

Thanks

  • Thanks to Iconfont for providing image resources, most of the images in the project are from this source, some from NetEase Cloud Music.

  • Thanks to our UI engineer, Sandra Wang, who designed some of the images such as ICONS.

  • Reference projects: ImitateNetEasyCloud, Banya; Main data sources: Gank.Io, Douban Api.

  • Open source libraries used: Glide, BottomSheet, NineoldAndroids, RxAndroid, etc.

  • Thanks to coders, Zhang Hongyang, Drakeet, Yang747046912, GiitSmile, ForezP and many other developers contributed open source projects, let me learn a lot from!

Statement

Thank you for the reference provided by NetEase Cloud Music App. Attached is “NetEase Cloud Music Android 3.0 Visual Design Specification Document”. I am a fan of NetEase Cloud music. I have used some of the material, which is not an attack. If it constitutes infringement, please timely inform me to modify or delete it. Most of the data comes from dry goods concentration camps and Douban APIV2.0, all data interpretation rights belong to code home and Douban all.

End

If you think it is good for you, you can help share it with more friends, which is the biggest motivation and support for us. Meanwhile, I hope you can fork, star and follow more, I will contribute more open source projects. Open source makes life better!

About me