Skip to content

Commit

Permalink
feat(android): text input support lineHeight (#3936)
Browse files Browse the repository at this point in the history
Co-authored-by: maxli <maxli@tencent.com>
  • Loading branch information
siguangli and siguangli2018 committed Nov 4, 2024
1 parent 0f71972 commit a5f4220
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 7 deletions.
2 changes: 2 additions & 0 deletions docs/api/hippy-react/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ import icon from './qb_icon_new.png';
| keyboardType | 决定弹出的何种软键盘的。 注意,`password`仅在属性 `multiline=false` 单行文本框时生效。 | `enum (default, numeric, password, email, phone-pad)` | `Android、iOS、hippy-react-web、Web-Renderer、Voltron` |
| maxLength | 限制文本框中最多的字符数。使用这个属性而不用JS 逻辑去实现,可以避免闪烁的现象。 | `number` | `Android、iOS、hippy-react-web、Web-Renderer、Voltron` |
| multiline | 如果为 `true` ,文本框中可以输入多行文字。 由于终端特性。 | `boolean` | `Android、iOS、hippy-react-web、Web-Renderer、Voltron` |
| lineSpacingExtra | 多行显示时每行文字的额外行高,如果style里设置的lineHeight属性该属性设置无效 | `number` | `Android` |
| lineSpacingMultiplier | 多行显示时每行文字的行高乘积系数,如果style里设置的lineHeight属性该属性设置无效 | `number` | `Android` |
| numberOfLines | 设置 `TextInput` 最大显示行数,如果 `TextInput` 没有显式设置高度,会根据 `numberOfLines` 来计算高度撑开。在使用的时候必需同时设置 `multiline` 参数为 `true`| `number` | `Android、hippy-react-web、Web-Renderer、Voltron` |
| onBlur | 当文本框失去焦点的时候调用此回调函数。 | `Function` | `Android、iOS、hippy-react-web、Web-Renderer、Voltron` |
| onFocus | 当文本框获得焦点的时候调用此回调函数。 | `Function` | `Android、iOS、Voltron` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ const styles = StyleSheet.create({
fontSize: 16,
color: '#242424',
height: 30,
// you can use lineHeight/lineSpacing/lineHeightMultiple
// to control the space between lines in multi-line input.(iOS only for now)
// you can use lineHeight
// to control the space between lines in multi-line input.
// for example:
lineHeight: 30,
// lineSpacing: 50,
// lineHeightMultiple: 1.5,
},
input_style_block: {
height: 100,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.tencent.mtt.hippy.views.textinput;

import static com.tencent.mtt.hippy.views.textinput.HippyTextInputController.UNSET;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.BlendMode;
Expand Down Expand Up @@ -83,10 +85,15 @@ public class HippyTextInput extends AppCompatEditText implements HippyViewBase,
private final ViewTreeObserver.OnGlobalLayoutListener mKeyboardEventObserver = this::checkSendKeyboardEvent;
private boolean mIsKeyBoardShow = false; //键盘是否在显示
private boolean mIsKeyBoardShowBySelf = false;
private boolean mShouldUpdateTypeface = false;
private boolean mShouldUpdateLineHeight = false;
private int mListenerFlag = 0;
private ReactContentSizeWatcher mReactContentSizeWatcher = null;
private boolean mItalic = false;
private int mFontWeight = TypeFaceUtil.WEIGHT_NORMAL;
private float mLineSpacingMultiplier = 1.0f;
private float mLineSpacingExtra = 0.0f;
private int mLineHeight = 0;
@Nullable
private String mFontFamily;
private Paint mTextPaint;
Expand Down Expand Up @@ -177,6 +184,48 @@ void setGravityVertical(int gravityVertical) {
setGravity((getGravity() & ~Gravity.VERTICAL_GRAVITY_MASK) | gravityVertical);
}

public void setLineSpacingMultiplier(float spacingMultiplier) {
if (Float.compare(spacingMultiplier, mLineSpacingMultiplier) != 0) {
mLineSpacingMultiplier = spacingMultiplier;
mShouldUpdateLineHeight = true;
}
}

public void setLineSpacingExtra(float spacingExtra) {
if (Float.compare(spacingExtra, mLineSpacingExtra) != 0) {
mLineSpacingExtra = spacingExtra;
mShouldUpdateLineHeight = true;
}
}

public void setTextLineHeight(int lineHeight) {
if (Float.compare(lineHeight, mLineHeight) != 0) {
mLineHeight = lineHeight;
mShouldUpdateLineHeight = true;
}
}

public void onBatchComplete() {
if (mShouldUpdateTypeface) {
updateTypeface();
mShouldUpdateTypeface = false;
}
if (!mShouldUpdateLineHeight) {
return;
}
if (mLineHeight > 0) {
final int fontHeight = getPaint().getFontMetricsInt(null);
// Make sure we don't setLineSpacing if it's not needed to avoid unnecessary redraw.
if (mLineHeight != fontHeight) {
// Set lineSpacingExtra by the difference of lineSpacing with lineHeight
setLineSpacing(mLineHeight - fontHeight, 1f);
}
} else {
setLineSpacing(mLineSpacingExtra, mLineSpacingMultiplier);
}
mShouldUpdateLineHeight = false;
}

@Override
protected void onDraw(Canvas canvas) {
RenderNode node = RenderManager.getRenderNode(this);
Expand Down Expand Up @@ -702,14 +751,14 @@ public void refreshSoftInput() {
public void setFontStyle(String style) {
if (TypeFaceUtil.TEXT_FONT_STYLE_ITALIC.equals(style) != mItalic) {
mItalic = !mItalic;
updateTypeface();
mShouldUpdateTypeface = true;
}
}

public void setFontFamily(String family) {
if (!Objects.equals(mFontFamily, family)) {
mFontFamily = family;
updateTypeface();
mShouldUpdateTypeface = true;
}
}

Expand All @@ -731,7 +780,7 @@ public void setFontWeight(String weight) {
}
if (fontWeight != mFontWeight) {
mFontWeight = fontWeight;
updateTypeface();
mShouldUpdateTypeface = true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,38 @@
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;

import androidx.annotation.Nullable;
import com.tencent.mtt.hippy.annotation.HippyController;
import com.tencent.mtt.hippy.annotation.HippyControllerProps;
import com.tencent.mtt.hippy.common.HippyArray;
import com.tencent.mtt.hippy.dom.node.NodeProps;
import com.tencent.mtt.hippy.modules.Promise;
import com.tencent.mtt.hippy.uimanager.ControllerManager;
import com.tencent.mtt.hippy.uimanager.HippyViewController;
import com.tencent.mtt.hippy.utils.LogUtils;
import com.tencent.mtt.hippy.utils.PixelUtil;
import com.tencent.mtt.hippy.views.view.HippyViewGroup;
import com.tencent.renderer.NativeRender;
import com.tencent.renderer.NativeRenderException;
import com.tencent.renderer.NativeRendererManager;
import com.tencent.renderer.component.text.TextRenderSupplier;
import com.tencent.renderer.node.RenderNode;
import com.tencent.renderer.node.TextInputRenderNode;
import com.tencent.renderer.node.TextVirtualNode;
import com.tencent.renderer.node.ViewPagerRenderNode;
import com.tencent.renderer.utils.ArrayUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static com.tencent.renderer.NativeRenderException.ExceptionCode.HANDLE_CALL_UI_FUNCTION_ERR;

@HippyController(name = HippyTextInputController.CLASS_NAME, dispatchWithStandardType = true)
public class HippyTextInputController extends HippyViewController<HippyTextInput> {

public static final String CLASS_NAME = "TextInput";
public final static int UNSET = -1;
public static final int DEFAULT_TEXT_COLOR = Color.BLACK;
public static final int DEFAULT_PLACEHOLDER_TEXT_COLOR = Color.GRAY;
private static final String TAG = "HippyTextInputControlle";
Expand All @@ -84,6 +92,17 @@ protected View createViewImpl(Context context) {
return new HippyTextInput(context);
}

@Override
public RenderNode createRenderNode(int rootId, int id, @Nullable Map<String, Object> props,
@NonNull String className, @NonNull ControllerManager controllerManager, boolean isLazy) {
return new TextInputRenderNode(rootId, id, props, className, controllerManager, isLazy);
}

@Override
public void onBatchComplete(@NonNull HippyTextInput textInput) {
textInput.onBatchComplete();
}

@Override
protected void updateExtra(@NonNull View view, Object object) {
super.updateExtra(view, object);
Expand Down Expand Up @@ -276,6 +295,24 @@ public void setLetterSpacing(HippyTextInput view, float letterSpacing) {
view.setLetterSpacing(PixelUtil.dp2px(letterSpacing));
}

@SuppressWarnings("unused")
@HippyControllerProps(name = NodeProps.LINE_HEIGHT, defaultType = HippyControllerProps.NUMBER)
public void setLineHeight(HippyTextInput view, int lineHeight) {
view.setTextLineHeight(Math.round(PixelUtil.dp2px(lineHeight)));
}

@SuppressWarnings("unused")
@HippyControllerProps(name = NodeProps.LINE_SPACING_MULTIPLIER, defaultType = HippyControllerProps.NUMBER, defaultNumber = UNSET)
public void setLineSpacingMultiplier(HippyTextInput view, float lineSpacingMultiplier) {
view.setLineSpacingMultiplier(lineSpacingMultiplier);
}

@SuppressWarnings("unused")
@HippyControllerProps(name = NodeProps.LINE_SPACING_EXTRA, defaultType = HippyControllerProps.NUMBER, defaultNumber = 0.0f)
public void setLineSpacingExtra(HippyTextInput view, float lineSpacingExtra) {
view.setLineSpacingExtra(PixelUtil.dp2px(lineSpacingExtra));
}

@HippyControllerProps(name = "value", defaultType = HippyControllerProps.STRING)
public void value(HippyTextInput view, String value) {
int selectionStart = view.getSelectionStart();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* Tencent is pleased to support the open source community by making Hippy available.
* Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.tencent.renderer.node;

import androidx.annotation.Nullable;
import com.tencent.mtt.hippy.uimanager.ControllerManager;
import java.util.Map;

public class TextInputRenderNode extends RenderNode {

public TextInputRenderNode(int rootId, int id, @Nullable Map<String, Object> props,
String className, ControllerManager componentManager, boolean isLazyLoad) {
super(rootId, id, props, className, componentManager, isLazyLoad);
}

@Override
protected boolean shouldNotifyNonBatchingChange() {
return !isBatching();
}
}

0 comments on commit a5f4220

Please sign in to comment.