一直以來,不管是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須要經歷如下幾步:app
1,Install
pod search TABAnimated
2,第二步(可選)
能夠選擇在appDelegate的didFinishLaunchingWithOptions方法全局設置動畫屬性,設有默認屬性。例如:框架
// 設置TABAnimated相關屬性 [[TABViewAnimated sharedAnimated]initWithAnimatedDuration:0.3 withColor:tab_kBackColor];
3,第三步,設置animatedStyle屬性
在須要動畫的view上,將屬性animatedStyle設置爲TABTableViewAnimationStart,不須要動畫的view不用作額外的操做。less
// 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,第四步
- 將須要動的組件的屬性loadStyle,設置爲須要的類型,不須要動的組件不用作額外的操做;
- (可選)新增屬性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是一個帶有閃光和指示效果的庫,其運行效果以下圖:
源碼地址:https://github.com/sharish/ShimmerRecyclerView
Skeleton
Skeleton也是一個使用得比較普遍的庫,它如今使用閃存動畫的內存優化版本,所以速度更快,您也能夠設置更大的佈局動畫。
項目源碼:https://github.com/ethanhua/Skeleton
spruce-android
Spruce 是一個輕量級動畫庫,可幫助編排屏幕上的動畫,該庫同時還支持 iOS。
源碼地址:https://github.com/willowtreeapps/spruce-android
前端
在前端中,經過 puppeteer 在服務端操控 headless Chrome 打開開發中的須要生成骨架屏的頁面,在等待頁面加載渲染完成以後,在保留頁面佈局樣式的前提下,經過對頁面中元素進行刪減或增添,對已有元素經過層疊樣式進行覆蓋,這樣達到在不改變頁面佈局下,隱藏圖片和文字,經過樣式覆蓋,使得其展現爲灰色塊。而後將修改後的 HTML 和 CSS 樣式提取出來,這樣就實現了骨架屏。
前端的骨架屏實現和優化,建議讀者閱讀如下連接文章:
eleme骨架屏插件實現原理
page-skeleton-webpack-plugin
本文同步分享在 博客「xiangzhihong8」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。