!320 Support Richtext self scroll

Merge pull request !320 from liguoqiang/rich_text
This commit is contained in:
openharmony_ci
2021-10-27 12:19:17 +00:00
committed by Gitee
6 changed files with 135 additions and 9 deletions
@@ -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();