QML не предоставляет анимацию взаимодействий кликов в стиле Material Design для Android по умолчанию, но это легко настраивается с помощью примитивов Rectangle. Анимация заключается в том, чтобы в одном родительском объекте Rectangle, при клике, необходимо второй дочерний объект Rectangle растянуть на всю область родительского. При этом дочерний объект будет растягиваться в течении определённого времени и выглядеть будет как расширяющийся круг, но при этом он не будет выходить за пределы родительского объекта.
Для наглядности создадим список элементов, по которым будем производить клики. Для отслеживания кликов будет использоваться область MouseArea, в которой будет отслеживаться несколько сигналов взаимодействия:
- onClicked - в данном сигнале будет останавливаться анимация и выполняться результат взаимодействия со списком;
- onPressed - при сигнале нажатия необходимо запустить анимацию, с предварительной установкой координат анимируемого объекта Rectangle.
- onReleased - при отпускании элемента списка необходимо остановить анимацию;
- onPositionChanged - при смене позиции области также необходимо остановить анимацию.
Для выполнения анимации используется объект PropertyAnimation. В данном объекте выбирается цель анимации, и список свойств, которые будут подвергаться изменению. В случае с анимируемым объектом Rectangl, необходимо расширять его как круг, для этого увеличиваем его свойства width, height и radius с одной и той же величиной. А для того, чтобы полностью заполнить родительский объект, выставим конечную величину свойств в три раза большую, чем ширина родительского элемента.
Также важным свойством родительского элемента является:
clip - активируя данное свойство ( true ), Мы обрезаем дочерние элементы объекта, чтобы они не выходили за границы родительского элемента.
Анимация клика - реализация в коде
- import QtQuick 2.5
- import QtQuick.Controls 1.4
- ApplicationWindow {
- visible: true
- width: 640
- height: 480
- title: qsTr("Hello World")
- /* Создадим список с несколькими элементами,
- * по которым будет производитсья анимированный клик
- * */
- ListView {
- anchors.fill: parent
- // В объекте находится ...
- delegate: Item {
- height: 48
- anchors.left: parent.left
- anchors.right: parent.right
- // ... прямоугольный фон,
- Rectangle {
- id: body
- anchors.fill: parent
- color: "white"
- // дочерние объекты будут обрезаться по области данного родительского элемента
- clip: true
- /* ... в котором находится другой фон, который будет
- * анимированным кругом клика
- * */
- Rectangle {
- id: colorRect
- height: 0
- width: 0
- color: "#e8e8e8"
- /* Свойство трансформации, в котором будут пересчитываться
- * стартовые координаты, чтобы был круг в центре клика
- * */
- transform: Translate {
- x: -colorRect.width / 2
- y: -colorRect.height / 2
- }
- }
- // Надпись в элементе списка
- Text {
- text: fragment
- anchors.left: parent.left
- anchors.leftMargin: 72
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- font.pixelSize: 14
- renderType: Text.NativeRendering
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- }
- // Область клика по элементу
- MouseArea {
- anchors.fill: parent
- onClicked: {
- circleAnimation.stop()
- }
- onPressed: {
- /* При нажатии на элемент выставляем стартовые координаты
- * фона для анимации круга в элементе
- * */
- colorRect.x = mouseX
- colorRect.y = mouseY
- // Запускаем анимацию
- circleAnimation.start()
- }
- onReleased: circleAnimation.stop()
- onPositionChanged: circleAnimation.stop()
- }
- // Анимация свойств
- PropertyAnimation {
- id: circleAnimation
- target: colorRect // Целью задаём круговой фон
- properties: "width,height,radius" // В анимации изменяем высоту, ширину и радиус закругления
- from: 0 // Изменяем параметры от о пикселей ...
- to: body.width*3 // ... до тройного размера ширины элемента списка
- duration: 300 // в течении 300 милисекунд
- // По остановке анимации обнуляем высоту и ширину анимированного фона
- onStopped: {
- colorRect.width = 0
- colorRect.height = 0
- }
- }
- }
- }
- model: listModel
- }
- // Модель списка с элементами
- ListModel {
- id: listModel
- ListElement {fragment: qsTr("1-й Фрагмент")}
- ListElement {fragment: qsTr("2-й Фрагмент")}
- ListElement {fragment: qsTr("3-й Фрагмент")}
- ListElement {fragment: qsTr("4-й Фрагмент")}
- ListElement {fragment: qsTr("5-й Фрагмент")}
- ListElement {fragment: qsTr("6-й Фрагмент")}
- ListElement {fragment: qsTr("7-й Фрагмент")}
- }
- }
Видеоурок
Результат анимации в стиле Material Design не является полностью идентичным тому, что должно быть, но показывает основную идею. Демонстрацию работы Вы можете увидеть в видеоуроке.