6

在我的 Android 布局中,我有一个 TextView。这个 TextView 正在显示一个相当大的可跨文本并且它能够滚动。现在,当手机旋转时,视图被销毁并创建,我必须再次 setText() TextView,将滚动位置重置为开头。

我知道我可以使用 getScrolly() 和 scrollTo() 滚动到像素位置,但是由于视图宽度的变化,线条变得更长,并且位于像素位置 400 的线条现在可能位于 250。所以这不是很有帮助。

我需要一种方法来在 onDestroy() 的 TextView 中找到第一条可见行,然后在旋转后让 TextView 滚动到这段特定的文本。

有任何想法吗?

4

3 回答 3

15

这是一个老问题,但我在寻找相同问题的解决方案时来到了这里,所以这就是我想出的。我结合了这三个问题的答案的想法:

我试图只从我的应用程序中提取相关代码,所以请原谅任何错误。另请注意,如果您旋转到横向并返回,它可能不会在您开始的相同位置结束。例如,说“彼得”是肖像中第一个可见的词。当您旋转到横向时,“Peter”是其行中的最后一个单词,第一个是“Larry”。当您向后旋转时,“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

最好的答案,我通过搜索得到。

@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 回答