自動佈局(Autolayout)

關於自動佈局(Autolayout)

在Xcode中,自動佈局看似是一個很複雜的系統,在真正使用它以前,我也是這麼認爲的,不過事實並不是如此。html

 

咱們知道,一款iOS應用,其主要UI組件是由一個個相對獨立的可視單元構成,這些可視單元有的主要負責向用戶輸出有用的信息,有些則負責信息的輸入(交互),交互的過程當中每每還伴隨有動畫的效果,已達到整個信息傳遞的連貫性以及用戶體驗的細膩感。可視單元,在實際開發中主要是view、button等,那麼這些可視單元的關係由兩個基本的關係構成:兄弟關係和父子關係,整個視圖單元就是一個樹形結構:ios

對於任何一個UI組件,肯定了它的(相對於父view)位置、大小也就肯定了它在整個UI視圖中的展現效果。segmentfault

 

Autolayout(以及iOS8中新增的sizeclass)是爲了解決這些UI可視單元或者元素是怎樣佈局、排列的問題。在過去只有iPhone4的時候,咱們能夠在代碼裏將沒一個可視單元的位置寫死,這樣是沒問題的,但隨着iPhone五、6的發佈,屏幕尺寸有了愈來愈多中可能,將來不排除更多尺寸的iPhone發佈出來,這就要求咱們的APP的UI元素具備在屏幕尺寸不一樣的設備上具備必定動態的可調性,已實現較好的UI展現效果。從目前蘋果提供的技術來看,有下、中、上三種實現方法:xcode

 

下策是,代碼中判斷當前設備的尺寸,對UI元素進行手工的調整,其缺點是顯而易見的:代碼複雜、容易出錯、且維護難度大、靈活性極差;緩存

 

中策是,經過設置可視單元(UIView UIButton...)的autoresizing屬性,預設當該view所在的環境(父view)發生變化時它的尺寸和位置應該如何調整,該方法能夠在Xcode的interface builder中(storyboard 或者 xib)設置完成,但其只能針對父子關係進行有限的調整,好比左邊距是否固定,尺寸是否可變等,而對於兄弟關係的調整則沒法實現,對於UI比較固定的APP這種調節方式也算基本知足需求;ide

 

上策就是結合使用autolayout和sizeclass對UI可視單元的父子關係、兄弟關係進行全方位的調整,並且調節精度更高:不只能肯定一個view的位置尺寸的變化依據是什麼,還能對這些依據加以不一樣的優先級,先知足什麼條件,再知足什麼條件,對於重要的位置尺寸能夠優先保證,這樣整個APP就具備極強的動態可調性,知足不一樣設備、不一樣應用場景下的需求。佈局

 

在目前蘋果手機蘋果尺寸多達四種的狀況下,顯然新的APP必需要採用上策來解決視圖組件的佈局問題。學習

 

Autolayout的做用很是明確:幫咱們肯定在不一樣設備、不一樣(父view)環境下,同一個可視單元所應具備合適的位置和尺寸,所以,當一個UIView上所施加的約束可以惟一肯定它的frame(x, y, width, height)的時候咱們的自動佈局的使用纔是正確的。而新手一般犯的兩類錯誤就是約束不足(約束太少)和約束衝突兩種(約束太多)。若是你給出的約束只可以肯定這個view的大小,或者位置或者位置中的某一個項(好比x)的時候,就會出現約束不足的狀況,在xib或者storyboard中,會以***的警告出如今左側提示框內;若是你給出的約束推導出了兩個甚至多個互相矛盾的位置尺寸結果的時候,就產生了佈局錯誤,在編譯的時候直接就build不過。動畫

 

2、關於iOS8新增的sizeclass屬性

在iOS8中,新增了Size Classes特性,它是對當前全部iOS設備尺寸的一個抽象,也是該抽象了,想一想如今多少種iOS尺寸的設備吧:iPhone4-5-6-6plus、iPad、iPad mini、iWatch,如何仍是按照之前那針對種特定設備來編寫不一樣的佈局的話,必定是很糟糕的一件事情。ui

 

如今有了sizeclass,事情就好辦多了:你不是設備多嗎,那咱們就只把屏幕的寬和高分別分紅三種狀況:(Compact, Regular, Any),也即緊湊、正常和任意。這樣寬和高三三一整合,一共9中狀況。以下圖所示,針對每一種狀況,若是須要的話,咱們能夠單獨在storyboard或xib中設置UIView的自動佈局約束,甚至某一個button是否顯示都是能輕鬆實現。

 

關於size class的詳細解析,參考蘋果文檔和wwdc2014視:點擊打開連接 (What's New in Interface Builder)。

 

3、storyboard中autolayout和size class的無敵配合

對Xcode的interface builder比較熟悉的童鞋應該對UIButton的超強定製性映像深入:經過選擇button的不一樣狀態(normal、height、disabled...),咱們能夠單獨設置每一種狀態,button的background p_w_picpath、p_w_picpath、text color等屬性,見下圖:

 

而Xcode6中對自動佈局的重大變動有殊途同歸之妙:開發者能夠根據實際須要,針對size class的九種組合中的某一種或幾種分別進行自動佈局的設置,這樣,當APP運行於不一樣屏幕、不一樣旋轉方向的時候,就能夠根據當前環境的size class狀況使用咱們預先設置好的佈局信息,從而達到APP UI的極大靈活性。

 

和設置UIButton的不一樣狀態的不一樣屬性相似,咱們首先選擇一種size class,而後針對該種size class進行自動佈局。下面咱們以一個簡單的佈局場景爲例進行說明:

 

假設,咱們想實現下面這個效果:橫屏和豎屏頭像和label都能正常的現實,且在「比較恰當」的位置:顯然橫屏的時候,高度處於壓縮的狀態,(height: compact),咱們須要先對正常的佈局以外,還要添加一種(wAny, hCompact)size class的佈局:

 

首先,咱們對默認的sizeclass進行佈局,肯定頭像和label的位置和尺寸:

 

設置完(wAny hAny)以後,點擊wAny hAny文字(上圖底部),選擇(wAny hCompact):注意點擊後彈出一個九宮格浮框,拖動鼠標便可選擇響應的size class,注意在右下角(紅色方框表示),還能夠選擇是否install,若是取消勾選,則這個頭像在當前size class下就不會被加載(天然也就不顯示出來)。

 

在新的size class下咱們開始添加新的佈局,注意,這裏並無覆蓋上一種size class咱們定義好了得佈局,知識針對當前的size class添加新的、獨立的佈局信息,狡兔三窟,Xcode6這下子一口氣給了咱們九個窟窿,爽!

 

今後愛上iOS Autolayout

時間 2014-09-06 19:13:01  segmentfault-博客

原文  http://blog.segmentfault.com/ilikewhite/1190000000646452

主題 iOS開發

這篇不是autolayout教程,只是autolayout動員文章和經驗之談,在本文第五節友情連接和推薦中,我將附上足夠你們熟練使用autolayout的教程。這篇文章兩個月前就想寫下來,但由於一直工做較多,沒有時間來完成。今天終於狠下心,丟下代碼不寫,來完成他吧!

1、別和我提Autolayout,我想死!!

從iOS6/xcode4開始,蘋果開始提供了autolayout——一種對不一樣屏幕尺寸有更好兼容的自動佈局機制,但我相信大多數人在剛接觸autolayout時,必定和我同樣,幾乎快被其折磨致死!

autolayout由於佈局思路與傳統frame有所不一樣,國內關於autolayout的教程有過少,且autolayout在剛上手時靈活性不易掌控,致使你們更多選擇了放棄。

2、爲啥我要用autolayout?

隨着3.5寸/4寸iPhone在市面同時使用愈來愈多,以及即將上市的iPhone六、iPhone6L,不一樣尺寸、不一樣分辨率的iOS設備將會愈來愈多,使用傳統frame佈局的工做量必將愈來愈大;加上蘋果發出的信號,使用autolayout勢在必行。

好了,我該來表揚表揚autolayout了,它到底能解決什麼問題,給咱們帶來哪些好處?


1)你基本上能夠不用考慮3.5寸和4寸以及即將上市的x.x寸屏幕不一樣分辨率的問題,你終於能夠不用在viewDidLoad方法裏判斷不一樣分辨率下,不一樣控件應該放在哪裏,或者針對不一樣分辨率寫不一樣的storyboard和xib;

2)你能夠拋棄那些根據不一樣文字來計算tableViewCell、UILabel高度的代碼了,由於autolayout會幫你自動計算好;

3)若是你的佈局在橫屏豎屏下變化不是特別大,你不用再爲橫着豎着寫兩套代碼或者寫兩個storyboard/xib了;


再看看蘋果的態度,默認就是選擇了使用autolayout。雖然我如今仍有時會罵autolayout,但我仍然會堅定地選擇走上這條道路。

3、Autolayout之折騰二三事

剛剛表揚完autolayout,那我得爲和我同樣,願意選擇走上這條道的同志們提點醒了,你究竟要作好哪些折騰的準備。

3.1.佈局思惟的轉變

傳統佈局思路中,一個view在哪裏有多大,那就寫清楚它的座標位置和寬高就定了,平時用CGRect和CGPoint這兩種模型就足夠了,並且它必定很是聽你的話,寫的是多少,它絕對就是多少;可是autolayout的思路卻變化了,或者說改進了,它囊括了傳統frame佈局思路,除了能夠告訴view的座標和寬高,它更提供了一種相對的概念,好比:

1)view相對於屏幕視圖左邊5點,右邊10點,上面15點,下面20點,若是屏幕的長寬比例發生了改變(好比從3.5寸的320:480變成了4寸的320:568,或者從橫屏切換到了豎屏),view仍然會隨着屏幕的比例而拉伸改變,仍然保持離屏幕視圖左邊5點,右邊10點,上面15點,下面20點;

2)view1和view2之間相距10點,當屏幕尺寸發生改變或者旋轉時,他倆仍然能夠經過改變自身的尺寸或位置改變來保證它們中間就是相距10點;

3)...

因此,使用autolayout的第一步是你須要考慮它相對於superView或者brotherView的上下左右的距離,改變本身佈局的思惟。

3.2.使用autolayout可能會常常獲得本身不想看到的樣子,並且你改變frame還沒用

frame時代,是你寫的多少位置點就是多少位置點,view不會被自動的拉伸或者改變位置,可是autolayout中的view卻會根據屏幕長寬比或者其餘view的改變而改變,你常常就會看到被自動佈局成了不是你想的樣子,這也是太多人被折磨的緣由。只要你考慮的相對的位置不正確,它真的就可能會亂掉。

3.3.autolayout的VFL(Visual Format Language)語法初看起來真蛋疼

好吧,既然使用了autolayout,使用frame來改變位置不起做用了,那我也用代碼來完成autolayout總行了吧。可是,讓我選一段最普通的VFL代碼給你看看:

NSString *vfl = @"V:|-5-[_view]-10-[_p_w_picpathView(20)]-10-[_backBtn]-5-|";

納尼?!這是什麼地幹活?!我又要付出學習成本了啊!!!其實這段話就是說,在垂直方向從上到下,view離父視圖5點,p_w_picpathView距離view 10點,同時p_w_picpathView是20點高,backBtn離p_w_picpathView底部10點,距離父視圖底部5點。

3.4.手動Constraint書寫,那個長長長啊~~

固然,你還能夠一個一個的寫佈局約束Constraint,就和frame分別指定origin和size相似,可是卻像這樣:

[self.view addConstraint: [NSLayoutConstraint constraintWithItem:blueView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:redView
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0]];

而上文中的「view離父視圖5點,p_w_picpathView距離view 10點,同時p_w_picpathView是20點高,backBtn離p_w_picpathView底部10點,距離父視圖底部5點」每個逗號短句都是像這樣的一個constraint。

4、你是否是已經準備放棄了?NO!說好的愛上Autolayout呢!

寫到這裏,我突然以爲我是在黑autolayout了,不,看個人題目,我是真的已經愛上使用autolayout了。就讓我來講說應該怎麼使用autolayout。

4.1.autolayout通常應用步驟和最適宜場景

當你的頁面不會變動總體佈局和設計,只有在不一樣屏幕尺寸、不一樣文字和內容下有適應性的變化,那這種狀況使用autolayout就再適宜不過了。不會在像frame的時代,苦逼的要爲不一樣屏幕尺寸計算各自的位置點座標和大小了。一般使用xcode->Editor->Pin/Align菜單爲視圖添加約束便可。通常經過InterfaceBuilder肯定控件位置,當存在須要自動被拉伸、適應或位移的控件時就要添加constraint;具體使用教程可參考  《開始iOS 7中自動佈局教程1》

4.2.你的視圖有比較簡單的佈局改變

當須要產生動畫或動態添加視圖時,autolayout就暴露了出我認爲讓人抓狂的元兇——優先級(Priority)和佈局衝突。autolayout對於相同方位的約束,如都是描述離superview上邊緣距離的約束,若是這兩個約束的數值不一樣,可是優先級同樣,則autolayout將報佈局衝突,將會根據其計算丟棄某一條約束(這時可能就會丟棄你想要的約束,而偏偏保留了你不想看到的佈局)。因此,當咱們發生佈局變化時,沒法像frame的絕對定位,直接改變,而且只有惟一的位置信息。那麼,咱們該怎麼處理這種佈局衝突呢?那就是讓描述相同但數值不一樣的這兩個約束採用不一樣的優先級。autolayout默認將使用數值較大的優先級約束。

可是當咱們新增了一個更高優先級約束改變了視圖佈局,在完成一些操做後,又想變回去怎麼辦?這時就必須刪除更高優先級的約束。

因此,對於視圖有動態變動時,個人一般作法是:爲須要變動的控件新增默認constraint,但對於這個默認constraint先下降優先級,在發生變化時再新增一個更高優先級的constraint2,且代碼中用一個Dictionary緩存該constraint2的對象,便於我隨時刪除或從新新增,讓視圖來回變化。

4.3.你的視圖有較爲複雜的動畫效果或者較大的佈局改變

雖然autolayout能夠完成全部的佈局問題,但它仍然在某些狀況下是不方便的,就像4.2節描述的,每次改變你必須新增或刪除一個不一樣優先級的constraint,單說構造constraint對象的工做就夠嗆了,還可能必須緩存該對象,便於以後清除。因此,當你須要很是頻繁的變動控件佈局,而且變動的位置是不肯定的(例如經過手勢拖動一個視圖到屏幕任意位置),那麼,我建議此視圖不要使用autolayout,而使用frame的所寫即所得的絕對定位方式更好,你只須要充分考慮各類屏幕適配,併爲其計算適合的座標點便可。同時,我還建議這種頻繁變動的視圖甚至不要InterfaceBuilder來繪製,最好直接代碼書寫,由於一旦你勾選了autolayout,那麼storyboard中的全部視圖都將autolayout。而當你須要變動視圖佈局時,則必須使用

view.translatesAutoresizingMaskIntoConstraints = NO;superview.translatesAutoresizingMaskIntoConstraints = NO;

來避免爲你的視圖新增默認autolayout約束。

5、友情連接和推薦

1.  《開始iOS 7中自動佈局教程1》

這個教程看完基本上能夠比較熟悉的使用autolayout,再結合本文的一些經驗,應該可以解決大部分問題了。而該文的教程2沒有中文翻譯,只有英文原版:  《Beginning Auto Layout Tutorial in iOS 7: Part 2》

2.  《Autolayout及VFL經驗分享》

這篇文章以較簡單的描述囊括了VFL使用方法和經常使用的autolayout技巧。足夠你們使用了。

3.  《AutoLayout(自動佈局)入門》

這篇文章精簡的囊括了autolayout的代碼操做方

這篇不是autolayout教程,只是autolayout動員文章和經驗之談,在本文第五節友情連接和推薦中,我將附上足夠你們熟練使用autolayout的教程。這篇文章兩個月前就想寫下來,但由於一直工做較多,沒有時間來完成。今天終於狠下心,丟下代碼不寫,來完成他吧!

1、別和我提Autolayout,我想死!!

從iOS6/xcode4開始,蘋果開始提供了autolayout——一種對不一樣屏幕尺寸有更好兼容的自動佈局機制,但我相信大多數人在剛接觸autolayout時,必定和我同樣,幾乎快被其折磨致死!

autolayout由於佈局思路與傳統frame有所不一樣,國內關於autolayout的教程有過少,且autolayout在剛上手時靈活性不易掌控,致使你們更多選擇了放棄。

2、爲啥我要用autolayout?

隨着3.5寸/4寸iPhone在市面同時使用愈來愈多,以及即將上市的iPhone六、iPhone6L,不一樣尺寸、不一樣分辨率的iOS設備將會愈來愈多,使用傳統frame佈局的工做量必將愈來愈大;加上蘋果發出的信號,使用autolayout勢在必行。

好了,我該來表揚表揚autolayout了,它到底能解決什麼問題,給咱們帶來哪些好處?


1)你基本上能夠不用考慮3.5寸和4寸以及即將上市的x.x寸屏幕不一樣分辨率的問題,你終於能夠不用在viewDidLoad方法裏判斷不一樣分辨率下,不一樣控件應該放在哪裏,或者針對不一樣分辨率寫不一樣的storyboard和xib;

2)你能夠拋棄那些根據不一樣文字來計算tableViewCell、UILabel高度的代碼了,由於autolayout會幫你自動計算好;

3)若是你的佈局在橫屏豎屏下變化不是特別大,你不用再爲橫着豎着寫兩套代碼或者寫兩個storyboard/xib了;


再看看蘋果的態度,默認就是選擇了使用autolayout。雖然我如今仍有時會罵autolayout,但我仍然會堅定地選擇走上這條道路。

3、Autolayout之折騰二三事

剛剛表揚完autolayout,那我得爲和我同樣,願意選擇走上這條道的同志們提點醒了,你究竟要作好哪些折騰的準備。

3.1.佈局思惟的轉變

傳統佈局思路中,一個view在哪裏有多大,那就寫清楚它的座標位置和寬高就定了,平時用CGRect和CGPoint這兩種模型就足夠了,並且它必定很是聽你的話,寫的是多少,它絕對就是多少;可是autolayout的思路卻變化了,或者說改進了,它囊括了傳統frame佈局思路,除了能夠告訴view的座標和寬高,它更提供了一種相對的概念,好比:

1)view相對於屏幕視圖左邊5點,右邊10點,上面15點,下面20點,若是屏幕的長寬比例發生了改變(好比從3.5寸的320:480變成了4寸的320:568,或者從橫屏切換到了豎屏),view仍然會隨着屏幕的比例而拉伸改變,仍然保持離屏幕視圖左邊5點,右邊10點,上面15點,下面20點;

2)view1和view2之間相距10點,當屏幕尺寸發生改變或者旋轉時,他倆仍然能夠經過改變自身的尺寸或位置改變來保證它們中間就是相距10點;

3)...

因此,使用autolayout的第一步是你須要考慮它相對於superView或者brotherView的上下左右的距離,改變本身佈局的思惟。

3.2.使用autolayout可能會常常獲得本身不想看到的樣子,並且你改變frame還沒用

frame時代,是你寫的多少位置點就是多少位置點,view不會被自動的拉伸或者改變位置,可是autolayout中的view卻會根據屏幕長寬比或者其餘view的改變而改變,你常常就會看到被自動佈局成了不是你想的樣子,這也是太多人被折磨的緣由。只要你考慮的相對的位置不正確,它真的就可能會亂掉。

3.3.autolayout的VFL(Visual Format Language)語法初看起來真蛋疼

好吧,既然使用了autolayout,使用frame來改變位置不起做用了,那我也用代碼來完成autolayout總行了吧。可是,讓我選一段最普通的VFL代碼給你看看:

NSString *vfl = @"V:|-5-[_view]-10-[_p_w_picpathView(20)]-10-[_backBtn]-5-|";

納尼?!這是什麼地幹活?!我又要付出學習成本了啊!!!其實這段話就是說,在垂直方向從上到下,view離父視圖5點,p_w_picpathView距離view 10點,同時p_w_picpathView是20點高,backBtn離p_w_picpathView底部10點,距離父視圖底部5點。

3.4.手動Constraint書寫,那個長長長啊~~

固然,你還能夠一個一個的寫佈局約束Constraint,就和frame分別指定origin和size相似,可是卻像這樣:

[self.view addConstraint: [NSLayoutConstraint constraintWithItem:blueView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:redView
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0]];

而上文中的「view離父視圖5點,p_w_picpathView距離view 10點,同時p_w_picpathView是20點高,backBtn離p_w_picpathView底部10點,距離父視圖底部5點」每個逗號短句都是像這樣的一個constraint。

4、你是否是已經準備放棄了?NO!說好的愛上Autolayout呢!

寫到這裏,我突然以爲我是在黑autolayout了,不,看個人題目,我是真的已經愛上使用autolayout了。就讓我來講說應該怎麼使用autolayout。

4.1.autolayout通常應用步驟和最適宜場景

當你的頁面不會變動總體佈局和設計,只有在不一樣屏幕尺寸、不一樣文字和內容下有適應性的變化,那這種狀況使用autolayout就再適宜不過了。不會在像frame的時代,苦逼的要爲不一樣屏幕尺寸計算各自的位置點座標和大小了。一般使用xcode->Editor->Pin/Align菜單爲視圖添加約束便可。通常經過InterfaceBuilder肯定控件位置,當存在須要自動被拉伸、適應或位移的控件時就要添加constraint;具體使用教程可參考  《開始iOS 7中自動佈局教程1》

4.2.你的視圖有比較簡單的佈局改變

當須要產生動畫或動態添加視圖時,autolayout就暴露了出我認爲讓人抓狂的元兇——優先級(Priority)和佈局衝突。autolayout對於相同方位的約束,如都是描述離superview上邊緣距離的約束,若是這兩個約束的數值不一樣,可是優先級同樣,則autolayout將報佈局衝突,將會根據其計算丟棄某一條約束(這時可能就會丟棄你想要的約束,而偏偏保留了你不想看到的佈局)。因此,當咱們發生佈局變化時,沒法像frame的絕對定位,直接改變,而且只有惟一的位置信息。那麼,咱們該怎麼處理這種佈局衝突呢?那就是讓描述相同但數值不一樣的這兩個約束採用不一樣的優先級。autolayout默認將使用數值較大的優先級約束。

可是當咱們新增了一個更高優先級約束改變了視圖佈局,在完成一些操做後,又想變回去怎麼辦?這時就必須刪除更高優先級的約束。

因此,對於視圖有動態變動時,個人一般作法是:爲須要變動的控件新增默認constraint,但對於這個默認constraint先下降優先級,在發生變化時再新增一個更高優先級的constraint2,且代碼中用一個Dictionary緩存該constraint2的對象,便於我隨時刪除或從新新增,讓視圖來回變化。

4.3.你的視圖有較爲複雜的動畫效果或者較大的佈局改變

雖然autolayout能夠完成全部的佈局問題,但它仍然在某些狀況下是不方便的,就像4.2節描述的,每次改變你必須新增或刪除一個不一樣優先級的constraint,單說構造constraint對象的工做就夠嗆了,還可能必須緩存該對象,便於以後清除。因此,當你須要很是頻繁的變動控件佈局,而且變動的位置是不肯定的(例如經過手勢拖動一個視圖到屏幕任意位置),那麼,我建議此視圖不要使用autolayout,而使用frame的所寫即所得的絕對定位方式更好,你只須要充分考慮各類屏幕適配,併爲其計算適合的座標點便可。同時,我還建議這種頻繁變動的視圖甚至不要InterfaceBuilder來繪製,最好直接代碼書寫,由於一旦你勾選了autolayout,那麼storyboard中的全部視圖都將autolayout。而當你須要變動視圖佈局時,則必須使用

view.translatesAutoresizingMaskIntoConstraints = NO;superview.translatesAutoresizingMaskIntoConstraints = NO;

來避免爲你的視圖新增默認autolayout約束。

5、友情連接和推薦

1.  《開始iOS 7中自動佈局教程1》

這個教程看完基本上能夠比較熟悉的使用autolayout,再結合本文的一些經驗,應該可以解決大部分問題了。而該文的教程2沒有中文翻譯,只有英文原版:  《Beginning Auto Layout Tutorial in iOS 7: Part 2》

2.  《Autolayout及VFL經驗分享》

這篇文章以較簡單的描述囊括了VFL使用方法和經常使用的autolayout技巧。足夠你們使用了。

3.  《AutoLayout(自動佈局)入門》

這篇文章精簡的囊括了autolayout的代碼操做方式。

若是在通讀了本文和以上連接後還沒法靈活運用autolayout,歡迎給我留言,你們一塊兒討論!同時歡迎關注個人博客  http://www.ilikewhite.com 和微博 http://weibo.com/ilikewhite

相關文章
相關標籤/搜索