mirror of
https://github.com/openharmony/ace_ace_engine.git
synced 2026-07-21 01:45:30 -04:00
!320 Support Richtext self scroll
Merge pull request !320 from liguoqiang/rich_text
This commit is contained in:
@@ -23,6 +23,97 @@
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
RenderRichText::RenderRichText() : RenderNode(true)
|
||||
{
|
||||
LOGI("[richtext] recognizer init");
|
||||
touchRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
|
||||
touchRecognizer_->SetOnTouchDown([wp = AceType::WeakClaim(this)](const TouchEventInfo& info) {
|
||||
auto sp = wp.Upgrade();
|
||||
if (sp) {
|
||||
sp->prevPos_ = info.GetTouches().front().GetLocalLocation().GetY();
|
||||
}
|
||||
});
|
||||
touchRecognizer_->SetOnTouchUp([wp = AceType::WeakClaim(this)](const TouchEventInfo& info) {
|
||||
// do nothing
|
||||
});
|
||||
touchRecognizer_->SetOnTouchMove([wp = AceType::WeakClaim(this)](const TouchEventInfo& info) {
|
||||
auto sp = wp.Upgrade();
|
||||
if (!sp) {
|
||||
LOGE("[richtext] process move, could not get render node");
|
||||
return;
|
||||
}
|
||||
|
||||
sp->PorcessMove(info.GetTouches().front().GetLocalLocation().GetY());
|
||||
});
|
||||
|
||||
// register this listener for consuming the drag events.
|
||||
dragRecognizer_ = AceType::MakeRefPtr<VerticalDragRecognizer>();
|
||||
dragRecognizer_->SetOnDragStart([](const DragStartInfo& info) {});
|
||||
dragRecognizer_->SetOnDragEnd([](const DragEndInfo& info) {});
|
||||
}
|
||||
|
||||
void RenderRichText::PorcessMove(double posY)
|
||||
{
|
||||
auto diff = prevPos_ - posY;
|
||||
double scale = 1.0f;
|
||||
auto context = GetContext().Upgrade();
|
||||
if (context) {
|
||||
scale = context->GetViewScale();
|
||||
}
|
||||
prevPos_ = posY;
|
||||
|
||||
// downside or upside
|
||||
if (diff > 0) {
|
||||
if (!startSelfScroll_ && currentScrollLength_ == couldScrollLength_) {
|
||||
// do nothing
|
||||
} else {
|
||||
if (currentScrollLength_ > couldScrollLength_) {
|
||||
startSelfScroll_ = false;
|
||||
currentScrollLength_ = couldScrollLength_;
|
||||
} else {
|
||||
startSelfScroll_ = true;
|
||||
currentScrollLength_ += std::round(scale * diff);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!startSelfScroll_ && currentScrollLength_ == 0) {
|
||||
// do nothing
|
||||
} else {
|
||||
if (currentScrollLength_ < 0) {
|
||||
startSelfScroll_ = false;
|
||||
currentScrollLength_ = 0;
|
||||
} else {
|
||||
startSelfScroll_ = true;
|
||||
currentScrollLength_ += std::round(scale * diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let window scroll
|
||||
if (startSelfScroll_ && delegate_) {
|
||||
delegate_->UpdateContentScroll(0, currentScrollLength_);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderRichText::OnTouchTestHit(
|
||||
const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
|
||||
{
|
||||
if (canSelfScroll_) {
|
||||
// control self scroll, true only self scroll, false outside or parent render node scroll
|
||||
if (startSelfScroll_) {
|
||||
if (dragRecognizer_) {
|
||||
dragRecognizer_->SetCoordinateOffset(coordinateOffset);
|
||||
result.emplace_back(dragRecognizer_);
|
||||
}
|
||||
}
|
||||
|
||||
if (touchRecognizer_) {
|
||||
touchRecognizer_->SetCoordinateOffset(coordinateOffset);
|
||||
result.emplace_back(touchRecognizer_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderRichText::Update(const RefPtr<Component>& component)
|
||||
{
|
||||
if (!component || !delegate_) {
|
||||
@@ -72,7 +163,7 @@ void RenderRichText::CreateRealWeb(int32_t top, int32_t left, bool visible, bool
|
||||
delegate_->CreatePlatformResource(context_, top, left, visible);
|
||||
}
|
||||
|
||||
void RenderRichText::UpdateLayoutParams(const int32_t width, const int32_t height)
|
||||
void RenderRichText::UpdateLayoutParams(const int32_t width, const int32_t height, const int32_t contentHeight)
|
||||
{
|
||||
float scale = 1.0f;
|
||||
auto pipelineContext = context_.Upgrade();
|
||||
@@ -89,6 +180,14 @@ void RenderRichText::UpdateLayoutParams(const int32_t width, const int32_t heigh
|
||||
drawSize_.SetWidth(webContentWidth_);
|
||||
drawSize_.SetHeight(webContentHeight_);
|
||||
|
||||
auto diff = contentHeight - height;
|
||||
LOGI("richtext update layout h:%{public}d c-h:%{public}d", height, contentHeight);
|
||||
// content height should more than layout height 2 pixel.
|
||||
if (diff > 2) {
|
||||
canSelfScroll_ = true;
|
||||
couldScrollLength_ = diff;
|
||||
}
|
||||
|
||||
MarkNeedLayout(false, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class RenderRichText : public RenderNode {
|
||||
public:
|
||||
static RefPtr<RenderNode> Create();
|
||||
|
||||
RenderRichText() : RenderNode(true) {}
|
||||
RenderRichText();
|
||||
~RenderRichText() override = default;
|
||||
|
||||
void Update(const RefPtr<Component>& component) override;
|
||||
@@ -37,14 +37,17 @@ public:
|
||||
void MarkNeedRender(bool overlay = false);
|
||||
void OnGlobalPositionChanged() override;
|
||||
|
||||
void UpdateLayoutParams(const int32_t width, const int32_t height);
|
||||
void UpdateLayoutParams(const int32_t width, const int32_t height, const int32_t contentHeight);
|
||||
void SetDelegate(const RefPtr<RichTextDelegate>& delegate)
|
||||
{
|
||||
delegate_ = delegate;
|
||||
}
|
||||
void OnTouchTestHit(
|
||||
const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) override;
|
||||
|
||||
private:
|
||||
void CreateRealWeb(int32_t top, int32_t left, bool visible, bool reCreate = false);
|
||||
void PorcessMove(double posY);
|
||||
|
||||
protected:
|
||||
RefPtr<RichTextDelegate> delegate_;
|
||||
@@ -56,6 +59,13 @@ private:
|
||||
bool hasCreateWeb_ = false;
|
||||
bool isVisible_ = true;
|
||||
bool initPositionSet_ = false;
|
||||
RefPtr<RawRecognizer> touchRecognizer_;
|
||||
RefPtr<DragRecognizer> dragRecognizer_;
|
||||
bool canSelfScroll_ = false;
|
||||
bool startSelfScroll_ = true;
|
||||
double prevPos_ = 0.0f;
|
||||
int32_t couldScrollLength_ = 0;
|
||||
int32_t currentScrollLength_ = 0;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
@@ -34,6 +34,7 @@ constexpr char RICH_TEXT_METHOD_HIDE_RICHTEXT_WHNE_PUSH[] = "hideRichTextWhenPus
|
||||
constexpr char RICH_TEXT_METHOD_SHOW_RICHTEXT[] = "showRichText";
|
||||
constexpr char RICH_TEXT_METHOD_UPDATE_CONTENT[] = "updateRichTextContent";
|
||||
constexpr char RICH_TEXT_METHOD_UPDATE_TRANSLATE[] = "updateTranslate";
|
||||
constexpr char RICH_TEXT_METHOD_UPDATE_CONTENT_TRANSLATE[] = "updateContentTranslate";
|
||||
|
||||
constexpr char RICH_TEXT_EVENT_LOAD_START[] = "onPageStarted";
|
||||
constexpr char RICH_TEXT_EVENT_LOAD_FINISHED[] = "onPageFinished";
|
||||
@@ -46,8 +47,11 @@ constexpr char NTC_PARAM_RICH_TEXT[] = "richtext";
|
||||
constexpr char NTC_PARAM_LEFT[] = "left";
|
||||
constexpr char NTC_PARAM_TOP[] = "top";
|
||||
constexpr char NTC_PARAM_URL[] = "url";
|
||||
constexpr char NTC_PARAM_X[] = "x";
|
||||
constexpr char NTC_PARAM_Y[] = "y";
|
||||
constexpr char NTC_PARAM_LAYOUT_HEIGHT[] = "layoutHeight";
|
||||
constexpr char NTC_PARAM_LAYOUT_WIDTH[] = "layoutWidth";
|
||||
constexpr char NTC_PARAM_CONTENT_HEIGHT[] = "contentHeight";
|
||||
constexpr char NTC_PARAM_RICHTEXT_VISIBILITY[] = "visibility";
|
||||
constexpr char NTC_PARAM_PAGE_PATH[] = "pageRoutePath";
|
||||
constexpr char NTC_PARAM_DESCRIPTION[] = "description";
|
||||
@@ -317,6 +321,18 @@ void RichTextDelegate::UpdateWebPostion(const int32_t top, const int32_t left)
|
||||
CallResRegisterMethod(updateLayoutPositionMethod, param, nullptr);
|
||||
}
|
||||
|
||||
void RichTextDelegate::UpdateContentScroll(const int32_t x, const int32_t y)
|
||||
{
|
||||
hash_ = MakeResourceHash();
|
||||
|
||||
Method updateLayoutPositionMethod = MakeMethodHash(RICH_TEXT_METHOD_UPDATE_CONTENT_TRANSLATE);
|
||||
std::stringstream paramStream;
|
||||
paramStream << NTC_PARAM_X << RICHTEXT_PARAM_EQUALS << x << RICHTEXT_PARAM_AND
|
||||
<< NTC_PARAM_Y << RICHTEXT_PARAM_EQUALS << y;
|
||||
std::string param = paramStream.str();
|
||||
CallResRegisterMethod(updateLayoutPositionMethod, param, nullptr);
|
||||
}
|
||||
|
||||
void RichTextDelegate::CallPopPageSuccessPageUrl(const std::string& url, const int32_t pageId)
|
||||
{
|
||||
if (url == pageUrl_ && pageId == pageId_) {
|
||||
@@ -384,9 +400,10 @@ void RichTextDelegate::OnPageFinished(const std::string& param)
|
||||
void RichTextDelegate::OnGotLayoutParam(const std::string& param)
|
||||
{
|
||||
int32_t layoutHeight = GetIntParam(param, NTC_PARAM_LAYOUT_HEIGHT);
|
||||
int32_t contentHeight = GetIntParam(param, NTC_PARAM_CONTENT_HEIGHT);
|
||||
int32_t layoutWidth = GetIntParam(param, NTC_PARAM_LAYOUT_WIDTH);
|
||||
if (webviewLayoutCallback_) {
|
||||
webviewLayoutCallback_(layoutWidth, layoutHeight);
|
||||
webviewLayoutCallback_(layoutWidth, layoutHeight, contentHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
using CreatedCallback = std::function<void()>;
|
||||
using ReleasedCallback = std::function<void(bool)>;
|
||||
using EventCallback = std::function<void(const std::string&)>;
|
||||
using UpdateWebViewLayoutCallback = std::function<void(int32_t, int32_t)>;
|
||||
using UpdateWebViewLayoutCallback = std::function<void(int32_t, int32_t, int32_t)>;
|
||||
enum class State: char {
|
||||
WAITINGFORSIZE,
|
||||
CREATING,
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
void AddWebLayoutChangeCallback(const UpdateWebViewLayoutCallback& layoutChangeCallback);
|
||||
void UpdateRichTextData(const std::string& data);
|
||||
void UpdateWebPostion(const int32_t top, const int32_t left);
|
||||
void UpdateContentScroll(const int32_t x, const int32_t y);
|
||||
void ChangeRichTextVisibility(const bool visible);
|
||||
void HideRichText();
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ RefPtr<RenderNode> RichTextComponent::CreateRenderNode()
|
||||
auto renderRichText = AceType::DynamicCast<RenderRichText>(renderNode);
|
||||
|
||||
delegate_->AddWebLayoutChangeCallback(
|
||||
[renderRichText, weak = WeakClaim(this)](int32_t width, int32_t height) {
|
||||
[renderRichText, weak = WeakClaim(this)](int32_t width, int32_t height, int32_t contentHeight) {
|
||||
if (!renderRichText) {
|
||||
LOGE("renderRichText is null");
|
||||
return;
|
||||
@@ -60,10 +60,10 @@ RefPtr<RenderNode> RichTextComponent::CreateRenderNode()
|
||||
auto uiTaskExecutor = SingleTaskExecutor::Make(pipelineContext->GetTaskExecutor(),
|
||||
TaskExecutor::TaskType::UI);
|
||||
auto weakRender = AceType::WeakClaim(AceType::RawPtr(renderRichText));
|
||||
uiTaskExecutor.PostTask([weakRender, width, height] {
|
||||
uiTaskExecutor.PostTask([weakRender, width, height, contentHeight] {
|
||||
auto renderRichText = weakRender.Upgrade();
|
||||
if (renderRichText) {
|
||||
renderRichText->UpdateLayoutParams(width, height);
|
||||
renderRichText->UpdateLayoutParams(width, height, contentHeight);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,7 +73,6 @@ void FlutterRenderContext::PaintChild(const RefPtr<RenderNode>& child, const Off
|
||||
if (child->NeedRender()) {
|
||||
FlutterRenderContext context;
|
||||
context.Repaint(child);
|
||||
LOGE("form PaintChild 3");
|
||||
} else {
|
||||
// No need to repaint, notify to update AccessibilityNode info.
|
||||
child->NotifyPaintFinish();
|
||||
|
||||
Reference in New Issue
Block a user