From dea6ca41f163e4a991b6603e1936239eebdb4c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A6=83=E6=9C=AC=E5=AD=A6?= Date: Mon, 5 Aug 2024 18:17:47 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0=E6=BB=9A=E5=8A=A8?= =?UTF-8?q?=E5=8C=BA=E5=9F=9F=E6=BB=9A=E8=BD=AE=E6=BB=9A=E5=8A=A8=E5=88=B0?= =?UTF-8?q?=E9=A1=B6=E9=83=A8=E6=88=96=E5=BA=95=E9=83=A8=E7=9A=84=E5=9B=9E?= =?UTF-8?q?=E5=BC=B9=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加滚动区域滚轮滚动到顶部或底部的回弹效果 Log: --- include/DWidget/DBounceAnimation | 1 + include/widgets/dbounceanimation.h | 30 +++++++ src/widgets/dbounceanimation.cpp | 101 +++++++++++++++++++++++ src/widgets/dlistview.cpp | 4 + src/widgets/private/dbounceanimation_p.h | 23 ++++++ 5 files changed, 159 insertions(+) create mode 100644 include/DWidget/DBounceAnimation create mode 100644 include/widgets/dbounceanimation.h create mode 100644 src/widgets/dbounceanimation.cpp create mode 100644 src/widgets/private/dbounceanimation_p.h diff --git a/include/DWidget/DBounceAnimation b/include/DWidget/DBounceAnimation new file mode 100644 index 000000000..b088a7338 --- /dev/null +++ b/include/DWidget/DBounceAnimation @@ -0,0 +1 @@ +#include "dbounceanimation.h" diff --git a/include/widgets/dbounceanimation.h b/include/widgets/dbounceanimation.h new file mode 100644 index 000000000..0fafc3876 --- /dev/null +++ b/include/widgets/dbounceanimation.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#ifndef DBOUNCEANIMATION_H +#define DBOUNCEANIMATION_H + +#include +#include + +class QPropertyAnimation; +class QAbstractScrollArea; +class DBounceAnimationPrivate; +class DBounceAnimation : public QObject, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT +public: + explicit DBounceAnimation(QObject *parent = nullptr); + + void setAnimationTarget(QAbstractScrollArea *w); + +protected: + bool eventFilter(QObject *o, QEvent *e) override; + void bounceBack(Qt::Orientation orientation); + +private: + D_DECLARE_PRIVATE(DBounceAnimation) + +}; + +#endif // DBOUNCEANIMATION_H diff --git a/src/widgets/dbounceanimation.cpp b/src/widgets/dbounceanimation.cpp new file mode 100644 index 000000000..bc7f8169a --- /dev/null +++ b/src/widgets/dbounceanimation.cpp @@ -0,0 +1,101 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "private/dbounceanimation_p.h" +#include +#include +#include +#include +#include +#include +#include + +DBounceAnimationPrivate::DBounceAnimationPrivate(DBounceAnimation *qq) + : DObjectPrivate (qq) + , m_animation(nullptr) + , m_animationTarget(nullptr) + , m_deltaSum(0) +{ +} + +DBounceAnimation::DBounceAnimation(QObject *parent) + : QObject(parent) + , DObject(*new DBounceAnimationPrivate(this)) +{ +} + +void DBounceAnimation::setAnimationTarget(QAbstractScrollArea *w) +{ + D_D(DBounceAnimation); + if (!w) + return; + + w->installEventFilter(this); + + if (d->m_animationTarget == w) + return; + + d->m_animationTarget = w; + +} + +bool DBounceAnimation::eventFilter(QObject *o, QEvent *e) +{ + D_D(DBounceAnimation); + if (e->type() == QEvent::Wheel) { + if (auto absscroll = dynamic_cast(o)) { + if (auto wheelEvent = dynamic_cast(e)) { + if (absscroll->verticalScrollBar()->value() <= 0 || absscroll->verticalScrollBar()->value() >= absscroll->verticalScrollBar()->maximum()) { + d->m_deltaSum += wheelEvent->delta(); + bounceBack(wheelEvent->angleDelta().x() == 0 ? Qt::Vertical : Qt::Horizontal); + } + } + } + } + + return false; +} + +void DBounceAnimation::bounceBack(Qt::Orientation orientation) +{ + D_D(DBounceAnimation); + if (d->m_animation) + return; + + if (orientation & Qt::Vertical && d->m_animationTarget->verticalScrollBar()->maximum() == d->m_animationTarget->verticalScrollBar()->minimum()) + return; + + if (orientation & Qt::Horizontal && d->m_animationTarget->horizontalScrollBar()->maximum() == d->m_animationTarget->horizontalScrollBar()->minimum()) + return; + + d->m_animation = new QPropertyAnimation(this); + d->m_animation->setTargetObject(d->m_animationTarget->viewport()); + d->m_animation->setPropertyName("pos"); + d->m_animation->setDuration(100); + d->m_animation->setEasingCurve(QEasingCurve::InQuart); + d->m_animation->setStartValue(QPoint(d->m_animationTarget->viewport()->x(), d->m_animationTarget->viewport()->y())); + + QTimer::singleShot(100, this, [this, d, orientation]() { + + orientation & Qt::Vertical + ? d->m_animation->setEndValue( + QPoint(d->m_animationTarget->viewport()->x(), d->m_animationTarget->viewport()->y() + d->m_deltaSum / 16)) + : d->m_animation->setEndValue( + QPoint(d->m_animationTarget->viewport()->x() + d->m_deltaSum / 16, d->m_animationTarget->viewport()->y())); + + d->m_animation->start(); + + connect(d->m_animation, &QPropertyAnimation::finished, this, [d]() { + if (d->m_animation->direction() == QPropertyAnimation::Backward) { + delete d->m_animation; + d->m_animation = nullptr; + return; + } + + d->m_animation->setDirection(QPropertyAnimation::Direction::Backward); + d->m_animation->setDuration(1000); + d->m_animation->start(QPropertyAnimation::DeleteWhenStopped); + d->m_deltaSum = 0; + }); + }); +} diff --git a/src/widgets/dlistview.cpp b/src/widgets/dlistview.cpp index 16672ba05..76a68b7c4 100644 --- a/src/widgets/dlistview.cpp +++ b/src/widgets/dlistview.cpp @@ -13,6 +13,8 @@ #include "dstyleditemdelegate.h" #include "dstyle.h" +#include + DWIDGET_BEGIN_NAMESPACE DVariantListModel::DVariantListModel(QObject *parent) : @@ -196,6 +198,8 @@ DListView::DListView(QWidget *parent) : DObject(*new DListViewPrivate(this)) { d_func()->init(); + auto animation = new DBounceAnimation(this); + animation->setAnimationTarget(this); } /*! diff --git a/src/widgets/private/dbounceanimation_p.h b/src/widgets/private/dbounceanimation_p.h new file mode 100644 index 000000000..09e2d5b3b --- /dev/null +++ b/src/widgets/private/dbounceanimation_p.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#ifndef DBOUNCEANIMATION_P_H +#define DBOUNCEANIMATION_P_H + +#include "dbounceanimation.h" +#include + +class DBounceAnimationPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DBounceAnimationPrivate(DBounceAnimation *qq); + + QPropertyAnimation *m_animation; + QAbstractScrollArea *m_animationTarget; + int m_deltaSum; + +private: + D_DECLARE_PUBLIC(DBounceAnimation) +}; + +#endif // DBOUNCEANIMATION_P_H