Skip to content

Commit

Permalink
feat(android,ios,js): add getBoundingClientRect method (Tencent#2651)
Browse files Browse the repository at this point in the history
* feat(android): add `getBoundingClientRect` api [WIP]

* feat(vue,react): add getBoundingClientRect api

* feat(android): add `getBoundingClientRect` api

* feat(ios): add getBoundingClientRect method

* docs(homepage): add getBoundingClientRect doc

* fix(demo): rm redundant file (Tencent#4)

* docs(homepage): add getBoundingClientRect doc

* fix(demo): rm redundant file

* fix(demo): rm redundant file

* refactor(vue-next-demo): rm unused code

* feat(android): add `getBoundingClientRect` api

Co-authored-by: iPel <pel20121221@gmail.com>
Co-authored-by: zoomchan-cxj <zoom_chan@163.com>
Co-authored-by: siguangli <siguangli@qq.com>
  • Loading branch information
4 people authored and pba-cra committed Feb 1, 2023
1 parent 12e7a0d commit 6898861
Show file tree
Hide file tree
Showing 24 changed files with 514 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.tencent.mtt.hippy.dom.node.*;
import com.tencent.mtt.hippy.modules.Promise;
import com.tencent.mtt.hippy.modules.javascriptmodules.EventDispatcher;
import com.tencent.mtt.hippy.runtime.builtins.JSObject;
import com.tencent.mtt.hippy.uimanager.DiffUtils;
import com.tencent.mtt.hippy.uimanager.RenderManager;
import com.tencent.mtt.hippy.utils.LogUtils;
Expand Down Expand Up @@ -917,11 +918,11 @@ public void exec() {
});
}

public void measureInWindow(final int id, final Promise promise) {
public void measureInWindow(final int id, final JSObject options, final Promise promise) {
addNulUITask(new IDomExecutor() {
@Override
public void exec() {
mRenderManager.measureInWindow(id, promise);
mRenderManager.measureInWindow(id, options, promise);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package com.tencent.mtt.hippy.modules.nativemodules.uimanager;

import android.text.TextUtils;
import com.tencent.mtt.hippy.HippyEngineContext;
import com.tencent.mtt.hippy.HippyRootView;
import com.tencent.mtt.hippy.annotation.HippyMethod;
Expand All @@ -25,6 +24,8 @@
import com.tencent.mtt.hippy.dom.DomManager;
import com.tencent.mtt.hippy.modules.Promise;
import com.tencent.mtt.hippy.modules.nativemodules.HippyNativeModuleBase;
import com.tencent.mtt.hippy.runtime.builtins.JSObject;
import com.tencent.mtt.hippy.uimanager.RenderNode;
import com.tencent.mtt.hippy.utils.LogUtils;

@SuppressWarnings({"deprecation", "unused"})
Expand Down Expand Up @@ -147,9 +148,25 @@ public void callUIFunction(HippyArray hippyArray, Promise promise) {
public void measureInWindow(int id, Promise promise) {
DomManager domManager = this.mContext.getDomManager();
if (domManager != null) {
domManager.measureInWindow(id, promise);
JSObject options = new JSObject();
options.set(RenderNode.KEY_COMPATIBLE, true);
domManager.measureInWindow(id, options, promise);
}
LogUtils.d("UIManagerModule", id + "" + promise);
LogUtils.d("UIManagerModule", "measureInWindow" + id + " " + promise);
}

@HippyMethod(name = "getBoundingClientRect", useJSValueType = true)
public void getBoundingClientRect(int id, JSObject options, Promise promise) {
DomManager domManager = this.mContext.getDomManager();
if (domManager == null) {
JSObject result = new JSObject();
result.set(RenderNode.KEY_ERR_MSG, "DomManager is null");
promise.reject(result);
return;
}
domManager.measureInWindow(id, options, promise);
LogUtils.d("UIManagerModule", "getBoundingClientRect" + id + " " + options + " " +
promise);
}

@HippyMethod(name = "startBatch")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.tencent.mtt.hippy.dom.node.NodeProps;
import com.tencent.mtt.hippy.dom.node.StyleNode;
import com.tencent.mtt.hippy.modules.Promise;
import com.tencent.mtt.hippy.runtime.builtins.JSObject;
import com.tencent.mtt.hippy.utils.ContextHolder;
import com.tencent.mtt.hippy.utils.DimensionsUtil;
import com.tencent.mtt.hippy.utils.LogUtils;
Expand Down Expand Up @@ -426,6 +427,52 @@ public void measureInWindow(int id, Promise promise) {

}

/**
* @param id view id
* @param rootView
* @param relToContainer true is relative to the rootView, otherwise relative to the app frame
* @param promise
*/
public void getBoundingClientRect(int id, HippyRootView rootView, boolean relToContainer, Promise promise) {
View v = mControllerRegistry.getView(id);
if (v == null) {
JSObject result = new JSObject();
result.set(RenderNode.KEY_ERR_MSG, "this view is null");
promise.reject(result);
return;
}
int x;
int y;
int width = v.getWidth();
int height = v.getHeight();
int[] pair = new int[2];
if (relToContainer) {
if (rootView == null) {
JSObject result = new JSObject();
result.set(RenderNode.KEY_ERR_MSG, "container is null");
promise.reject(result);
return;
}

v.getLocationInWindow(pair);
x = pair[0];
y = pair[1];
rootView.getLocationInWindow(pair);
x -= pair[0];
y -= pair[1];
} else {
v.getLocationOnScreen(pair);
x = pair[0];
y = pair[1];
}
JSObject result = new JSObject();
result.set("x", PixelUtil.px2dp(x));
result.set("y", PixelUtil.px2dp(y));
result.set("width", PixelUtil.px2dp(width));
result.set("height", PixelUtil.px2dp(height));
promise.resolve(result);
}

public void onManageChildComplete(String className, int id) {
HippyViewController hippyViewController = mControllerRegistry.getViewController(className);
View view = mControllerRegistry.getView(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import android.text.TextUtils;
import android.util.SparseArray;

import com.tencent.mtt.hippy.HippyAPIProvider;
import com.tencent.mtt.hippy.HippyEngineContext;
import com.tencent.mtt.hippy.HippyRootView;
Expand All @@ -26,8 +25,8 @@
import com.tencent.mtt.hippy.dom.node.DomNode;
import com.tencent.mtt.hippy.dom.node.NodeProps;
import com.tencent.mtt.hippy.modules.Promise;
import com.tencent.mtt.hippy.runtime.builtins.JSObject;
import com.tencent.mtt.hippy.utils.LogUtils;

import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -252,12 +251,18 @@ public void replaceID(int oldId, int newId) {
}


public void measureInWindow(int id, Promise promise) {
public void measureInWindow(int id, JSObject options, Promise promise) {
RenderNode renderNode = mNodes.get(id);
if (renderNode == null) {
promise.reject("this view is null");
if (options.get(RenderNode.KEY_COMPATIBLE) == Boolean.TRUE) {
promise.reject("this node is null");
} else {
JSObject result = new JSObject();
result.set(RenderNode.KEY_ERR_MSG, "this node is null");
promise.reject(result);
}
} else {
renderNode.measureInWindow(promise);
renderNode.measureInWindow(options, promise);

addNullUINodeIfNeeded(renderNode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,28 @@
package com.tencent.mtt.hippy.uimanager;

import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseArray;
import android.view.View;
import com.tencent.mtt.hippy.HippyRootView;
import com.tencent.mtt.hippy.common.HippyArray;
import com.tencent.mtt.hippy.common.HippyMap;
import com.tencent.mtt.hippy.dom.node.NodeProps;
import com.tencent.mtt.hippy.modules.Promise;
import com.tencent.mtt.hippy.runtime.builtins.JSObject;
import com.tencent.mtt.hippy.utils.LogUtils;

import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

@SuppressWarnings({"deprecation", "unused"})
public class RenderNode {

public static final String KEY_COMPATIBLE = "compatible";
public static final String KEY_REL_TO_CONTAINER = "relToContainer";
public static final String KEY_ERR_MSG = "errMsg";
final int mId;
int mX;
int mY;
Expand All @@ -46,7 +54,7 @@ public class RenderNode {

SparseArray<Integer> mDeletedIdIndexMap;

List<Promise> mMeasureInWindows = null;
List<Pair<JSObject, Promise>> mMeasureInWindows = null;
Object mTextExtra;
Object mTextExtraUpdate;

Expand Down Expand Up @@ -343,8 +351,13 @@ public int compare(RenderNode o1, RenderNode o2) {
}
if (mMeasureInWindows != null && mMeasureInWindows.size() > 0) {
for (int i = 0; i < mMeasureInWindows.size(); i++) {
Promise promise = mMeasureInWindows.get(i);
mComponentManager.measureInWindow(mId, promise);
Pair<JSObject, Promise> pair = mMeasureInWindows.get(i);
if (pair.first.get(KEY_COMPATIBLE) == Boolean.TRUE) {
mComponentManager.measureInWindow(mId, pair.second);
} else {
boolean relToContainer = pair.first.get(KEY_REL_TO_CONTAINER) == Boolean.TRUE;
mComponentManager.getBoundingClientRect(mId, mRootView, relToContainer, pair.second);
}
}
mMeasureInWindows.clear();
mMeasureInWindows = null;
Expand All @@ -368,11 +381,11 @@ public void updateLayout(int x, int y, int w, int h) {
mHasUpdateLayout = true;
}

public void measureInWindow(Promise promise) {
public void measureInWindow(JSObject options, Promise promise) {
if (mMeasureInWindows == null) {
mMeasureInWindows = new ArrayList<>();
}
mMeasureInWindows.add(promise);
mMeasureInWindows.add(new Pair<>(options, promise));
}


Expand Down
16 changes: 15 additions & 1 deletion docs/en-us/hippy-react/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,4 +468,18 @@ Measure the size and position of a component within the scope of the App window.

`(ref, callback: Function) => Promise`

>- callback: ({ x, y, width, height }| string |-1) => void - Callback function, its parameters can get the coordinate value, width and height of the referenced component within the scope of the App window. May return -1 or a string with `this view is null` in case of error or [node is optimized (Android only)](hippy-react/components?id=样式内特殊属性).
>- callback: ({ x, y, width, height }| string |-1) => void - Callback function, its parameters can get the coordinate value, width and height of the referenced component within the scope of the App window. May return -1 or a string with `this view is null` in case of error or [node is optimized (Android only)](style/layout?id=collapsable).
### UIManagerModule.getBoundingClientRect

[[getBoundingClientRect example]](//github.com/Tencent/Hippy/tree/master/examples/hippy-react-demo/src/modules/UIManagerModule/index.jsx)

> Minimum supported version `2.15.3`, `measureInWindow` and `measureInAppWindow` will be deprecated soon.
Measure the size and position of a component within the scope of the App Container(RootView) or App Window(Screen).

`(instance: ref, options: { relToContainer: boolean }) => Promise<DOMRect: { x: number, y: number, width: number, height: number, bottom: number, right: number, left: number, top: number }>`

> - instance: reference of the element of component.
> - options: optional,`relToContainer` indicates whether to be measured relative to the App Container(RootView), default is `false`, meaning relative to App Window(Screen).
> - DOMRect: same with [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect) introduction, which can get the size and position of a component. If something goes wrong or [the node is optimized (Android only)](style/layout?id=collapsable), `Promise.reject` error will be thrown.
20 changes: 17 additions & 3 deletions docs/en-us/hippy-vue/vue-native.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ Attributes:

Gets the CSS style for a concrete node.

> Minimum Supported Version 2.10.1
> Minimum Supported Version `2.10.1`
`(ref: ElementNode) => {}`

Expand All @@ -294,7 +294,7 @@ console.log(Vue.Native.getElemCss(this.demon1Point)) // => { height: 80, left: 0

Can do the corresponding operations to the remote image through this module.

> Minimum Supported Version 2.7.0
> Minimum Supported Version `2.7.0`
## Methods

Expand All @@ -314,7 +314,7 @@ Can do the corresponding operations to the remote image through this module.

# measureInAppWindow

> Minimum Supported Version 2.11.0
> Minimum Supported Version `2.11.0`
Measure the size and position of a component within the scope of the App window. Note that this method can be called only after the node instance is actually displayed (after the layout event).

Expand All @@ -324,6 +324,20 @@ Measure the size and position of a component within the scope of the App window.
---

# getBoundingClientRect

> Minimum supported version `2.15.3`, `measureInWindow` and `measureInAppWindow` will be deprecated soon.
Measure the size and position of a component within the scope of the App Container(RootView) or App Window(Screen).

`(instance: ref, options: { relToContainer: boolean }) => Promise<DOMRect: { x: number, y: number, width: number, height: number, bottom: number, right: number, left: number, top: number }>`

> * instance: reference of the element of component.
> * options: optional,`relToContainer` indicates whether to be measured relative to the App Container(RootView). Default is `false`, meaning relative to App Window(Screen).
> * DOMRect: same with [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect) introduction, which can get the size and position of a component. If something goes wrong or [the node is optimized (Android only)](style/layout?id=collapsable), `Promise.reject` error will be thrown.
---

# NetInfo

Through the interface can obtain the current equipment network status, also can register a listener. When the system network switches, you will get a notice.
Expand Down
14 changes: 14 additions & 0 deletions docs/hippy-react/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,3 +469,17 @@ AsyncStorage 是一个简单的、异步的、持久化的 Key-Value 存储系
`(ref, callback: Function) => Promise`

> - callback: ({ x, y, width, height } | string | -1) => void - 回调函数, 参数可以获取到引用组件在 App 窗口范围内的坐标值和宽高,如果出错或者 [节点被优化(仅在Android)](style/layout?id=collapsable)可能返回 -1 或者 `this view is null` 字符串
### UIManagerModule.getBoundingClientRect

[[getBoundingClientRect 范例]](//github.com/Tencent/Hippy/tree/master/examples/hippy-react-demo/src/modules/UIManagerModule/index.jsx)

> 最低支持版本 `2.15.3`,原有 `measureInWindow``measureInAppWindow` 将逐渐废弃
测量元素在宿主容器(RootView) 或 App 窗口(屏幕)范围内的尺寸和位置。

`(instance: ref, options: { relToContainer: boolean }) => Promise<DOMRect: { x: number, y: number, width: number, height: number, bottom: number, right: number, left: number, top: number }>`

> - instance: 元素或组件的引用 Ref。
> - options: 可选参数,`relToContainer` 表示是否相对宿主容器(RootView)进行测量,默认 `false` 相对 App 窗口或屏幕进行测量。
> - DOMRect: 与 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect) 一致的返回参数, 可以获取元素相应的位置信息和尺寸,如果出错或者 [节点被优化(仅在Android)](style/layout?id=collapsable),会触发 `Promise.reject`
20 changes: 17 additions & 3 deletions docs/hippy-vue/vue-native.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ Hippy 中通过 fetch 服务返回的 `set-cookie` Header 会自动将 Cookie

获取具体节点的 CSS 样式。

> 最低支持版本 2.10.1
> 最低支持版本 `2.10.1`
`(ref: ElementNode) => {}`

Expand All @@ -294,7 +294,7 @@ console.log(Vue.Native.getElemCss(this.demon1Point)) // => { height: 80, left: 0

通过该模块可以对远程图片进行相应操作

> 最低支持版本 2.7.0
> 最低支持版本 `2.7.0`
## 方法

Expand All @@ -314,7 +314,7 @@ console.log(Vue.Native.getElemCss(this.demon1Point)) // => { height: 80, left: 0

# measureInAppWindow

> 最低支持版本 2.11.0
> 最低支持版本 `2.11.0`
测量在 App 窗口范围内某个组件的尺寸和位置,注意需要保证节点实例真正上屏后(layout事件后)才能调用该方法。

Expand All @@ -324,6 +324,20 @@ console.log(Vue.Native.getElemCss(this.demon1Point)) // => { height: 80, left: 0
---

# getBoundingClientRect

> 最低支持版本 `2.15.3`,原有 `measureInWindow``measureInAppWindow` 将逐渐废弃
测量元素在宿主容器(RootView)或者 App 窗口(屏幕)范围内的尺寸和位置。

`(instance: ref, options: { relToContainer: boolean }) => Promise<DOMRect: { x: number, y: number, width: number, height: number, bottom: number, right: number, left: number, top: number }>`

> * instance: 元素或组件的引用 Ref。
> * options: 可选参数,`relToContainer` 表示是否相对宿主容器(RootView)进行测量,默认 `false` 相对 App 窗口或屏幕进行测量。
> * DOMRect: 与 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect) 一致的返回参数, 可以获取元素相应的位置信息和尺寸,如果出错或者 [节点被优化(仅在Android)](style/layout?id=collapsable),会触发 `Promise.reject`
---

# NetInfo

通过该接口可以获得当前设备的网络状态;也可以注册一个监听器,当系统网络切换的时候,得到网络变化通知。
Expand Down
2 changes: 1 addition & 1 deletion examples/android-demo/res/index.android.js

Large diffs are not rendered by default.

Loading

0 comments on commit 6898861

Please sign in to comment.