QML:20分のアニメーションマテリアルデザインサンドイッチアイコン

こんにちは、Habr。



ユーザーインターフェイス(およびAndroidユーザーのみ)の開発に興味のある多くの開発者は、Android 5.0のリリースの一環としてGoogleによって積極的に推進されているマテリアルデザインインターフェイスの新しい概念に既に慣れています。 アプリケーションデザインガイドに精通し最近更新されたGoogle Playを注意深く調べて、非常に素晴らしいコンポーネントの1つに注目しました-メニューアイコン(一般的にはハンバーガーアイコンとして知られています)、アニメーションでバックアイコンに変わり、 QMLインターフェースの記述に宣言型言語を使用します。







この記事では、そのようなコンポーネントを実装する方法と、プロセスで発生する可能性のある問題や困難を説明します。 投稿の最後にある完全なソースコードへのリンク。



注釈
メインページでgifアニメーションを使用したことをすぐにおpoびしますが、残念ながら、これが何であるかは完全に不明になります。



記事のすべてのスクリーンショットは、レビューしやすいように3:1のスケールで表示されます。 記述内容を理解するには、QML言語の構文とそれがサポートする機能の基本的な理解が必要です。



Qtライブラリの配布キットとOSのQt Creator開発環境は、 公式のQt Webサイトからダウンロードできます。



ところで、HabrがサポートするソースタグはQMLソースの強調表示をサポートしていません。これにより、コードの読み取りが多少複雑になる可能性があります。 コードの量を可能な限り最小化しようとするだけです。



準備



最初に、Qt Creatorを実行し、「Qt Quick Interface」のようなプロジェクトを作成します。この例では、純粋なQMLを使用し、C ++コードを1行も記述しません。



コンポーネント用に別のQMLファイルをすぐに作成します。後で他のプロジェクトで使用する予定であるため、AppBarの標準アイコンサイズをMaterial Designから24×24に設定します。

MenuBackButton.qml

import QtQuick 2.2 Item { id: root width: 24 height: 24 }
      
      





アイコンを表示するためにプロジェクトのルート要素を準備し、マテリアルデザインスタイルで明るい背景を設定します。

main.qml

 import QtQuick 2.2 Rectangle { width: 48 height: 48 color: "#9c27b0" MenuBackIcon { id: menuBackIcon anchors.centerIn: parent } }
      
      







コンポーネントの構造



コンポーネントを詳しく見て、コンポーネントの構成とすべてをコードに変換する方法を見てみましょう。







まず、アイコンに「メニュー」と「戻る」という2つの主要な状態があることにすぐに気付くことができます。 他のすべての状態は、2つの間の遷移中のアニメーションの中間部分です。 これをQMLですぐに説明します。

MenuBackButton.qml

 ... state: "menu" states: [ State { name: "menu" }, State { name: "back" } ] ...
      
      





デバッグの利便性のために、main.qmlのルート要素に小さなフラグメントを追加します。これにより、マウスのクリックでアイコンの状態を切り替えることができます。

main.qml

 ... MouseArea { anchors.fill: parent onClicked: menuBackIcon.state = menuBackIcon.state === "menu" ? "back" : "menu" } ...
      
      







“「メニュー」のステータス



ご覧のとおり、アイコンは3つの長方形で構成され、それらは「メニュー」状態にあり、同じサイズで、上下に配置されています。 オリジナルと一致するピクセル単位の要素を取得するために、スマートフォンでGoogle Playアプリケーションのスクリーンショットをいくつか撮り、要素の座標とサイズを選択して、結果をスクリーンショットと比較しました。



これらの要素をコードに追加しましょう。

MenuBackButton.qml

 ... Rectangle { id: bar1 x: 2 y: 5 width: 20 height: 2 } Rectangle { id: bar2 x: 2 y: 10 width: height: } Rectangle { id: bar3 x: 2 y: 15 width: 20 height: 2 } ...
      
      





これで、作成されたアプリケーションを実行し、この状態のアイコンが必要なとおりに表示されることを確認できます。





animationアニメーションの構成



「戻る」状態の説明に進むために、アニメーションがどのように見えるかをもう一度注意深く見てみましょう。 これが今行われていない場合は、すでに記述されたコードをやり直す必要がある可能性がありますが、もちろんやりたくないでしょう。



コンポーネントの状態間の遷移は、2つの並行アニメーションで構成されます。



もちろん、私はすぐにそれを考慮せず、各要素の回転のアニメーションを個別に作成しようとしました。 コードを保存しておらず、まったく再現したくありません。ひどくナンセンスになったからです。 私の間違いを繰り返さないでください:)



実際、ピクセルごとの検査により、中央の長方形もアニメーション化されていることが明らかになりました-その幅はわずかに減少します。



▌後退状態



踏むべきではないレーキがわかったので、「戻る」状態について説明しましょう。 すでにわかったように、軸の周りを180度回転した「前方」アイコンで構成されます。



これをコードに実装するために、QML要素PropertyChangesを使用します。これにより、別の状態への遷移中に要素のプロパティを変更する方法を指定できます。 「戻る」状態の説明を次のコードに置き換えます。

MenuBackButton.qml

 ... State { name: "back" PropertyChanges { target: root; rotation: 180 } PropertyChanges { target: bar1; rotation: 45; width: 13; x: 9.5; y: 8 } PropertyChanges { target: bar2; width: 17; x: 3; y: 12 } PropertyChanges { target: bar3; rotation: -45; width: 13; x: 9.5; y: 16 } } ...
      
      





ルート要素に設定された回転プロパティは、そのすべての子にも影響することに注意してください。 起動し、要素をクリックします...万歳! :)





これらの座標を使用すると、すべてが正常に見えますが、90°の倍数以外の角度で回転した要素の一部をピクセルの半分またはピクセルに移動すると、長方形が率直に、奇妙に見え始める可能性があります。 実際、Rectangle要素のアンチエイリアスプロパティは、丸みのある長方形に対してのみデフォルトで有効になっています。 したがって、アニメーションの外観をより滑らかにし、さまざまな種類のレンダリングの問題を回避するには、発表した各四角形にプロパティ設定を追加する価値があります。
  antialiasing: true
      
      







▌トランジションアニメーション



必要な両方の要素の状態を説明したので、今度はそれらの間の遷移アニメーションを処理します。 これを行うには、QML Transition要素とPropertyAnimation要素を使用します。



また、使用の柔軟性を高めるために、animationDurationプロパティをすぐに宣言します。これにより、要素コードに干渉することなく、将来的に移行期間を変更できます。

MenuBackButton.qml

 ... property int animationDuration: 350 ... transitions: [ Transition { PropertyAnimation { target: root; duration: animationDuration; easing.type: Easing.InOutQuad } PropertyAnimation { target: bar1; properties: "rotation, width, x, y"; duration: animationDuration; easing.type: Easing.InOutQuad } PropertyAnimation { target: bar2; properties: "rotation, width, x, y"; duration: animationDuration; easing.type: Easing.InOutQuad } PropertyAnimation { target: bar3; properties: "rotation, width, x, y"; duration: animationDuration; easing.type: Easing.InOutQuad } } ] ...
      
      







「to」および「from」プロパティは通常、Transition要素で指定され、この遷移がどの状態遷移に作用するかを指定します。 ただし、この例では2つの状態しかないため、両方向の遷移アニメーションはほぼ同じであるため、これらのプロパティは設定できません。



easing.typeプロパティに注意してください -このプロパティを使用して、要素のアニメーション速度曲線を設定します。 事実、一定の速度で実行されるアニメーションは、通常、見た目があまり美しくありません。 現実の世界の動きには、動きの開始時に速度が増加する期間があり、終わりに速度が減少する期間が必要です。 実際、Googleはマテリアルデザインドキュメントでこれ参照しています



私たちはチェックします:





勝利? そうでもない。



ほぼ完了しましたが、「メニュー」状態に戻すときの回転アニメーションは、希望どおりに動作しません。 原則として、すべてが論理的です。回転角度は180度から0度に反対方向に変化します。 ただし、変更するのは非常に簡単です。

 ... RotationAnimation { target: root; direction: RotationAnimation.Clockwise; duration: animationDuration; easing.type: Easing.InOutQuad } ...
      
      





RotationAnimation要素は、このような場合のために特別に設計されており、回転が行われる方向を指定できます。 必要に応じて、呼び出し元のコードからアニメーションの方向を設定できるプロパティを要素に追加できます。



結果とリンク



このガイドは完全と見なすことができます。 最小限の変更で再利用に適した既製のコンポーネントを入手しました。 明るい背景に対して使用される場合、要素の色を設定するために「色」プロパティを追加することをお勧めします。



私の観点から見ると、QMLの大きな利点は、多くの場合、視覚的なコンポーネントのコードが読みやすく、非常にコンパクトであることです。 個人的には要素全体でたった60行のコードしか使用していなかったため、githubに別のリポジトリを作成するのはなんとなく不便だったので、gist リンクを提供しました。



All Articles