From a951958bd60cfe087ed4970070d8c2cbe9a02483 Mon Sep 17 00:00:00 2001 From: Whale107 <72391936+Whale107@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:33:32 +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=20(#596)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加滚动区域滚轮滚动到顶部或底部的回弹效果 Log: --- include/DWidget/DBounceAnimation | 1 + include/widgets/dbounceanimation.h | 31 +++++++ src/widgets/dbounceanimation.cpp | 107 +++++++++++++++++++++++ src/widgets/dlistview.cpp | 7 ++ src/widgets/private/dbounceanimation_p.h | 23 +++++ 5 files changed, 169 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..b5ff98fa5 --- /dev/null +++ b/include/widgets/dbounceanimation.h @@ -0,0 +1,31 @@ +// 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); + void setAniMationEnable(bool enable); + +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..d574375a7 --- /dev/null +++ b/src/widgets/dbounceanimation.cpp @@ -0,0 +1,107 @@ +// 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; + + if (d->m_animationTarget == w) + return; + + d->m_animationTarget = w; +} + +void DBounceAnimation::setAniMationEnable(bool enable) +{ + D_D(DBounceAnimation); + enable ? d->m_animationTarget->installEventFilter(this) + : d->m_animationTarget->removeEventFilter(this); +} + +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]() { + + if (orientation & Qt::Vertical) { + d->m_animation->setEndValue( + QPoint(d->m_animationTarget->viewport()->x(), d->m_animationTarget->viewport()->y() + d->m_deltaSum / 16)); + } else { + 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..8b7bff3d6 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,11 @@ DListView::DListView(QWidget *parent) : DObject(*new DListViewPrivate(this)) { d_func()->init(); + if (!qEnvironmentVariableIsSet("DTK_DISABLE_LISTVIEW_ANIMATION")) { + auto ani = new DBounceAnimation(this); + ani->setAnimationTarget(this); + ani->setAniMationEnable(true); + } } /*! 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