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);
    }
}

getHitRect1 レベル上の親に対する座標を返すことに注意してください。したがって、上記のコードは機能します。

ただし、やや複雑なケースになると。上記のコードは機能しなくなりました。

<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 1を考慮する必要がありますgetHitRectInfo View 4-6 に関して言えば、 LinearLayout 0LinearLayout 2について考慮する必要がありますgetHitRect

物事は面倒に見えます。一番上を基準にしてビューの座標を取得する方法はあります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);
    }
}

getLocationInWindowgetLocationOnScreenおよびもテストしまし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を取ります。ActionBar、またはStatusBar高さが寄与していると思います。

getLocationOnScreen

と同じ動作getLocationInWindow

getLocalVisibleRect

行が画面に完全に表示されていない場合にのみ、期待値と同じ値が取得されます。理由がわからない。最後の行を見てください。ここでは、予想される下部 y と同じ下部 y 値 (485) を持っています。

于 2013-03-21T07:50:43.467 に答える