Skip to content

Draggable ​

可拖拽容器组件,通过指针输入拖拽。拖拽偏移在绘制时应用平移,不影响 Taitank 布局。

概述 ​

Draggable 继承 Container,重写指针事件处理函数以跟踪拖拽状态。用户按下并移动指针时,组件的视觉位置按拖拽增量偏移,布局位置(Taitank 计算)保持不变。

状态机 ​

Draggable 使用轻量状态机,包含三种状态:

状态说明
kIdle指针未与组件交互
kHovering指针在组件上方但未按下
kDragging指针按下并移动组件

状态转换由指针事件触发:

  • OnPointerEnter → kHovering(非拖拽时)
  • OnPointerExit → kIdle(非拖拽时)
  • OnPointerDown → kDragging
  • OnPointerUp → kIdle

使用示例 ​

cpp
#include <neoflux/widget/draggable.h>

auto box = std::make_shared<Draggable>();
box->SetWidth(100.0F)
   .SetHeight(100.0F)
   .SetBackgroundColor({.r = 51, .g = 128, .b = 230, .a = 255})
   .SetBorderRadius(12.0F);

auto label = std::make_shared<Text>("Drag Me");
box->AddChild(label);

API 参考 ​

方法 ​

方法说明
GetDragOffset() -> Point返回当前拖拽偏移 (x, y)
IsDragging() -> bool返回组件是否正在被拖拽

重写事件 ​

事件行为
OnPointerDown(pos)记录按下位置,设置拖拽状态
OnPointerUp(pos)结束拖拽,返回空闲状态
OnPointerMove(pos)拖拽时更新偏移,标记需要重建
OnPointerEnter()转换为悬停状态
OnPointerExit()转换为空闲状态
Paint(ctx)保存上下文,平移拖拽偏移,绘制子组件,恢复

长按检测模式 ​

将 Draggable 与协程结合实现长按检测。状态机作为"条件锁":指针按下时启动的协程在睡眠后检查组件状态,如果状态已改变(指针释放),协程静默返回。

cpp
class DragBox : public Draggable {
 public:
  bool OnPointerDown(const Point& local_pos) override {
    Draggable::OnPointerDown(local_pos);
    auto weak = std::weak_ptr<DragBox>(
        std::static_pointer_cast<DragBox>(shared_from_this()));
    app_->GetEventLoop().Schedule(LongPressCoroutine(weak));
    return true;
  }

 private:
  static Task<void> LongPressCoroutine(std::weak_ptr<DragBox> weak) {
    co_await Sleep(std::chrono::milliseconds(500));
    auto box = weak.lock();
    if (!box || !box->IsDragging()) co_return;
    // 检测到长按
  }
};

另见 ​

讨论

Released under the GPL-3.0 License.