客戶端骨架屏詳解

一直以來(lái)磁椒,客戶端的應(yīng)用中堤瘤,為了提升應(yīng)用的加載等待這段時(shí)間的用戶感知體驗(yàn),各種技術(shù)層出不窮浆熔。其中本辐,尤以菊花圖以及由它衍生各種加載動(dòng)畫(huà)最為突出。

對(duì)于菊花圖我們自不必多說(shuō)医增,現(xiàn)在對(duì)于加載的設(shè)計(jì)體驗(yàn)有了比菊花加載體驗(yàn)更棒的方法慎皱,即大家常看到的Skeleton Screen Loading叶骨,中文叫做骨架屏茫多。

所謂Skeleton Screen Loading,即表示在頁(yè)面完全渲染完成之前忽刽,用戶會(huì)看到一個(gè)占位的樣式天揖,用以描繪了當(dāng)前頁(yè)面的大致框架,加載完成后跪帝,最終骨架屏中各個(gè)占位部分將被真實(shí)的數(shù)據(jù)替換今膊。很多項(xiàng)目中都有相關(guān)的應(yīng)用,如餓了么h5版本伞剑、知乎斑唬、facebook等網(wǎng)站中都有應(yīng)用。 其效果如下圖所示:

iOS

iOS實(shí)現(xiàn)Skeleton效果的第三方庫(kù)有很多,當(dāng)然也可以自己創(chuàng)建一個(gè)恕刘,而骨架屏最核心的就是占位和屬性動(dòng)畫(huà)缤谎。在實(shí)現(xiàn)方面,本文介紹幾種主流的實(shí)現(xiàn)方式:

SkeletonView

實(shí)現(xiàn)原理

對(duì)UIView進(jìn)行擴(kuò)展雪营,增加skeletonable弓千、skeletonLayer等屬性。調(diào)用showSkeleton方法献起,對(duì)屬性skeletonable為true的視圖進(jìn)行遍歷,找到其最上層的镣陕、skeletonable為true的子View谴餐,然后創(chuàng)建skeletonLayer添加到上面,構(gòu)成骨架圖呆抑,動(dòng)效效果亦是在skeletonLayer層岂嗓。需要隱藏效果時(shí),調(diào)用hideSkeleton鹊碍,同樣進(jìn)行遍歷厌殉,移除skeletonLayer。

簡(jiǎn)單的說(shuō)侈咕,在顯示占位的時(shí)候公罕,將tableView的代理設(shè)置為通過(guò)某個(gè)對(duì)象,這個(gè)對(duì)象根據(jù)cell的Idenfier創(chuàng)建cell并添加占位顯示耀销。關(guān)閉顯示占位的時(shí)候楼眷,將代理tableView的代理切回ViewController,正常顯示熊尉。

特點(diǎn)

1罐柳、不需手動(dòng)寫(xiě)占位控件,不需處理圓角等問(wèn)題狰住,占位效果與實(shí)際控件布局一致张吉。

2、缺點(diǎn)是有的控件是自適應(yīng)大小催植,在未獲得數(shù)據(jù)之前肮蛹,控件位置是錯(cuò)誤的,導(dǎo)致占位效果有問(wèn)題查邢。

Somo

同樣是擴(kuò)展UIView蔗崎,添加屬性somoContainer,表示占位視圖的容器視圖扰藕,其中每個(gè)占位區(qū)域都是一個(gè)SomoView缓苛。對(duì)于想要顯示占位效果的View,需實(shí)現(xiàn)協(xié)議,在協(xié)議方法中返回SomoView列表未桥。將這些SomoView添加到somoContainer笔刹,并顯示。

特點(diǎn)

1冬耿、避免了上述自適應(yīng)控件無(wú)數(shù)據(jù)時(shí)大小不正確的問(wèn)題舌菜。

2、需要手工指定每個(gè)占位區(qū)域亦镶,且每個(gè)占位區(qū)域是UIView級(jí)別日月,不是CALayer。

TABAnimated

除此之外缤骨,TABAnimated也是一個(gè)被使用的比較多的爱咬,同樣TABAnimated也是擴(kuò)展的UIView。在ios中集成TABAnimated需要經(jīng)歷以下幾步:

1绊起,Install

pod 'TABAnimated'

2精拟,第二步(可選)

可以選擇在appDelegate的didFinishLaunchingWithOptions方法全局設(shè)置動(dòng)畫(huà)屬性,設(shè)有默認(rèn)屬性虱歪。例如:

// 設(shè)置TABAnimated相關(guān)屬性

[[TABViewAnimated sharedAnimated]initWithAnimatedDuration:0.3 withColor:tab_kBackColor];

3蜂绎,第三步,設(shè)置animatedStyle屬性

在需要?jiǎng)赢?huà)的view上笋鄙,將屬性animatedStyle設(shè)置為T(mén)ABTableViewAnimationStart,不需要?jiǎng)赢?huà)的view不用做額外的操作师枣。

// UIView和UICollectionView枚舉

typedef NS_ENUM(NSInteger,TABViewAnimationStyle) {

? ? TABViewAnimationDefault = 0,? ? ? ? ? ? ? // 默認(rèn),沒(méi)有動(dòng)畫(huà)

? ? TABViewAnimationStart,? ? ? ? ? ? ? ? ? ? // 開(kāi)始動(dòng)畫(huà)

? ? TABViewAnimationRuning,? ? ? ? ? ? ? ? ? ? // 動(dòng)畫(huà)中

? ? TABViewAnimationEnd,? ? ? ? ? ? ? ? ? ? ? // 結(jié)束動(dòng)畫(huà)

? ? TABCollectionViewAnimationStart,? ? ? ? ? // CollectionView 開(kāi)始動(dòng)畫(huà)

? ? TABCollectionViewAnimationRunning,? ? ? ? // CollectionView 動(dòng)畫(huà)中

? ? TABCollectionViewAnimationEnd? ? ? ? ? ? ? // CollectionView 結(jié)束動(dòng)畫(huà)

};

// UITableView枚舉

typedef NS_ENUM(NSInteger,TABViewAnimationStyle) {

? ? TABViewAnimationDefault = 0,? ? // 沒(méi)有動(dòng)畫(huà),默認(rèn)

? ? TABViewAnimationStart,? ? ? ? ? // 開(kāi)始動(dòng)畫(huà)

? ? TABViewAnimationEnd? ? ? ? ? ? // 結(jié)束動(dòng)畫(huà)

};

// UITableView例子

- (UITableView *)mainTV {

? ? if (!_mainTV) {

? ? ? ? _mainTV = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)];

? ? ? ? _mainTV.animatedStyle = TABTableViewAnimationStart;? // 開(kāi)啟動(dòng)畫(huà)

? ? ? ? _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;? //開(kāi)啟動(dòng)畫(huà)

? ? }

? ? return _headView;

}

4局装,第四步

1坛吁、將需要?jiǎng)拥慕M件的屬性loadStyle,設(shè)置為需要的類型铐尚,不需要?jiǎng)拥慕M件不用做額外的操作拨脉;

2、(可選)新增屬性tabViewWidth宣增,其為動(dòng)畫(huà)開(kāi)啟時(shí)該組件的寬度,有較為合理默認(rèn)值玫膀;

typedef enum {

? ? TABViewLoadAnimationDefault = 0, //默認(rèn)沒(méi)有動(dòng)畫(huà)

? ? TABViewLoadAnimationShort,? ? ? //動(dòng)畫(huà)先變短再變長(zhǎng)

? ? TABViewLoadAnimationLong? ? ? ? //動(dòng)畫(huà)先變長(zhǎng)再變短

}TABViewLoadAnimationStyle;? ? ? ? ? //view動(dòng)畫(huà)類型枚舉

{

? ? ? ? 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,第五步

在獲取到數(shù)據(jù)后爹脾,停止動(dòng)畫(huà)帖旨。

//停止動(dòng)畫(huà),并刷新數(shù)據(jù)

_mainTV.animatedStyle = TABTableViewAnimationEnd;

[_mainTV reloadData];

_headView.animatedStyle = TABViewAnimationEnd;

[_headView initWithData:headGame];

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


Android

在Android中,骨架屏的實(shí)現(xiàn)也后很多的第三方框架灵妨,常見(jiàn)的有以下幾個(gè)庫(kù):

ShimmerRecyclerView

ShimmerRecyclerView是一個(gè)帶有閃光和指示效果的庫(kù)解阅,其運(yùn)行效果如下圖:



源碼地址:https://github.com/sharish/ShimmerRecyclerView


Skeleton

Skeleton也是一個(gè)使用得比較廣泛的庫(kù),它現(xiàn)在使用閃存動(dòng)畫(huà)的內(nèi)存優(yōu)化版本泌霍,因此速度更快货抄,您也可以設(shè)置更大的布局動(dòng)畫(huà)。



項(xiàng)目源碼:https://github.com/ethanhua/Skeleton


spruce-android

Spruce 是一個(gè)輕量級(jí)動(dòng)畫(huà)庫(kù),可幫助編排屏幕上的動(dòng)畫(huà)蟹地,該庫(kù)同時(shí)還支持 iOS积暖。


源碼地址:https://github.com/willowtreeapps/spruce-android

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者怪与。
  • 序言:七十年代末夺刑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子分别,更是在濱河造成了極大的恐慌遍愿,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茎杂,死亡現(xiàn)場(chǎng)離奇詭異错览,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)煌往,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)轧邪,“玉大人刽脖,你說(shuō)我怎么就攤上這事〖捎蓿” “怎么了曲管?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)硕糊。 經(jīng)常有香客問(wèn)我院水,道長(zhǎng),這世上最難降的妖魔是什么简十? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任檬某,我火速辦了婚禮,結(jié)果婚禮上螟蝙,老公的妹妹穿的比我還像新娘恢恼。我一直安慰自己,他們只是感情好胰默,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布场斑。 她就那樣靜靜地躺著,像睡著了一般牵署。 火紅的嫁衣襯著肌膚如雪漏隐。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天奴迅,我揣著相機(jī)與錄音青责,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛爽柒,可吹牛的內(nèi)容都是我干的吴菠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼浩村,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼做葵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起心墅,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤酿矢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后怎燥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瘫筐,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年铐姚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了策肝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡隐绵,死狀恐怖之众,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情依许,我是刑警寧澤棺禾,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站峭跳,受9級(jí)特大地震影響膘婶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛀醉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一悬襟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滞欠,春花似錦古胆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至夭谤,卻和暖如春棺牧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背朗儒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工颊乘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留参淹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓乏悄,卻偏偏與公主長(zhǎng)得像浙值,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子檩小,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容