ÅngströmStyle Systemとは何ですか?
通常のモバイルアプリケーションでは、インターフェイスは最も複雑で最も重要な部分の1つです。 仕事を受け入れるとき、ユーザーが見るもの、顧客がまず評価するもの。
設計が開発前に描かれたとしても、最初のバージョンを作成する過程で、膨大な量の変更が依然として現れます。 ここでは、ボタンを再描画し、ここに移動し、フォントが収まらないためにフォントを増減します。 これらの各変更には改良が必要です。 正しいパラメーターをすぐに選択できない場合、多くの場合、このような改善は数百または数千にもなります。
このような状況では、デザイン設定をインターフェイス自体から分離し、個別に設定することが非常に有益であることがわかりました。 この問題は、HTMLのCSSのような、イデオロギー的にスタイルシステムによって解決する必要があります。
この記事では、アプリケーションでスタイルを正確に整理する方法と、これに使用する意味を示します。
アプリケーションのスタイルシステムの構造
アプリケーションを開発するとき、通常、2層のスタイル設定を取得します。 最初のレイヤーには、最も基本的なものが含まれています。
- アプリケーションの色
- アプリケーションフォント
- アプリケーションテキストの基本スタイル、
- 基本的なパラメーター。 たとえば、角の丸みの合計半径、またはグリッドのインデントステップ。
これらは、アプリケーション全体に浸透するパラメーターです。 デザイナーが突然失敗したフォントを選択し、変更する必要があると判断した場合、すぐにどこでも変更する必要があります。 通常、このレイヤーは非常に小さく、誰でも理解できます。 それを編集者/チューナー、デザイナー、または特に信頼できる場合には顧客に渡すことができます。
これらのパラメーターから、膨大な数のバリエーションで、スタイルの2番目のレイヤーが作成されます。 特定の画面、特定のインターフェイスコンポーネントについては既に説明しています。 たとえば。
- ラベル時間:フォント番号2、色3、左揃え、
- ボタン2:フォント5、青アクティブ、中央揃え。
通常、2番目のレイヤーのファイルはボリュームが大きいため、画面上またはアプリケーションのセクション上で複数に分割すると便利です。
アプリケーションのスタイルの利点
スタイルは、特に2つのレイヤーで構成されており、インターフェイス設定とコードを非常にうまく分離しています 。 何百ものソースコードや巨大なストーリーボードで検索するよりも、このフォントサイズを設定できるいくつかのスタイルファイルで見つける方が簡単です。
(DropBoxのファイルから)リモートソースからスタイルをロードする方法を学ぶと、リモート開発により設計セットアップが何百倍も高速化されます 。 デザイナーが開発者と一緒に座って、いくつかのパラメーターをすばやく調整しようとすることができるのは1つのことです。 各反復には数時間と数日かかることがあります。 この場合、ファイルを更新し、アプリケーションを再起動(または巧妙な秘密のジェスチャーを作成)して、結果を確認しました。
状況によっては、スキンを使用すると便利です。 たとえば、ブックリーダーの場合、これは必要です;日中は明るい背景で、夜は暗い背景で読むのが便利です。 顧客がそれを望んでいる場合もあれば、設計によって「すごい効果」が必要な場合もあります。 スタイルの最初のレイヤーに2つのオプションを作成する場合、それらを切り替えることができ、2番目のレイヤーは同じままにします。 その結果、 スキンはほとんど無料になります。
スタイルシステムが必要になったのはいつですか?
スタイルシステムの必要性は、2つの側面から同時に現れました。
- アウトソーシング会社は多くのアプリケーションを開発しています。 ある開発者が別の開発者のコードを修正できるように、一般的な作業スキームを用意しておくと便利です。 また、要件を常に変更している顧客も、私たちが望むよりも一般的です。
- それらのアプリケーションの開発では、常に「完璧な」ことを望んでいます。 Ilya BirmanでAngstromを開発したとき、Ilyaがカスタムカーソルなどの複雑なコンポーネントの設定を操作できる設計調整メカニズムが必要でした。
お客様のプロジェクトではなく、自分のプロジェクトで新しいアイデアをテストしたいので、Angstromは幸運で、彼のためにスタイルシステムを作成しました。 JSONファイルを使用してスタイルを記述し、それに(「Dropboxから」など)他のファイルを含める機能を追加しました。 フレームワークは、スタイルが変更されたことを報告するコールバックも実装しました。 私は、スタイルの更新を揺れ動くiPhoneに接続しました。 Sublimeのファイルを修正し、保存し、iPhoneを振って、スタイルをアップロードし、アプリケーション全体に適用しました。
「離陸しなかった」という既存のシステムの欠点は?
一般に、このアイデアは非常に成功し、作成されたすべてのアプリケーションにすぐに広まったことが判明しました。 場合によっては、これにより開発時間の大幅な短縮が可能になりました(たとえば、顧客のデザイナーがフォントや色をカスタマイズしたい場合)。時には、開発者の参加なしで(または最小限の関与で)シン瞬間)。
しかし、私はいくつかの点が好きではありませんでした。
最初はJSONです。 誤ってコンマを忘れたり、ファイルに別の愚かな間違いを犯したりして、すべてのスタイルが壊れたことが常に判明しました。 JSONはプロパティの名前をチェックせず(単なる文字列であり、そこに何が書かれているかは関係ありません)、タイピングが人為的に導入され、エラーの早期検出を妨害します。
同じJSONにより、名前にデータ型をエンコードできました。 私の色は色で終わり、中心または点の点などで終わりました。 その結果、フィールド名は必要以上に長くなりました。
スタイルシステムの使用を最初に試みた後、最も便利なオプションは、JSONでオブジェクトの階層を完全に繰り返すJSONを使用してクラスの階層を作成するときであることがわかりました。 厳密に型指定された構造がアプリケーションに表示され、通常のコードとして便利にアクセスできます。 原則として、UIコンポーネントをスタイルの更新にバインドして、スタイルがこのボタンに適用されることを知っていたため、スタイルが突然更新された場合(新しいスタイルがDropboxからダウンロードされた場合)、ボタン自体が更新されました。 しかし、実際には、そのような魔法は人生を妨げるだけであることが判明したため、更新ルールを明示的に規定する方がよいでしょう。
第三に、スタイルクラスを生成するコンソールユーティリティを作成しませんでした。 また、スタイル自体は、アプリケーションがシミュレーターで起動されたときに再作成されました。 これは、スタイルをプロジェクトに接続するときと、その後の更新中の両方で、重大なマイナスであることが判明しました。
Objective-Cと古いバージョンのiOSをサポートする必要性も少し干渉しました。 生成されたクラスのコードは大きくて不快であることが判明したので、私はそれを最適化したいと思います。
S2-よりシンプルで効率的なスタイルシステム
欠陥を理解したので、私はシステムを改善し、すべての点で解決されるタスクにより適しているようにしました。
- 現在、ファイル形式はKTVです。 基本タイプの色を含む、リンク、ミックスイン、およびタイプをサポートします。 KTVは変更せずにJSONファイルを読み取ることができるため、古いスタイルは変更せずに新しい構造に移行しました。
- スタイルファイルは、Swiftのktvファイルから作成されます。 同時に、Objective-Cサポートを使用しない場合(これも可能です)、コンパクトであり、アプリケーションのグローバル名前空間を詰まらせないクラス(ネストされたクラスの階層)を表示および使用するのに便利です。
- KTVでの型のサポートのおかげで、名前のサフィックスを放棄することが可能になり、プロパティとクラスの名前が簡素化されました。
- ktvファイル(または複数のファイル)からスタイルクラスを作成できるコンソールユーティリティが登場しました。
たとえば、元のKTVの(非常に小さな)フラグメントを提供します。
{ maxWidthForIPad: 600 darkTheme: false defaultFontName: HelveticaNeue-Light bolderFontName: HelveticaNeue boldFontName: HelveticaNeue-Medium defaultSymbolFontName: AngstromSymbols-Light bolderSymbolFontName: AngstromSymbols basicColors: { plateBackground: #edf5f4 separators: #00407020 } ilya: { aboutBackground: @basicColors.plateBackground listSeparator: @basicColors.separators } colors: { about: { background: @ilya.aboutBackgroundColor separator: @ilya.listSeparatorColor } } about: { margins: [0, 0, 0, 0] separatorSpacing: 10 background: @colors.about.backgroundColor separator: @colors.about.separatorColor } }
スタイルファイルの対応するフラグメントは、次のようになります。
let S2 = CONStyle() public struct CONStyle: S2Object { private static let _rootStyle = S2 public struct BasicColors: S2Object { let separators = UIColor(colorLiteralRed:Float(1.0), green:Float(1.0), blue:Float(1.0), alpha:Float(0.0)) let plateBackground = UIColor(colorLiteralRed:Float(0.929411764705882), green:Float(0.929411764705882), blue:Float(0.929411764705882), alpha:Float(1.0)) } let basicColors = BasicColors() public struct Ilya: S2Object { let aboutBackground = _rootStyle.basicColors.plateBackground let listSeparator = _rootStyle.basicColors.separators } let ilya = Ilya() public struct Colors: S2Object { public struct About: S2Object { let background = _rootStyle.ilya.aboutBackgroundColor let separator = _rootStyle.ilya.listSeparatorColor } let about = About() } public struct About: S2Object { let margins = UIEdgeInsets(top:0.0, left:0.0, bottom:0.0, right:0.0) let separatorSpacing = Int(10) let background = _rootStyle.colors.about.backgroundColor let separator = _rootStyle.colors.about.separatorColor } }
もちろん、Swiftを使用することは、Objective-Cの完全なプロジェクトには不便です。 これにより、Swiftランタイムがプロジェクトにドラッグされ、アプリケーションのサイズが大幅に増加する可能性があります。 しかし、第一に、純粋にObjective-Cコードのジェネレーターを書くことはそれほど難しくありません。第二に、すべてがアプリケーションでSwiftの大規模な使用に移行しているため、生成されたS2コードは「対象」になります。