Various technologies have been developed to improve the user experience of waiting for an app to load, whether on the Web or iOS or Android. Among them, chrysanthemum diagram and various loading animations derived from it are the most prominent.

Needless to say, there is now a better way to load the design experience than chrysanthemum, which is commonly known as Skeleton Screen Loading.

The so-called Skeleton Screen Loading means that before the page is completely rendered, the user will see a placeholder style to describe the general frame of the current page. After Loading, each placeholder part of the Skeleton Screen will be replaced with real data. There are related applications in many projects, such as ele. me H5 version, Zhihu, Facebook and other websites. The effect is shown below:

iOS

There are plenty of third-party libraries for iOS to implement the Skeleton effect, and you can create your own, but at the heart of the Skeleton screen are placeholders and property animations. In terms of implementation, this paper introduces several mainstream implementation methods:

SkeletonView

Realize the principle of

Extend UIView to add attributes such as skeleton onable and skeletonLayer. Call the showSkeleton method, iterate over the View with the attribute skeletononable true, find its topmost sub-view with skeletononable true, and create the skeletonLayer to add to it. The dynamic effects are also in the skeletonLayer. To hide the effects, call hideSkeleton and iterate again to remove the skeletonLayer.

To put it simply, when displaying placeholders, set the tableView’s proxy to pass through an object that creates the cell according to the Idenfier of the cell and adds the placeholder display. When the display placeholder is turned off, the proxy of the tableView is cut back to the ViewController and displayed normally.

The characteristics of

  • There is no need to manually write placeholder controls, no need to deal with rounded corners and other problems, placeholder effect is consistent with the actual control layout.
  • The disadvantage is that some controls are adaptive size, before the data is obtained, the control position is wrong, resulting in a placeholder effect is problematic.

Somo

Again, extend UIView by adding the property somoContainer, which represents the container view of the placeholder view, where each placeholder area is a SomoView. For views that want to display placeholders, implement the protocol and return the SomoView list in the protocol method. Add these SomoViews to the somoContainer and display them.

The characteristics of

  • The problem of incorrect size when the adaptive control has no data is avoided.
  • You need to manually specify each placeholder area, and each placeholder area is UIView level, not CALayer.

TABAnimated

In addition, TABAnimated is one of the most used, and TABAnimated is also an extended UIView. To integrate TABAnimated on ios, go through the following steps:

1, Install the

pod search TABAnimated
Copy the code

2. Step 2 (Optional)

Can choose the appDelegate didFinishLaunchingWithOptions methods global Settings animation properties, with the default properties. Such as:

/ / set TABAnimated relevant properties [[TABViewAnimated sharedAnimated] initWithAnimatedDuration: 0.3 withColor: tab_kBackColor];Copy the code

Step 3: Set the animatedStyle property

In need of the animation view, sets the attribute animatedStyle to TABTableViewAnimationStart, don’t need animation view without doing extra work.

/ / UIView and UICollectionView enumeration typedef NS_ENUM (NSInteger TABViewAnimationStyle) {TABViewAnimationDefault = 0, // By default, no animation TABViewAnimationStart, // animation TABViewAnimationRuning, // animation TABViewAnimationEnd, / / end animation TABCollectionViewAnimationStart, / / TABCollectionViewAnimationRunning CollectionView start animation, / / CollectionView animation TABCollectionViewAnimationEnd / / CollectionView end animation}; / / UITableView enumeration typedef NS_ENUM (NSInteger TABViewAnimationStyle) {TABViewAnimationDefault = 0, / / no animation, Default TABViewAnimationStart, // start animation TABViewAnimationEnd // end animation};Copy the code
// UITableView - (UITableView *)mainTV {if(! _mainTV) { _mainTV = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)]; _mainTV.animatedStyle = TABTableViewAnimationStart; _maintv.delegate = self; _mainTV.dataSource = self; _mainTV.rowHeight = 100; _mainTV.backgroundColor = [UIColor whiteColor]; _mainTV.estimatedRowHeight = 0; _mainTV.estimatedSectionFooterHeight = 0; _mainTV.estimatedSectionHeaderHeight = 0; _mainTV.separatorStyle = UITableViewCellSeparatorStyleNone; }return_mainTV; } // UIView example - (TestHeadView *)headView {if(! _headView) { _headView = [[TestHeadView alloc]initWithFrame:CGRectMake(0, 0, tab_kScreenWidth, 90)]; _headView.animatedStyle = TABViewAnimationStart; // Start animation}return _headView;
}
Copy the code

Step 4

  1. Set the loadStyle attribute of the component that needs to be moved to the required type. The component that does not need to be moved does not need to do additional operations.
  2. (Optional) Added property tabViewWidth, which is the width of the component when animation is on, with a reasonable default value;
Typedef enum {TABViewLoadAnimationDefault = 0, / / the default no animation TABViewLoadAnimationShort, / / first animated short variable-length TABViewLoadAnimationLong again. / / to change long and short} TABViewLoadAnimationStyle animation; // View animation type enumerationCopy the code
{
        UILabel *lab = [[UILabel alloc]init];
        [lab setFont:tab_kFont(15)];
        lab.loadStyle = TABViewLoadAnimationLong;
        lab.tabViewWidth = 100;
        [lab setTextColor:[UIColor blackColor]];
        [lab setText:@""];
        
        titleLab = lab;
        [self.contentView addSubview:lab];
 }
Copy the code

Step 5

After the data is retrieved, stop the animation.

// Stop animation and refresh data _maintv.animatedStyle = TABTableViewAnimationEnd; [_mainTV reloadData]; _headView.animatedStyle = TABViewAnimationEnd; [_headView initWithData:headGame];Copy the code

Example source link: iOS skeleton screen example

Android

In Android, the skeleton screen implementation is also a lot of third-party frameworks, common have the following libraries:

ShimmerRecyclerView

ShimmerRecyclerView is a library with flash and indicator effects.

Source code address: github.com/sharish/Shi…

Skeleton

Skeleton is also one of the more widely used libraries, and it now uses a memory-optimized version of flash animation, so it’s faster and you can set up larger layout animations.

Project source: github.com/ethanhua/Sk…

spruce-android

Spruce is a lightweight animation library that helps orchestrate on-screen animations and also supports iOS.

Source code address: github.com/willowtreea…

The front end

In the front end, headless Chrome is manipulated by puppeteer on the server to open the page in development that needs to generate skeleton screen. After the page loading and rendering is completed, the existing elements are covered by cascading style by deleting or adding elements in the page on the premise of retaining the page layout style. This allows you to hide images and text without changing the layout of the page, overlay them with styles, and make them appear as gray blocks. The modified HTML and CSS styles are then extracted to achieve a skeleton screen.

Front-end skeleton screen implementation and optimization, readers are advised to read the following link article:

Implementation principle of Eleme skeleton screen plug-in

page-skeleton-webpack-plugin