1

在 Android 布局中,它有一个包含 LinearLayout 的 RelativeLayout(忽略布局中的一些其他视图)。

< ...> //other layout
<NestedScrollView
                android:id="@+id/scroll_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scrollbars="none"
                android:fillViewport="false">

                <RelativeLayout
                    android:id="@+id/view_root"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:paddingTop="0dp">
                    <LinearLayout
                        android:id="@+id/list_container"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                    
                        />
                </RelativeLayout>

            </NestedScrollView>
<...>//other layout

list_container可能有几个视图,一个是 webView 。想要做的是在 webview 加载的 html 中,有一个 div 元素,所以 android 端可以定位这个 div 并在该 div 元素顶部浮动一个视图(<div>被视为位置标记)。

使其更简单,假设 中只有一个 webview list_container,因此originwebview 视图的 与 relativeLayout 的左/上相同。

并且有一些浮动 View 是 RelativeLayout 的子级(的兄弟list_container),因此想法是设置floatingView左/上边距以将 floatingView 放置<div>在 html 中的元素上。

这里使用webview.evaluateJavascript运行 javascript,并通过回调获取元素的位置(从 js 的 document.getElementById(elm.id).getBoundingClientRect() 获取,之后,只需将左侧/顶部应用于浮动视图利润。

val strJs = "(function() {\n" +
                "var elementId = 'element_div_id';\n" +
                "try {\n" +
                "   var elm = document.getElementById(elementId);\n" +
                "   var rect = document.getElementById(elm.id).getBoundingClientRect();\n" +
                "   return {\n" +
                "       'elementId': elm.id,\n" +
                "       'left': Math.floor(rect.left),\n" +
                "       'top': Math.floor(rect.top)\n" +
                "   };\n" +
                "} catch (e) {}\n" +
                "return '';})();"
        
        
        webview.evaluateJavascript(strJs) { data ->
            if (!data.isNullOrBlank() && data.isNotEmpty()) {
                try {
                    val obj: JSONObject = JSONObject(data)
                    val floatViewId = obj.optString("elementId")
                    val left = obj.optInt("left")
                    val top = obj.optInt("top")

                    val theFloatingView = lookupFloatingViewById(floatViewId)
                    var lp = (theFloatingView.layoutParams)
                    if (lp != null) {
                        if (lp.leftMargin != left || lp.topMargin != top) {
                            lp.setMargins(left, top, 0, 0)
                            theFloatingView.layoutParams = lp
                        }
                    }
                    
                } catch (ex: Throwable) {
                   
                }
            }
        }

但结果是浮动视图没有放置在返回的 html<div>元素的left/top处,它在 html 内容的不同部分上处于关闭状态(在不同的设备上,关闭可能更大或更小)。

不是 webview 和 webview 中托管的 html 都应该具有相同的来源(实际上与 relativeLayout 的 lefty/top 相同)吗?为什么我们不能直接使用从 html dom 的getBoundingClientRect()获得的left/top作为视图的边距(用于定位视图)?

4

1 回答 1

1

找到了解决类似问题的答案。似乎 Android 视图与 html 窗口的坐标不同。(有人可以确认或有人有不同的意见吗?)

返回的位置getBoundingClientRect()需要重新映射到android的坐标。

       final int px = (int) (x * ctx.getResources().getDisplayMetrics().density);
       final int py = (int) (y * ctx.getResources().getDisplayMetrics().density);

于 2020-07-16T11:40:48.417 回答