6

以前,我有以下ScrollView和布局。它的滚动直到选定的视图可见代码有效。

<ScrollView>
    <LinearLayout>
        <Info View 1/>
        <Info View 2/>
        <Info View 3/>
    </LinearLayout>
</ScrollView>

private void initScrollView() {
    if (this.selectedInfoView == null) {
        // Nothing to scroll.
        return;
    }

    ScrollView scrollView = (ScrollView)this.getView().findViewById(R.id.scrollView);

    Rect rect = new Rect();
    Rect scrollViewRect = new Rect();
    selectedInfoView.getHitRect(rect);
    scrollView.getDrawingRect(scrollViewRect);
    int dy = rect.bottom - scrollViewRect.bottom;
    if (dy > 0) {
        scrollView.scrollBy(0, dy);
    }
}

注意,getHitRect将坐标返回到上一级父级。因此,上面的代码将起作用。

但是,当涉及到稍微复杂的情况时。上面的代码不再起作用。

<ScrollView>
    <LinearLayout 0>
        <TextView/>
        <LinearLayout 1>
            <Info View 1/>
            <Info View 2/>
            <Info View 3/>
        </LinearLayout>

        <TextView/>
        <LinearLayout 2>
            <Info View 4/>
            <Info View 5/>
            <Info View 6/>
        </LinearLayout>
    </LinearLayout>
</ScrollView>

在我的代码中,如果遇到Info View 1 - 3,我需要考虑LinearLayout 0LinearLayout 1getHitRect谈到Info View 4-6,我需要考虑LinearLayout 0LinearLayout 2getHitRect

事情看起来很麻烦。有什么方法可以让我获得视图的坐标,相对于 top most ScrollView

4

2 回答 2

9

这是当前可用的代码。很麻烦。但它在这一刻有效。我有几点意见。

private void initScrollView() {
    if (this.selectedInfoView == null) {
        // Nothing to scroll.
        return;
    }

    ScrollView scrollView = (ScrollView)this.getView().findViewById(R.id.scrollView);
    LinearLayout linearLayout = null;

    if (this.selectedInfo instanceof Info0) {
        linearLayout = (LinearLayout)this.getView().findViewById(R.id.linearLayout0);
    } else {
        assert(this.selectedInfo instanceof Info1);
        linearLayout = (LinearLayout)this.getView().findViewById(R.id.linearLayout1);
    }

    Rect rect = new Rect();
    Rect linearLayoutRect = new Rect();
    Rect scrollViewRect = new Rect();
    selectedInfoView.getHitRect(rect);
    linearLayout.getHitRect(linearLayoutRect);
    scrollView.getDrawingRect(scrollViewRect);

    // Get coordinate relative to linear layout. See the note below.
    int correct_expected_bottom_y = linearLayoutRect.top + rect.bottom;

    int dy = correct_expected_bottom_y  - scrollViewRect.bottom;
    if (dy > 0) {
        scrollView.scrollBy(0, dy);
    }
}

我还用getLocationInWindow,getLocationOnScreen和进行了测试getLocalVisibleRect。他们都不是万无一失的。

(x, y - 宽度, 高度)

--------------------
|                  | (?, 120) <-- correct expected bottom y
|                  | (0, 146) <-- from getLocationInWindow/ getLocationOnScreen
|                  | (0, 0 - 360, 72) <-- from getLocalVisibleRect
--------------------
|                  | (?, 193) <-- correct expected bottom y
|                  | (0, 219) <-- from getLocationInWindow/ getLocationOnScreen
|                  | (0, 0 - 360, 72) <-- from getLocalVisibleRect
--------------------
|                  | (?, 266) <-- correct expected bottom y
|                  | (0, 292) <-- from getLocationInWindow/ getLocationOnScreen
|                  | (0, 0 - 360, 72) <-- from getLocalVisibleRect
--------------------
|                  | (?, 339) <-- correct expected bottom y
|                  | (0, 365) <-- from getLocationInWindow/ getLocationOnScreen
|                  | (0, 0 - 360, 72) <-- from getLocalVisibleRect
--------------------
|                  | (?, 485) <-- correct expected bottom y
| [not visible]    | (0, 511) <-- from getLocationInWindow/ getLocationOnScreen
|                  | (0, 413 - 360, 485) <-- from getLocalVisibleRect
--------------------

getLocationInWindow

它总是比预期值多 26 个像素。例如,取第一行26 = 146 - 120。我认为这可能是由ActionBarStatusBar高度贡献的。

getLocationOnScreen

相同的行为getLocationInWindow

获取LocalVisibleRect

当行在屏幕上完全不可见时,它只会获得与预期值相同的值。不知道为什么。查看最后一行,它的底部 y 值 (485) 与预期的底部 y 相同。

于 2013-03-21T07:50:43.467 回答
1

不确定这是否在 2013 年可用,您现在可以这样做:

val bounds = Rect()
childView.getDrawingRect(bounds) // now bounds has the visible drawing coordinates of the view
parentViewGroup.offsetDescendantRectToMyCoords(childView, bounds) // now bounds has the view's coordinates according to the parentViewGroup

parentViewGroupchildView是层次结构中任何级别的父级。

于 2019-12-12T06:48:14.373 回答