(iOS)autolayoutを使用した複雑なレイアウト時のUILabel関連trick
6910 ワード
本論文はCSDNに先発する:http://blog.csdn.net/madongchunqiu/article/details/47960745.
せっかちな同級生にまず結論を言います:(私もせっかちな同級生だから) UILabelの場合、number of linesを設定することは、縦方向のconstraintを設定することに相当する.すなわち,UILabelは3つのconstraintを設定すれば である. UILabelに対して、横方向に1つの"<="のconstraintを設置し、UILabel自身に幅 を適応させることができる.文章の終わりに試験問題がありますよ.挑戦が好きな人は を見てください.
一、本文:
まず気持ちを一つ.
1つ目のプロジェクトは純ハンドコードで、MRCであり、サードパーティ製ライブラリはほとんど使用されていません.一日中紙の上でレイアウトの座標を計算して、各種の大きさはすべて比例によってリアルタイムに計算しました.欠点は明らかで、レイアウトのコードが多すぎて、論理部分のコードを絞ってしまった.メリットは、私は超制御性を感じて、ほとんど予想外のバグがなくて、アップルの更新バージョンがappの使用に影響を与えることを恐れません.(注:最新バージョンではstoryboardを使用してインタフェースを切り替え、ほとんどのレイアウトはハンドコードです)
2番目のプロジェクトは膨大すぎて、Storyboard+auto layout、ARC、4桁のスターを使用して、活発なサードパーティライブラリを維持しています.デザイナーのUIのコントロールは超精細で、auto layoutは本当に私をインタフェースのレイアウトから解放しました.しかし、最初は「横2つのconstraint+縦2つのconstraint」を使用していたが、現在は主に「UItableView-DTemplateLayoutCell」を使用している(https://github.com/forkingdog/UITableView-FDTemplateLayoutCell)tableviewcellのレイアウトを行うには、まだ議論と学習に値するところがあります.
二、討論対象:
以下では、シーンがUItableViewCellを使用してレイアウトされていると仮定し、UItableViewCellにはLabel/Image/Buttonなどの複雑なレイアウトがいくつかあります.一般的に、ImageとButtonの大きさは変わらないか、Cellと比例関係を保っているので、扱いやすい.Labelは文字の長さ、フォントの大きさの変化によって、幅と高さの変化を招き、計算上の面倒をもたらす可能性があります.
三、設置方法
(以下の2つの方法はそれぞれ運用シーンがある)
1:基本金
「横2つのconstraint+縦2つのconstraint」という方法で、pointの各インタフェース要素の位置とサイズを正確に制御します.次の図を示します.
上図はLabelにTop,Left,Righ,Heightの4つの属性を設定し,Labelのサイズを完全に制御できる.
ただし、Labelで表示する必要があるコンテンツが複数行を占有する可能性がある場合はnumber of linesを0(タイトルが2列まで表示される場合は2)に設定し、HeightというconstraintをIB Outletとして引き出し、次の図のようにプログラムで随時変更できます.
文字の長さとcellの幅はLabelのレイアウトに影響し、cellの高さを決定するため、heightForCellAtIndexPath:の戻り値は計算する必要があります.このcellでは、2つの関数が実装されます.
前者のclass methodはheightForCellAtIndexPath:によって呼び出され、cellのインスタンス化を回避します.呼び出し
labelの高さを計算し、cell全体の高さを合成します.
後者のinstance methodはcellForRowAtIndexPath:によって呼び出され、cellの各コントロールパラメータをインスタンス化し、上のコードの計算結果をconstraintのIB Outletに付与する.
利点:計算が迅速で効率が高く、制御が正確である.
欠点:IBで設定されたgap,marginなどの数値はcellHeightWithDataという関数で使用されるhardcodeの数値と一致する必要があり、1つのデータの両方を維持することは、まったく我慢できません.また、Labelのフォントサイズが変更された場合は、再設定が必要になる場合があり、不便です.
2.適応金
constraintの「ratio」、「multiply」、「>=」、「<=」などの設定を利用してauto layoutの自動レイアウトを完了します.
この設定は前の設定でHeightというconstraintを削除したもので、この場合number of linesが4番目のconstraintとして機能し、auto layoutをレイアウトできると理解できる.案の定、auto layoutはレイアウトと実行後が一致しない(実行後にauto layoutに正しい位置に置かれた)とヒントを与えた.このwarningはauto layoutがこのlabelを正しくhandleできることを教えてくれる一方で、「Update Frame」という方法でLabelを正しく置くべきだと教えてくれます.
別のケースでは、labelが横方向の領域全体を満たすことができない場合があります.その後、図のように、「<=」constraintを設定して自動的にレイアウトするコントロールがある場合があります.
前述の「UItableView-DTemplateLayoutCell」(https://github.com/forkingdog/UITableView-FDTemplateLayoutCell)、レイアウトなどについてのすべてのmargin、gapなどは、IBでしかできません.constraintをoutletとして手動で設定する必要はほとんどありません.cellが実装する必要がある関数は、次のとおりです.
この関数は、heightForRowAtIndexPath:およびcellForRowAtIndexPath:で呼び出されます.【具体的にはUITableView-DTemplateLayoutCellのドキュメントとソースコードを参照してください】
利点:レイアウトはすべてIBで、コードの中でほとんど管理しないことができます
欠点:heightForRowAtIndexPathではcellをインスタンス化し、レイアウト計算を行う必要があるため、効率はやや低下します(もちろん、最適化方法もあります)
四、シーンの使用
(以下のタイトルはuitableviewにおける各cellのレイアウトの難しさを説明する)
A.均一な高さ
hardcodeさん、いいですね.
(欠図)
B.計算しやすい高さ
例えば高さと幅の割合が16:9でclass methodを使って計算してみるといいでしょう.
(欠図)
C.複雑なレイアウト+効率を考慮する必要がない
UITableView-FDTemplateLayoutCellを使いましょう
(欠図)
D.複雑なレイアウト+効率優先
特別な事情が必要である
(欠くことなく)
五、練習問題
i)あるリストはtableviewによって実現され、各cellには多くの情報があり、その中でTitleは長くても短くてもよく、短いのは1行を表示し、長いのは最大2行を表示する.タイトルの横にDateが表示されます.次の4つのケースがあります.
ケース1:見出しが1行を占め、右側に日付を配置できる場合、見出しと日付は同じ行に配置されます.
|——————————————————|
| Title Short Date |
| (Others) |
ケース2:見出しが1行を占めるが、1行目は日付を収容できず、日付が2行目に置かれる
|——————————————————|
| Title Ratherrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr Long |
| Date |
| (Others) |
ケース3:タイトルは2行で、2行目は右側で日付を防ぐことができ、日付は2行目に置く
|——————————————————|
| Title Verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr |
| rrrrrrrrrrrrrrrry Long Date |
| (Others) |
ケース4:タイトルが2行を占めるが、2行目に日付が収まらない場合、日付は2行目、タイトルTrunk Tail、表示
|——————————————————|
| Title Terrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr |
| rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrriblely … Date |
|(Others)|ii)もっと練習問題...
せっかちな同級生にまず結論を言います:(私もせっかちな同級生だから)
一、本文:
まず気持ちを一つ.
1つ目のプロジェクトは純ハンドコードで、MRCであり、サードパーティ製ライブラリはほとんど使用されていません.一日中紙の上でレイアウトの座標を計算して、各種の大きさはすべて比例によってリアルタイムに計算しました.欠点は明らかで、レイアウトのコードが多すぎて、論理部分のコードを絞ってしまった.メリットは、私は超制御性を感じて、ほとんど予想外のバグがなくて、アップルの更新バージョンがappの使用に影響を与えることを恐れません.(注:最新バージョンではstoryboardを使用してインタフェースを切り替え、ほとんどのレイアウトはハンドコードです)
2番目のプロジェクトは膨大すぎて、Storyboard+auto layout、ARC、4桁のスターを使用して、活発なサードパーティライブラリを維持しています.デザイナーのUIのコントロールは超精細で、auto layoutは本当に私をインタフェースのレイアウトから解放しました.しかし、最初は「横2つのconstraint+縦2つのconstraint」を使用していたが、現在は主に「UItableView-DTemplateLayoutCell」を使用している(https://github.com/forkingdog/UITableView-FDTemplateLayoutCell)tableviewcellのレイアウトを行うには、まだ議論と学習に値するところがあります.
二、討論対象:
以下では、シーンがUItableViewCellを使用してレイアウトされていると仮定し、UItableViewCellにはLabel/Image/Buttonなどの複雑なレイアウトがいくつかあります.一般的に、ImageとButtonの大きさは変わらないか、Cellと比例関係を保っているので、扱いやすい.Labelは文字の長さ、フォントの大きさの変化によって、幅と高さの変化を招き、計算上の面倒をもたらす可能性があります.
三、設置方法
(以下の2つの方法はそれぞれ運用シーンがある)
1:基本金
「横2つのconstraint+縦2つのconstraint」という方法で、pointの各インタフェース要素の位置とサイズを正確に制御します.次の図を示します.
上図はLabelにTop,Left,Righ,Heightの4つの属性を設定し,Labelのサイズを完全に制御できる.
ただし、Labelで表示する必要があるコンテンツが複数行を占有する可能性がある場合はnumber of linesを0(タイトルが2列まで表示される場合は2)に設定し、HeightというconstraintをIB Outletとして引き出し、次の図のようにプログラムで随時変更できます.
文字の長さとcellの幅はLabelのレイアウトに影響し、cellの高さを決定するため、heightForCellAtIndexPath:の戻り値は計算する必要があります.このcellでは、2つの関数が実装されます.
+ (CGFloat)cellHeightWithData:(MDDataType*)data withCellWidth:(CGFloat)cellWidth;
- (void)updateWithData:(MDDataType*)data;
前者のclass methodはheightForCellAtIndexPath:によって呼び出され、cellのインスタンス化を回避します.呼び出し
[label.text boundingRectWithSize:CGSizeMake(cellWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label.font} context:nil].size.height
labelの高さを計算し、cell全体の高さを合成します.
後者のinstance methodはcellForRowAtIndexPath:によって呼び出され、cellの各コントロールパラメータをインスタンス化し、上のコードの計算結果をconstraintのIB Outletに付与する.
利点:計算が迅速で効率が高く、制御が正確である.
欠点:IBで設定されたgap,marginなどの数値はcellHeightWithDataという関数で使用されるhardcodeの数値と一致する必要があり、1つのデータの両方を維持することは、まったく我慢できません.また、Labelのフォントサイズが変更された場合は、再設定が必要になる場合があり、不便です.
2.適応金
constraintの「ratio」、「multiply」、「>=」、「<=」などの設定を利用してauto layoutの自動レイアウトを完了します.
この設定は前の設定でHeightというconstraintを削除したもので、この場合number of linesが4番目のconstraintとして機能し、auto layoutをレイアウトできると理解できる.案の定、auto layoutはレイアウトと実行後が一致しない(実行後にauto layoutに正しい位置に置かれた)とヒントを与えた.このwarningはauto layoutがこのlabelを正しくhandleできることを教えてくれる一方で、「Update Frame」という方法でLabelを正しく置くべきだと教えてくれます.
別のケースでは、labelが横方向の領域全体を満たすことができない場合があります.その後、図のように、「<=」constraintを設定して自動的にレイアウトするコントロールがある場合があります.
前述の「UItableView-DTemplateLayoutCell」(https://github.com/forkingdog/UITableView-FDTemplateLayoutCell)、レイアウトなどについてのすべてのmargin、gapなどは、IBでしかできません.constraintをoutletとして手動で設定する必要はほとんどありません.cellが実装する必要がある関数は、次のとおりです.
- (void)updateWithData:(MDDataType*)data;
この関数は、heightForRowAtIndexPath:およびcellForRowAtIndexPath:で呼び出されます.【具体的にはUITableView-DTemplateLayoutCellのドキュメントとソースコードを参照してください】
利点:レイアウトはすべてIBで、コードの中でほとんど管理しないことができます
欠点:heightForRowAtIndexPathではcellをインスタンス化し、レイアウト計算を行う必要があるため、効率はやや低下します(もちろん、最適化方法もあります)
四、シーンの使用
(以下のタイトルはuitableviewにおける各cellのレイアウトの難しさを説明する)
A.均一な高さ
hardcodeさん、いいですね.
(欠図)
B.計算しやすい高さ
例えば高さと幅の割合が16:9でclass methodを使って計算してみるといいでしょう.
+ (CGFloat)cellHeightWithData:(MDDataType*)data withCellWidth:(CGFloat)cellWidth;
(欠図)
C.複雑なレイアウト+効率を考慮する必要がない
UITableView-FDTemplateLayoutCellを使いましょう
(欠図)
D.複雑なレイアウト+効率優先
特別な事情が必要である
(欠くことなく)
五、練習問題
i)あるリストはtableviewによって実現され、各cellには多くの情報があり、その中でTitleは長くても短くてもよく、短いのは1行を表示し、長いのは最大2行を表示する.タイトルの横にDateが表示されます.次の4つのケースがあります.
ケース1:見出しが1行を占め、右側に日付を配置できる場合、見出しと日付は同じ行に配置されます.
|——————————————————|
| Title Short Date |
| (Others) |
ケース2:見出しが1行を占めるが、1行目は日付を収容できず、日付が2行目に置かれる
|——————————————————|
| Title Ratherrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr Long |
| Date |
| (Others) |
ケース3:タイトルは2行で、2行目は右側で日付を防ぐことができ、日付は2行目に置く
|——————————————————|
| Title Verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr |
| rrrrrrrrrrrrrrrry Long Date |
| (Others) |
ケース4:タイトルが2行を占めるが、2行目に日付が収まらない場合、日付は2行目、タイトルTrunk Tail、表示
|——————————————————|
| Title Terrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr |
| rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrriblely … Date |
|(Others)|ii)もっと練習問題...