6

私の Android レイアウトには、TextView があります。この TextView はかなり大きなスパン可能なテキストを表示しており、スクロールできます。電話が回転すると、View が破棄されて作成され、TextView を再度 setText() して、スクロール位置を最初にリセットする必要があります。

getScrolly() と scrollTo() を使用してピクセル位置にスクロールできることはわかっていますが、ビューの幅が変更されたため、行が長くなり、ピクセル位置が 400 だった行が 250 になる可能性があります。役に立った。

onDestroy() の TextView で最初に表示されている行を見つける方法と、回転後に TextView をこの特定のテキストにスクロールさせる方法が必要です。

何か案は?

4

3 に答える 3

15

これは古い質問ですが、同じ問題の解決策を探すときにここにたどり着いたので、これが私が思いついたものです。私はこれらの3つの質問に対する答えからのアイデアを組み合わせました:

アプリから関連するコードのみを抽出しようとしましたので、エラーはご容赦ください。また、横向きに回転して戻ると、開始した位置と同じ位置で終了しない場合があることに注意してください。たとえば、「Peter」がポートレートで最初に表示される単語であるとします。横向きに回転すると、「Peter」がその行の最後の単語で、最初の単語が「Larry」です。後ろに回転すると、「ラリー」が表示されます。

private static float scrollSpot;

private ScrollView scrollView;
private TextView textView;

protected void onCreate(Bundle savedInstanceState) {
    textView = new TextView(this);
    textView.setText("Long text here...");
    scrollView = new ScrollView(this);
    scrollView.addView(textView);

    // You may want to wrap this in an if statement that prevents it from
    // running at certain times, such as the first time you launch the 
    // activity with a new intent.
    scrollView.post(new Runnable() {
        public void run() {
            setScrollSpot(scrollSpot);
        }
    });

    // more stuff here, including adding scrollView to your main layout
}

protected void onDestroy() {
    scrollSpot = getScrollSpot();
}

/**
 * @return an encoded float, where the integer portion is the offset of the
 *         first character of the first fully visible line, and the decimal
 *         portion is the percentage of a line that is visible above it.
 */
private float getScrollSpot() {
    int y = scrollView.getScrollY();
    Layout layout = textView.getLayout();
    int topPadding = -layout.getTopPadding();
    if (y <= topPadding) {
        return (float) (topPadding - y) / textView.getLineHeight();
    }

    int line = layout.getLineForVertical(y - 1) + 1;
    int offset = layout.getLineStart(line);
    int above = layout.getLineTop(line) - y;
    return offset + (float) above / textView.getLineHeight();
}

private void setScrollSpot(float spot) {
    int offset = (int) spot;
    int above = (int) ((spot - offset) * textView.getLineHeight());
    Layout layout = textView.getLayout();
    int line = layout.getLineForOffset(offset);
    int y = (line == 0 ? -layout.getTopPadding() : layout.getLineTop(line))
        - above;
    scrollView.scrollTo(0, y);
}
于 2013-01-17T20:57:11.313 に答える
1

TextView は、その状態を保存および復元できます。それを使用できない場合は、それを無効にして明示的にメソッドを呼び出すことができます:

http://developer.android.com/reference/android/widget/TextView.SavedState.html http://developer.android.com/reference/android/widget/TextView.html#onSaveInstanceState() http://developer. android.com/reference/android/widget/TextView.html#onRestoreInstanceState(android.os.Parcelable )

于 2011-03-21T19:06:05.617 に答える
0

The best answer, I got by searching.

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
final ScrollView scrollView = (ScrollView) findViewById(R.id.Trial_C_ScrollViewContainer);
outState.putFloatArray(ScrollViewContainerScrollPercentage,
        new float[]{
        (float) scrollView.getScrollX()/scrollView.getChildAt(0).getWidth(),
        (float) scrollView.getScrollY()/scrollView.getChildAt(0).getHeight() });
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
final float[] scrollPercentage = savedInstanceState.getFloatArray(ScrollViewContainerScrollPercentage);
final ScrollView scrollView = (ScrollView) findViewById(R.id.Trial_C_ScrollViewContainer);
scrollView.post(new Runnable() {
    public void run() {
        scrollView.scrollTo(
                Math.round(scrollPercentage[0]*scrollView.getChildAt(0).getWidth()),
                Math.round(scrollPercentage[1]*scrollView.getChildAt(0).getHeight()));
    }
});

}

于 2021-10-21T04:50:20.283 に答える