Change layer widget height with animation.

This commit is contained in:
John Preston 2022-04-12 16:07:25 +04:00
parent 9933d1ff3a
commit f6f39d1560
5 changed files with 79 additions and 13 deletions

View file

@ -86,15 +86,50 @@ void LayerWidget::setupHeightConsumers() {
}) | rpl::start_with_next([this] { }) | rpl::start_with_next([this] {
resizeToWidth(width()); resizeToWidth(width());
}, lifetime()); }, lifetime());
_content->grabbingForExpanding(
) | rpl::start_with_next([=](bool grabbing) {
if (grabbing) {
_savedHeight = _contentHeight;
_savedHeightAnimation = base::take(_heightAnimation);
setContentHeight(_desiredHeight);
} else {
_heightAnimation = base::take(_savedHeightAnimation);
setContentHeight(_savedHeight);
}
}, lifetime());
_content->desiredHeightValue( _content->desiredHeightValue(
) | rpl::start_with_next([this](int height) { ) | rpl::start_with_next([this](int height) {
accumulate_max(_desiredHeight, height); if (!height) {
if (_content && !_inResize) { // New content arrived.
_heightAnimated = _heightAnimation.animating();
return;
}
std::swap(_desiredHeight, height);
if (!height
|| (_heightAnimated && !_heightAnimation.animating())) {
setContentHeight(_desiredHeight);
} else {
_heightAnimated = true;
_heightAnimation.start([=] {
setContentHeight(_heightAnimation.value(_desiredHeight));
}, _contentHeight, _desiredHeight, st::slideDuration);
resizeToWidth(width()); resizeToWidth(width());
} }
}, lifetime()); }, lifetime());
} }
void LayerWidget::setContentHeight(int height) {
if (_contentHeight == height) {
return;
}
_contentHeight = height;
if (_content && !_inResize) {
resizeToWidth(width());
}
}
void LayerWidget::showFinished() { void LayerWidget::showFinished() {
floatPlayerShowVisible(); floatPlayerShowVisible();
} }
@ -217,8 +252,8 @@ int LayerWidget::resizeGetHeight(int newWidth) {
st::infoLayerTopMaximal); st::infoLayerTopMaximal);
auto newBottom = newTop; auto newBottom = newTop;
// Top rounding is included in _desiredHeight. // Top rounding is included in _contentHeight.
auto desiredHeight = _desiredHeight + st::boxRadius; auto desiredHeight = _contentHeight + st::boxRadius;
accumulate_min(desiredHeight, windowHeight - newTop - newBottom); accumulate_min(desiredHeight, windowHeight - newTop - newBottom);
// First resize content to new width and get the new desired height. // First resize content to new width and get the new desired height.
@ -230,6 +265,8 @@ int LayerWidget::resizeGetHeight(int newWidth) {
auto scrollTillBottom = _content->scrollTillBottom(contentHeight); auto scrollTillBottom = _content->scrollTillBottom(contentHeight);
auto additionalScroll = std::min(scrollTillBottom, newBottom); auto additionalScroll = std::min(scrollTillBottom, newBottom);
const auto expanding = (_desiredHeight > _contentHeight);
desiredHeight += additionalScroll; desiredHeight += additionalScroll;
contentHeight += additionalScroll; contentHeight += additionalScroll;
_tillBottom = (newTop + desiredHeight >= windowHeight); _tillBottom = (newTop + desiredHeight >= windowHeight);
@ -241,7 +278,8 @@ int LayerWidget::resizeGetHeight(int newWidth) {
contentLeft, contentLeft,
contentTop, contentTop,
contentWidth, contentWidth,
contentHeight }, additionalScroll); contentHeight,
}, expanding, additionalScroll);
auto newGeometry = QRect(newLeft, newTop, newWidth, desiredHeight); auto newGeometry = QRect(newLeft, newTop, newWidth, desiredHeight);
if (newGeometry != geometry()) { if (newGeometry != geometry()) {

View file

@ -68,11 +68,17 @@ private:
not_null<const HistoryItem*> item) override; not_null<const HistoryItem*> item) override;
void setupHeightConsumers(); void setupHeightConsumers();
void setContentHeight(int height);
not_null<Window::SessionController*> _controller; not_null<Window::SessionController*> _controller;
object_ptr<WrapWidget> _content; object_ptr<WrapWidget> _content;
int _desiredHeight = 0; int _desiredHeight = 0;
int _contentHeight = 0;
int _savedHeight = 0;
Ui::Animations::Simple _heightAnimation;
Ui::Animations::Simple _savedHeightAnimation;
bool _heightAnimated = false;
bool _inResize = false; bool _inResize = false;
bool _tillBottom = false; bool _tillBottom = false;

View file

@ -44,9 +44,10 @@ void SectionWidget::init() {
sizeValue( sizeValue(
) | rpl::start_with_next([wrap = _content.data()](QSize size) { ) | rpl::start_with_next([wrap = _content.data()](QSize size) {
const auto expanding = false;
auto wrapGeometry = QRect{ { 0, 0 }, size }; auto wrapGeometry = QRect{ { 0, 0 }, size };
auto additionalScroll = 0; auto additionalScroll = 0;
wrap->updateGeometry(wrapGeometry, additionalScroll); wrap->updateGeometry(wrapGeometry, expanding, additionalScroll);
}, _content->lifetime()); }, _content->lifetime());
_connecting = std::make_unique<Window::ConnectionState>( _connecting = std::make_unique<Window::ConnectionState>(

View file

@ -645,10 +645,10 @@ rpl::producer<bool> WrapWidget::topShadowToggledValue() const {
rpl::producer<int> WrapWidget::desiredHeightForContent() const { rpl::producer<int> WrapWidget::desiredHeightForContent() const {
using namespace rpl::mappers; using namespace rpl::mappers;
return rpl::combine( return rpl::single(0) | rpl::then(rpl::combine(
_content->desiredHeightValue(), _content->desiredHeightValue(),
topWidget()->heightValue(), topWidget()->heightValue(),
_1 + _2); _1 + _2));
} }
rpl::producer<SelectedItems> WrapWidget::selectedListValue() const { rpl::producer<SelectedItems> WrapWidget::selectedListValue() const {
@ -738,7 +738,14 @@ QPixmap WrapWidget::grabForShowAnimation(
//if (params.withTabs && _topTabs) { //if (params.withTabs && _topTabs) {
// _topTabs->hide(); // _topTabs->hide();
//} //}
const auto expanding = _expanding;
if (expanding) {
_grabbingForExpanding = true;
}
auto result = Ui::GrabWidget(this); auto result = Ui::GrabWidget(this);
if (expanding) {
_grabbingForExpanding = false;
}
if (params.withTopBarShadow) { if (params.withTopBarShadow) {
_topShadow->setVisible(true); _topShadow->setVisible(true);
} }
@ -1007,11 +1014,15 @@ object_ptr<Ui::RpWidget> WrapWidget::createTopBarSurrogate(
return nullptr; return nullptr;
} }
void WrapWidget::updateGeometry(QRect newGeometry, int additionalScroll) { void WrapWidget::updateGeometry(
QRect newGeometry,
bool expanding,
int additionalScroll) {
auto scrollChanged = (_additionalScroll != additionalScroll); auto scrollChanged = (_additionalScroll != additionalScroll);
auto geometryChanged = (geometry() != newGeometry); auto geometryChanged = (geometry() != newGeometry);
auto shrinkingContent = (additionalScroll < _additionalScroll); auto shrinkingContent = (additionalScroll < _additionalScroll);
_additionalScroll = additionalScroll; _additionalScroll = additionalScroll;
_expanding = expanding;
if (geometryChanged) { if (geometryChanged) {
if (shrinkingContent) { if (shrinkingContent) {
@ -1038,6 +1049,10 @@ rpl::producer<int> WrapWidget::scrollTillBottomChanges() const {
) | rpl::flatten_latest(); ) | rpl::flatten_latest();
} }
rpl::producer<bool> WrapWidget::grabbingForExpanding() const {
return _grabbingForExpanding.value();
}
WrapWidget::~WrapWidget() = default; WrapWidget::~WrapWidget() = default;
} // namespace Info } // namespace Info

View file

@ -118,11 +118,15 @@ public:
object_ptr<Ui::RpWidget> createTopBarSurrogate(QWidget *parent); object_ptr<Ui::RpWidget> createTopBarSurrogate(QWidget *parent);
bool closeByOutsideClick() const; [[nodiscard]] bool closeByOutsideClick() const;
void updateGeometry(QRect newGeometry, int additionalScroll); void updateGeometry(
int scrollTillBottom(int forHeight) const; QRect newGeometry,
rpl::producer<int> scrollTillBottomChanges() const; bool expanding,
int additionalScroll);
[[nodiscard]] int scrollTillBottom(int forHeight) const;
[[nodiscard]] rpl::producer<int> scrollTillBottomChanges() const;
[[nodiscard]] rpl::producer<bool> grabbingForExpanding() const;
~WrapWidget(); ~WrapWidget();
@ -203,6 +207,8 @@ private:
std::unique_ptr<Controller> _controller; std::unique_ptr<Controller> _controller;
object_ptr<ContentWidget> _content = { nullptr }; object_ptr<ContentWidget> _content = { nullptr };
int _additionalScroll = 0; int _additionalScroll = 0;
bool _expanding = false;
rpl::variable<bool> _grabbingForExpanding = false;
//object_ptr<Ui::PlainShadow> _topTabsBackground = { nullptr }; //object_ptr<Ui::PlainShadow> _topTabsBackground = { nullptr };
//object_ptr<Ui::SettingsSlider> _topTabs = { nullptr }; //object_ptr<Ui::SettingsSlider> _topTabs = { nullptr };
object_ptr<TopBar> _topBar = { nullptr }; object_ptr<TopBar> _topBar = { nullptr };