客戶端骨架屏實現

一直以來,不管是Web仍是iOS、Android的應用中,爲了提高應用的加載等待這段時間的用戶感知體驗,各類技術層出不窮。其中,尤以菊花圖以及由它衍生各類加載動畫最爲突出。前端

對於菊花圖咱們自沒必要多說,如今對於加載的設計體驗有了比菊花加載體驗更棒的方法,即你們常看到的Skeleton Screen Loading,中文叫作骨架屏。android

所謂Skeleton Screen Loading,即表示在頁面徹底渲染完成以前,用戶會看到一個佔位的樣式,用以描繪了當前頁面的大體框架,加載完成後,最終骨架屏中各個佔位部分將被真實的數據替換。不少項目中都有相關的應用,如餓了麼h5版本、知乎、facebook等網站中都有應用。 其效果以下圖所示:webpack

在這裏插入圖片描述

iOS

iOS實現Skeleton效果的第三方庫有不少,固然也能夠本身建立一個,而骨架屏最核心的就是佔位和屬性動畫。在實現方面,本文介紹幾種主流的實現方式:ios

SkeletonView

實現原理

對UIView進行擴展,增長skeletonable、skeletonLayer等屬性。調用showSkeleton方法,對屬性skeletonable爲true的視圖進行遍歷,找到其最上層的、skeletonable爲true的子View,而後建立skeletonLayer添加到上面,構成骨架圖,動效效果亦是在skeletonLayer層。須要隱藏效果時,調用hideSkeleton,一樣進行遍歷,移除skeletonLayer。git

簡單的說,在顯示佔位的時候,將tableView的代理設置爲經過某個對象,這個對象根據cell的Idenfier建立cell並添加佔位顯示。關閉顯示佔位的時候,將代理tableView的代理切回ViewController,正常顯示。github

特色

  • 不需手動寫佔位控件,不需處理圓角等問題,佔位效果與實際控件佈局一致。
  • 缺點是有的控件是自適應大小,在未得到數據以前,控件位置是錯誤的,致使佔位效果有問題。

Somo

一樣是擴展UIView,添加屬性somoContainer,表示佔位視圖的容器視圖,其中每一個佔位區域都是一個SomoView。對於想要顯示佔位效果的View,需實現協議,在協議方法中返回SomoView列表。將這些SomoView添加到somoContainer,並顯示。web

特色

  • 避免了上述自適應控件無數據時大小不正確的問題。
  • 須要手工指定每一個佔位區域,且每一個佔位區域是UIView級別,不是CALayer。

TABAnimated

除此以外,TABAnimated也是一個被使用的比較多的,一樣TABAnimated也是擴展的UIView。在ios中集成TABAnimated須要經歷如下幾步:bash

1,Install

pod search TABAnimated
複製代碼

2,第二步(可選)

能夠選擇在appDelegate的didFinishLaunchingWithOptions方法全局設置動畫屬性,設有默認屬性。例如:app

// 設置TABAnimated相關屬性
[[TABViewAnimated sharedAnimated]initWithAnimatedDuration:0.3 withColor:tab_kBackColor];
複製代碼

3,第三步,設置animatedStyle屬性

在須要動畫的view上,將屬性animatedStyle設置爲TABTableViewAnimationStart,不須要動畫的view不用作額外的操做。框架

// UIView和UICollectionView枚舉
typedef NS_ENUM(NSInteger,TABViewAnimationStyle) {
    TABViewAnimationDefault = 0,               // 默認,沒有動畫
    TABViewAnimationStart,                     // 開始動畫
    TABViewAnimationRuning,                    // 動畫中
    TABViewAnimationEnd,                       // 結束動畫
    TABCollectionViewAnimationStart,           // CollectionView 開始動畫
    TABCollectionViewAnimationRunning,         // CollectionView 動畫中
    TABCollectionViewAnimationEnd              // CollectionView 結束動畫
};

// UITableView枚舉
typedef NS_ENUM(NSInteger,TABViewAnimationStyle) {
    TABViewAnimationDefault = 0,    // 沒有動畫,默認
    TABViewAnimationStart,          // 開始動畫
    TABViewAnimationEnd             // 結束動畫
};
複製代碼
// 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例子
- (TestHeadView *)headView {
    if (!_headView) {
        _headView = [[TestHeadView alloc]initWithFrame:CGRectMake(0, 0, tab_kScreenWidth, 90)];
        _headView.animatedStyle = TABViewAnimationStart;  //開啓動畫
    }
    return _headView;
}
複製代碼

4,第四步

  1. 將須要動的組件的屬性loadStyle,設置爲須要的類型,不須要動的組件不用作額外的操做;
  2. (可選)新增屬性tabViewWidth,其爲動畫開啓時該組件的寬度,有較爲合理默認值;
typedef enum {
    TABViewLoadAnimationDefault = 0, //默認沒有動畫
    TABViewLoadAnimationShort,       //動畫先變短再變長
    TABViewLoadAnimationLong         //動畫先變長再變短
}TABViewLoadAnimationStyle;          //view動畫類型枚舉
複製代碼
{
        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];
 }
複製代碼

5,第五步

在獲取到數據後,中止動畫。

//中止動畫,並刷新數據
_mainTV.animatedStyle = TABTableViewAnimationEnd;
[_mainTV reloadData];
    
_headView.animatedStyle = TABViewAnimationEnd;
[_headView initWithData:headGame];
複製代碼

示例源碼連接:iOS骨架屏示例

Android

在Android中,骨架屏的實現也後不少的第三方框架,常見的有如下幾個庫:

ShimmerRecyclerView

ShimmerRecyclerView是一個帶有閃光和指示效果的庫,其運行效果以下圖:

在這裏插入圖片描述

在這裏插入圖片描述

源碼地址:github.com/sharish/Shi…

Skeleton

Skeleton也是一個使用得比較普遍的庫,它如今使用閃存動畫的內存優化版本,所以速度更快,您也能夠設置更大的佈局動畫。

在這裏插入圖片描述

在這裏插入圖片描述

項目源碼:github.com/ethanhua/Sk…

spruce-android

Spruce 是一個輕量級動畫庫,可幫助編排屏幕上的動畫,該庫同時還支持 iOS。

在這裏插入圖片描述

源碼地址:github.com/willowtreea…

前端

在前端中,經過 puppeteer 在服務端操控 headless Chrome 打開開發中的須要生成骨架屏的頁面,在等待頁面加載渲染完成以後,在保留頁面佈局樣式的前提下,經過對頁面中元素進行刪減或增添,對已有元素經過層疊樣式進行覆蓋,這樣達到在不改變頁面佈局下,隱藏圖片和文字,經過樣式覆蓋,使得其展現爲灰色塊。而後將修改後的 HTML 和 CSS 樣式提取出來,這樣就實現了骨架屏。

前端的骨架屏實現和優化,建議讀者閱讀如下連接文章:

eleme骨架屏插件實現原理

page-skeleton-webpack-plugin

相關文章
相關標籤/搜索