1 /* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "core/components_ng/pattern/text_field/text_field_manager.h" 17 18 #include "base/memory/ace_type.h" 19 #include "base/utils/utils.h" 20 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h" 21 #include "core/components_ng/pattern/text_field/text_field_pattern.h" 22 23 namespace OHOS::Ace::NG { GetKeyEventHandler()24const RefPtr<KeyEventHandler>& TextFieldManagerNG::GetKeyEventHandler() 25 { 26 if (!keyEventHandler_) { 27 keyEventHandler_ = AceType::MakeRefPtr<KeyEventHandler>(); 28 } 29 return keyEventHandler_; 30 } 31 ClearOnFocusTextField()32void TextFieldManagerNG::ClearOnFocusTextField() 33 { 34 onFocusTextField_ = nullptr; 35 CHECK_NULL_VOID(keyEventHandler_); 36 keyEventHandler_->ClearClient(); 37 } 38 OnBackPressed()39bool TextFieldManagerNG::OnBackPressed() 40 { 41 auto pattern = onFocusTextField_.Upgrade(); 42 CHECK_NULL_RETURN(pattern, false); 43 auto textfieldPattern = AceType::DynamicCast<TextFieldPattern>(pattern); 44 CHECK_NULL_RETURN(textfieldPattern, false); 45 return textfieldPattern->OnBackPressed(); 46 } 47 FindScrollableOfFocusedTextField(const RefPtr<FrameNode> & textField)48RefPtr<FrameNode> TextFieldManagerNG::FindScrollableOfFocusedTextField(const RefPtr<FrameNode>& textField) 49 { 50 CHECK_NULL_RETURN(textField, {}); 51 auto parent = textField->GetAncestorNodeOfFrame(); 52 while (parent) { 53 auto pattern = parent->GetPattern<ScrollablePattern>(); 54 if (pattern) { 55 return parent; 56 } 57 parent = parent->GetAncestorNodeOfFrame(); 58 } 59 return {}; 60 } 61 ScrollToSafeAreaHelper(const SafeAreaInsets::Inset & bottomInset)62void TextFieldManagerNG::ScrollToSafeAreaHelper(const SafeAreaInsets::Inset& bottomInset) 63 { 64 auto textField = DynamicCast<TextFieldPattern>(onFocusTextField_.Upgrade()); 65 CHECK_NULL_VOID(textField); 66 auto textFieldNode = textField->GetHost(); 67 CHECK_NULL_VOID(textFieldNode); 68 69 auto scrollableNode = FindScrollableOfFocusedTextField(textFieldNode); 70 CHECK_NULL_VOID_NOLOG(scrollableNode); 71 auto scrollPattern = scrollableNode->GetPattern<ScrollablePattern>(); 72 CHECK_NULL_VOID(scrollPattern); 73 74 auto scrollableRect = scrollableNode->GetTransformRectRelativeToWindow(); 75 CHECK_NULL_VOID_NOLOG(scrollableRect.Top() < bottomInset.start); 76 77 auto caretRect = textField->GetCaretRect() + textFieldNode->GetOffsetRelativeToWindow(); 78 // caret above scroll's content region 79 auto diffTop = (caretRect.Top() - caretRect.Height() * 2) - scrollableRect.Top(); 80 if (diffTop < 0) { 81 scrollPattern->ScrollTo(scrollPattern->GetTotalOffset() + diffTop); 82 return; 83 } 84 85 // caret below safeArea 86 auto diffBot = bottomInset.start - (caretRect.Bottom() + caretRect.Height() * 2); 87 CHECK_NULL_VOID_NOLOG(diffBot < 0); 88 scrollPattern->ScrollTo(scrollPattern->GetTotalOffset() - diffBot); 89 } 90 ScrollTextFieldToSafeArea()91void TextFieldManagerNG::ScrollTextFieldToSafeArea() 92 { 93 auto pipeline = PipelineContext::GetCurrentContext(); 94 CHECK_NULL_VOID(pipeline); 95 auto keyboardInset = pipeline->GetSafeAreaManager()->GetKeyboardInset(); 96 // only scroll when keyboard shows 97 CHECK_NULL_VOID_NOLOG(keyboardInset.IsValid()); 98 auto bottomInset = pipeline->GetSafeArea().bottom_.Combine(keyboardInset); 99 CHECK_NULL_VOID_NOLOG(bottomInset.IsValid()); 100 ScrollToSafeAreaHelper(bottomInset); 101 } 102 } // namespace OHOS::Ace::NG 103