AsyncDisplayKit 2.0テクスチャチュヌトリアル自動レむアりト


AsyncDisplayKitテクスチャ蚘事シリヌズの第2郚ぞようこそ


AsyncDisplayKitビルドシステムを䜿甚するず、非垞に高速な宣蚀型コヌドを蚘述できたす。


クむック蚭定に加えお、アプリケヌションが実行されおいるデバむスに自動的に適応したす。 アプリケヌションのView Controllerで、たたはiPad甚アプリケヌションのポップオヌバヌずしお䜿甚できるノヌドを䜜成しようずしおいるずしたす。 レむアりトが正しく䜜成されおいれば、レむアりトの基本コヌドを倉曎するこずを心配せずにノヌドをこの新しい環境に転送できたす



このAsyncDisplayKit 2.0チュヌトリアルでは、 最初の郚分からCardNodeクラスに戻り、䜜成に䜿甚されたレむアりト仕様に぀いお孊習したす。 レむアりト仕様を䜜成しお、目的の結果を埗るこずがどれほど簡単かがわかりたす。


自動レむアりトの問題


「自動レむアりトの䜕が問題なのですか」ず叫んでいるのが聞こえたす。自動レむアりトでは、䜜成した各コストラむンは、連立方皋匏の方皋匏ずしお衚瀺されたす。 これは、定数を远加するたびに、定数を指数関数的に蚈算する時間が長くなるこずを意味したす。 この蚈算は垞にメむンスレッドで実行されたす。


ASDK蚭蚈の目暙の1぀は、UIKit APIに可胜な限り忠実に埓うこずです。 残念ながら、自動レむアりトは䞍透明なシステムであり、別のスレッドでconstを蚈算する方法はありたせん。


さあ始めたしょう


開始するには、 ここからスタヌタヌプロゞェクトをダりンロヌドしたす 。 レむアりトの仕様の䞀郚を孊習するので、最初のAsyncDisplayKit 2.0チュヌトリアルの完成品の修正版から始める䟡倀がありたす。


泚 AsyncDisplayKit 2.0チュヌトリアルで䜜業を開始する前に、 最初のパヌトをお読みください。

ASLayoutSpecの玹介


始める前に、少し背景を説明したす。


レむアりト仕様は、レむアりトシステムを䞀般化したものです。これに぀いおは、 Building Paper Eventで簡単に説明しおいたす。 アむデアは、ノヌドずサブノヌドの次元ず䜍眮の蚈算ず適甚を統䞀し、それらを再利甚できるようにするこずです。


ASDK 1.9.Xでは、非同期レむアりトを䜜成できたしたが、レむアりトコヌドはUIKitの事前自動レむアりトに䌌おいたした 。 ノヌドサブノヌドのサむズは、 -calculateSizeThatFitsメ゜ッドを䜿甚しお蚈算できたす。 これらのサむズをキャッシュし、埌で-layoutに远加できたす。 たた、ノヌドの䜍眮は、叀き良き数孊を䜿甚しお蚈算する必芁がありたした-誰も数孊を台無しにしたくない



レむアりト仕様


ASDK 2.0では、ASDisplayNodeのサブクラスは-layoutSpecThatFitsを実装できたす。 クラスオブゞェクトASLayoutSpecは、すべおのサブノヌドのサむズず䜍眮を決定したす。 レむアりト仕様は、芪ノヌドのサむズも決定したす。


ノヌドは、 -layoutSpecThatFitsからレむアりト仕様オブゞェクトを返したす。 このオブゞェクトは、ノヌドのサむズ、およびそのすべおのサブノヌドのサむズず䜍眮を再垰的に決定したす。


ThatFits匕数は、クラスASSizeRangeのオブゞェクトです。 これには、ノヌドの最小サむズず最倧サむズを決定するCGSize型の2぀のプロパティ最小ず最倧がありたす。


ASDKはさたざたな皮類の仕様を提䟛したす。 それらのいく぀かを次に瀺したす。



ASLayoutElementプロトコル


レむアりト仕様は、1぀以䞊の子のレむアりトを制埡したす。 芁玠は、 ASTextNodeやASImageNodeなどのノヌドにするこずができたす。 ノヌドに加えお、子レむアりト仕様テンプレヌトも異なるレむアりト仕様になる堎合がありたす。


ねえ、どうやっおそれが可胜ですか


レむアりト仕様の子芁玠は、 ASLayoutElementプロトコルに準拠する必芁がありたす。 ASLayoutSpecずASDisplayNodeはASLayoutElementに察応しおいるため、型ずそのサブクラスの䞡方を子にするこずができたす。



このシンプルなコンセプトは非垞に匷力です。 最も重芁なレむアりト機胜の1぀はASStackLayoutSpecです。 画像ずテキストを配眮する機胜は1぀ですが、画像ず別のスタックを配眮する機胜は別です。


あなたは絶察に正しいです。 決闘の時が来たした ぀たり、コヌドを曞く...



動物の画像を配眮する


ですから、あなたは仕事をしおいお、デザむナヌはあなたが取り組んでいる新しいアプリケヌション「動物のための癟科事兞」のために圌が望むもののスクリヌンショットを送っおきたした。



最初に行うこずは、党䜓的なレむアりトを理解するために、画面を適切なレむアりト仕様に分割するこずです。 これは時には混乱を招く可胜性がありたすが、レむアりトの嚁力は配眮の容易さに䟝存するこずを忘れないでください。 シンプルに始めたしょう。


今埌は、䞊半分ず䞋半分が䞀緒にスタック䞊で完党に機胜するず蚀えたす。 これがわかったので、2぀の半分を別々に配眮しお、最埌に結合できたす。


スタヌタヌプロゞェクトを解凍し、 RainforestStarter.xcworkspaceを開きたす。 CardNode.mの-layoutSpecThatFitsメ゜ッドに移動したす。 珟圚は、空のASLayoutSpecオブゞェクトを返すだけです。


プロゞェクトをコンパむルしお実行するず、次のように衚瀺されたす。



さお、これはほんの始たりです。 最初に動物の画像を衚瀺しおみおはどうですか


デフォルトでは、ネットワヌクむメヌゞノヌドにはコンテンツがないため、独自のサむズがありたせん。 スクリヌンショットを芋るず、動物の画像は画面の幅党䜓ず高さの2/3を占める必芁があるず蚀えたす。


これを行うには、既存のreturnステヌトメントを次のステヌトメントに眮き換えたす。


//1 CGFloat ratio = constrainedSize.min.height/constrainedSize.min.width; //2 ASRatioLayoutSpec *imageRatioSpec = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:ratio child:self.animalImageNode]; //3 return imageRatioSpec; 

各番号のコメントを順番に怜蚎しおください。


  1. 比率の蚈算 最初に、画像に適甚する比率を決定したす。 比率は高さ/幅によっお決たりたす。 ここでは、この画像の高さが最小セルの高さ、぀たり画面の高さの2/3であるこずを瀺したす。
  2. 比率レむアりト仕様の䜜成 次に、蚈算された関係ず子animalImageNodeを䜿甚しお、新しいASRatioLayoutSpecを䜜成したす。
  3. 仕様を返す 返されるimageRatioSpecは、セルの高さず幅を決定したす。

コンパむルしお実行し、レむアりトがどのように芋えるかを確認したす。



ずおも簡単ですね。 画像はサむズを持぀唯䞀の芁玠であるため、セルはそれに合わせお䌞瞮したす。


泚 テヌブルノヌドセルに枡されるconstrainedSizeは、最小倀0、0ず最倧倀 tableNodeWidth、INF で構成されたす。 したがっお、 preferredFrameSizeを䜿甚しお画像の高さを決定する必芁がありたす。 preferredFrameSizeは、パヌト1でAnimalPagerControllerに蚭定されたした。

グラデヌションを远加


動物の画像ができたので、次のステップは、グラデヌションノヌドをその䞊に远加するこずです。


ASOverlayLayoutSpecは、ゞョブの単なる仕様です。


imageRatioSpecを初期化した埌、最初に次の行を远加したす。


 ASOverlayLayoutSpec *gradientOverlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:imageRatioSpec overlay:self.gradientNode]; 

レむアりト仕様を䜜成するず、残りを含む仕様が垞に取埗されたす。 gradientOverlaySpecの時間です。


珟圚のリタヌンを次のものに眮き換えたす。


 return gradientOverlaySpec; 

コンパむルしお実行し、各imageNodeオブゞェクトに広がるグラデヌションを確認したす。


すべおの鳥の募配は玠晎らしいです



動物名のテキストを远加


あずは、動物の名前を远加するだけです。


タスクは簡単に思えたすが、考慮すべき芁件がいく぀かありたす。


  1. 名前はグラデヌションの䞊に配眮する必芁がありたす。
  2. 名前は動物の画像の巊䞋隅にある必芁がありたす。
  3. むンデント-巊に16ポむント、䞋に8ポむント。

テキストを䞀番䞊に配眮する方法はすでに知っおいたす。 実蚌枈みの真のオヌバヌレむ仕様から脱华する時が来たした。


gradientOverlaySpecの盎埌に次の行を远加したす


 ASOverlayLayoutSpec *nameOverlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:gradientOverlaySpec overlay:self.animalNameTextNode]; 

さらに、 returnステヌトメントを次のように倉曎する必芁がありたす。


 return nameOverlaySpec; 

アプリケヌションをコンパむルしお実行し、画面䞊のテキストを確認したす。



悪くない。 このテキストを䞋隅に移動するだけです。


あなたが遭遇する䞀般的なケヌスに蚀及する䟡倀がありたす。 あなたは鳥にテキストを持っおいるので、自然な欲求は、他の仕様でOverlaySpecをラップしお、 奜きな堎所に眮くこずです。 原則ずしお、䞀歩埌退しお、あなたが衚珟しようずしおいるこずに぀いお考える必芁がありたす。


この堎合、 nameOverlaySpecを䜿甚しお、既存のコンテンツの䞊にある他のものを拡匵したす。


実際、コンテンツのタむトルを拡匵したくありたせん。 空き領域の巊䞋隅にあるこずを名前に䌝え、このレむアりト仕様を利甚可胜な領域に拡匵したす。


ASRelativeLayoutSpecの玹介


実際にはASRelativeLayoutSpecが必芁です 。


ASRelativeLayoutSpecはASLayoutElement子を受け入れ、それが䜿甚可胜なスペヌスを考慮しお、指瀺に埓っおこの子を配眮したす。


盞察仕様を定矩するずき、プロパティverticalPositionおよびhorizo​​ntalPositionを蚭定できたす。


これらの2぀のプロパティは次のずおりです。



この組み合わせにより、オブゞェクトをコヌナヌ、゚ッゞのいずれか、たたは䜿甚可胜なスペヌスの䞭倮に配眮できたす。


挔習ずしお、このカ゚ルを空き領域の右端にどのように配眮したすか



「verticalPositionをASRelativeLayoutSpecPositionCenterに蚭定し、 horizo​​ntalPositionをASRelativeLayoutSpecPositionEndに蚭定」ず蚀った堎合、あなたは正しいです


緎習が終わったので、次の行はもう少し意味がありたす。 nameOverlaySpecの盎前に次の行を远加したす 。


 ASRelativeLayoutSpec *relativeSpec = [ASRelativeLayoutSpec relativePositionLayoutSpecWithHorizontalPosition:ASRelativeLayoutSpecPositionStart verticalPosition:ASRelativeLayoutSpecPositionEnd sizingOption:ASRelativeLayoutSpecSizingOptionDefault child:self.animalNameTextNode]; 

したがっお、子のhorizo​​ntalPositionをstartに、verticalPositionを完了に蚭定したす。 カ゚ルの蚀語では、次のようになりたす。



盞察仕様が蚭定されたので、 nameOverlaySpec定矩を次のように倉曎したす。


 ASOverlayLayoutSpec *nameOverlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:gradientOverlaySpec overlay:relativeSpec]; 

コンパむルしお実行し、埗られるものを確認したす。



いいね セルのこの半分で行うこずがもう1぀ありたす。


ASInsetLayoutSpecの玹介


最埌に行う必芁があるのは、動物の名前を16ポむント巊に、8ポむント䞋に眮くこずです。 これにはASInsetLayoutSpecがありたす。


オブゞェクトの呚囲に小さなむンデントを远加するには、挿入仕様でオブゞェクトをラップし、 UIEdgeInsetsに必芁なむンデントを決定させたす。


nameOverlaySpecの埌に次の行を远加したす。


 ASInsetLayoutSpec *nameInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(0, 16.0, 8.0, 0.0) child:nameOverlaySpec]; 

次に、最も倖偎の仕様を返すようにreturnステヌトメントを再床倉曎したす。


 return nameInsetSpec; 

コンパむルしお実行したす。




オヌバヌレむには動物の画像が含たれおいるため、オヌバヌレむが芆う領域党䜓に挿入を適甚したくない堎合がありたす。


本圓に必芁なのは、挿入をrelativeSpecスペヌスに適甚するこずです。 これを修正するには、たず珟圚のnameInsetSpec定矩を削陀したす。


次に、 nameOverlaySpec定矩の盎前に、次の新しい改良バヌゞョンを远加したす。


 ASInsetLayoutSpec *nameInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(0, 16.0, 8.0, 0.0) child:relativeSpec]; 

ここで、 relativeSpecではなくnameOverlaySpecが新しい挿入をオヌバヌレむする必芁がありたす。 nameOverlaySpecの定矩を次のように眮き換えたす。


 ASOverlayLayoutSpec *nameOverlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:gradientOverlaySpec overlay:nameInsetSpec]; 

最埌に、以䞋に戻りたす。


 return nameOverlaySpec; 

コンパむルしお実行し、䜕が起こったかを確認したす。



半分の䜜業が完了したした


䞋半分


埌半は少し簡単です。 これは、その呚りに挿入物がある動物の単なる説明です...そしおあなたはすでにそれを行う方法を知っおいたす。


return文の前に次の行を远加しお、説明テキストを含む挿入を䜜成したす。


 ASInsetLayoutSpec *descriptionTextInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(16.0, 28.0, 12.0, 28.0) child:self.animalDescriptionTextNode]; 

この挿入を返し、アプリケヌションをコンパむルしお起動するず、次のように衚瀺されたす。



これはたさにあなたが望んでいたものです。 䞡方の半分がわかったので、それらを組み合わせるのは難しくありたせん。


コンテンツの内郚寞法


テキストがスペヌスを埋めるためにコンテンツのサむズを持っおいるこずを心配する必芁はありたせん。 これは、 ASTextNodeがテキストず属性に基づいお独自の内郚コンテンツサむズを持っおいるためです。


次のノヌドにはデフォルトのサむズはありたせん。



䞀般的には、これらのノヌドには元のコンテンツがないため、独自のサむズを決定する方法はありたせん。 䜿甚する特定のサむズを蚭定する前に、 preferredFrameSizeを持぀か、レむアりト仕様に配眮する必芁がありたす。


ASStackLayoutSpecの玹介


これは、スタックレむアりト仕様を䜿甚するのに最適な時期です。 これはUIStackViewず同等のレむアりト仕様ずしおずらえるこずができたすが、自動埌方互換性は非垞に゚レガントです。


スタックは、垂盎ず氎平の䞡方で定矩できたす。 他のすべおの人ず同様に、レむアりト仕様はノヌドたたは他のマヌクアップを子ずしお受け入れるこずができたす。


このスタックを構成するには、挿入の説明を定矩した埌、次の3行を远加したす。


 ASStackLayoutSpec *verticalStackSpec = [[ASStackLayoutSpec alloc] init]; verticalStackSpec.direction = ASStackLayoutDirectionVertical; verticalStackSpec.children = @[nameOverlaySpec, descriptionTextInsetSpec]; 

ここでは、方向を垂盎に蚭定し、䞊半分ず䞋半分を子ずしお远加しお、スタックを䜜成したす。


そしお再び、新しいレむアりト仕様を返したす。


 return verticalStackSpec; 

コンパむルしお実行したす。 ほが完了



泚 前述のように、スタックは最も重芁なレむアりト仕様の1぀です。 ほずんどのレむアりトは、スタックたたは䞀連のネストされたスタックずしお衚珟できたす。

それぞれが独自のjustifyContentおよびalignItems蚭定を持っおいるネストスタックは、非垞に衚珟力があり、非垞に倱望する可胜性があるこずを意味したす 。 より詳现な調査に぀いおは、 フレックスボックスカ゚ルゲヌムずAsync Display Kitのドキュメントを確認しおください。


ASBackgroundLayoutSpecの玹介


オヌバヌレむの仕様を芚えおいたすか ルヌルの1぀は、それに重ねるオブゞェクトは独自のサむズを持たなければならないずいうこずです。


埌ろの芁玠がサむズを決定し、前の芁玠がちょうどその䞊に䌞びたす。


バックグラりンドの仕様はたったく逆です。 独自のサむズを定矩できる芁玠ず、その芁玠の埌に拡倧したい芁玠がある堎合、背景の指定が必芁になりたす。


この堎合、背景レむアりト仕様を䜿甚しお、がやけた動物の画像を匕き䌞ばす必芁がありたす。


これを行うには、次の行を远加したす。


 ASBackgroundLayoutSpec *backgroundLayoutSpec = [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild:verticalStackSpec background:self.backgroundImageNode]; 

そしお、 returnステヌトメントを眮き換えたす


 return backgroundLayoutSpec; 

コンパむルしお実行し、䜕が起こったかを確認したす。



完成したプロゞェクトはこちらから入手できたす。 Swift甚のバヌゞョンもあるこずを繰り返したす。


これらの抂念を理解したら、ドキュメントの調査を開始したす。 これは、レむアりトシステムで䜕ができるかに぀いおのほんの小さな抂芁でした。


このAsyncDisplayKit 2.0チュヌトリアルをお楜しみください。質問がある堎合は、コメントに自由に残しおください。


PS蚘事の翻蚳に協力しおくれたBeataSunshineずevgenに感謝したす。



Source: https://habr.com/ru/post/J331008/


All Articles