Evgenii Legotckoi
04 січня 2016 р. 21:41

QML - Урок 022. Анімація Клацніть елемент у списку Стиль Material Design

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 не є повністю ідентичним тому, що має бути, але демонструє основну ідею. Демонстрацію роботи Ви можете побачити у відеоуроці.

Рекомендовані статті на цю тему

По статті запитували0питання

0

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up