Skip to content

Commit

Permalink
chore: 增加滚动区域滚轮滚动到顶部或底部的回弹效果
Browse files Browse the repository at this point in the history
增加滚动区域滚轮滚动到顶部或底部的回弹效果

Log:
  • Loading branch information
Whale107 committed Aug 5, 2024
1 parent b8497a4 commit dea6ca4
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/DWidget/DBounceAnimation
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "dbounceanimation.h"
30 changes: 30 additions & 0 deletions include/widgets/dbounceanimation.h
Original file line number Diff line number Diff line change
@@ -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 <DObject>
#include <QObject>

class QPropertyAnimation;
class QAbstractScrollArea;
class DBounceAnimationPrivate;
class DBounceAnimation : public QObject, public DTK_CORE_NAMESPACE::DObject

Check warning on line 13 in include/widgets/dbounceanimation.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

class DBounceAnimation is not documented!
{
Q_OBJECT
public:
explicit DBounceAnimation(QObject *parent = nullptr);

Check warning on line 17 in include/widgets/dbounceanimation.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

function DBounceAnimation::DBounceAnimation is not documented!

void setAnimationTarget(QAbstractScrollArea *w);

Check warning on line 19 in include/widgets/dbounceanimation.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

function void DBounceAnimation::setAnimationTarget is not documented!

protected:
bool eventFilter(QObject *o, QEvent *e) override;
void bounceBack(Qt::Orientation orientation);

private:
D_DECLARE_PRIVATE(DBounceAnimation)

};

#endif // DBOUNCEANIMATION_H
101 changes: 101 additions & 0 deletions src/widgets/dbounceanimation.cpp
Original file line number Diff line number Diff line change
@@ -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 <QPropertyAnimation>
#include <QEvent>
#include <QDebug>
#include <QAbstractScrollArea>
#include <QScrollBar>
#include <QWheelEvent>
#include <QTimer>

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<QAbstractScrollArea *>(o)) {
if (auto wheelEvent = dynamic_cast<QWheelEvent *>(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(

Check warning on line 81 in src/widgets/dbounceanimation.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Suspicious calculation. Please use parentheses to clarify the code. The code ''a&b?c:d'' should be written as either ''(a&b)?c:d'' or ''a&(b?c:d)''.
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;
});
});
}
4 changes: 4 additions & 0 deletions src/widgets/dlistview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "dstyleditemdelegate.h"
#include "dstyle.h"

#include <DBounceAnimation>

DWIDGET_BEGIN_NAMESPACE

DVariantListModel::DVariantListModel(QObject *parent) :
Expand Down Expand Up @@ -196,6 +198,8 @@ DListView::DListView(QWidget *parent) :
DObject(*new DListViewPrivate(this))
{
d_func()->init();
auto animation = new DBounceAnimation(this);
animation->setAnimationTarget(this);
}

/*!
Expand Down
23 changes: 23 additions & 0 deletions src/widgets/private/dbounceanimation_p.h
Original file line number Diff line number Diff line change
@@ -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 <DObjectPrivate>

class DBounceAnimationPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate

Check warning on line 10 in src/widgets/private/dbounceanimation_p.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

class DBounceAnimationPrivate is not documented!
{
public:
DBounceAnimationPrivate(DBounceAnimation *qq);

Check warning on line 13 in src/widgets/private/dbounceanimation_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Class 'DBounceAnimationPrivate' has a constructor with 1 argument that is not explicit. Such constructors should in general be explicit for type safety reasons. Using the explicit keyword in the constructor means some mistakes when using the class can be avoided.

Check warning on line 13 in src/widgets/private/dbounceanimation_p.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

function DBounceAnimationPrivate::DBounceAnimationPrivate is not documented!

QPropertyAnimation *m_animation;

Check warning on line 15 in src/widgets/private/dbounceanimation_p.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

variable QPropertyAnimation* DBounceAnimationPrivate::m_animation is not documented!
QAbstractScrollArea *m_animationTarget;

Check warning on line 16 in src/widgets/private/dbounceanimation_p.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

variable QAbstractScrollArea* DBounceAnimationPrivate::m_animationTarget is not documented!
int m_deltaSum;

Check warning on line 17 in src/widgets/private/dbounceanimation_p.h

View workflow job for this annotation

GitHub Actions / check_job / DOXYGEN_CHECK

variable int DBounceAnimationPrivate::m_deltaSum is not documented!

private:
D_DECLARE_PUBLIC(DBounceAnimation)
};

#endif // DBOUNCEANIMATION_P_H

0 comments on commit dea6ca4

Please sign in to comment.