屏幕旋转后如何恢复textview滚动位置?

发布于 2024-10-24 02:25:24 字数 326 浏览 5 评论 0原文

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

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

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

有什么想法吗?

In my Android Layout, I have a TextView. This TextView is displaying a rather large spannable text and it is able to scroll. Now when the phone is rotated, the View is destroyed and created and I have to setText() the TextView again, resetting the scroll position to the beginning.

I know I can use getScrolly() and scrollTo() to scroll to pixel positions, but due to the change in View widths, lines become longer and a line that was at pixel pos 400 might now be at 250. So this is not very helpful.

I need a way to find the first visible line in a TextView in onDestroy() and then a way to make the TextView scroll to this specific piece of text after the rotation.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情泪▽动烟 2024-10-31 02:25:24

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

我尝试从我的应用程序中仅提取相关代码,因此请原谅任何错误。另请注意,如果您旋转到横向并返回,它可能不会以您开始的位置结束。例如,假设“Peter”是肖像中第一个可见的单词。当您旋转到横向时,“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);
}

This is an old question, but I landed here when searching for a solution to the same problem, so here is what I came up with. I combined ideas from answers to these three questions:

I tried to extract only the relevant code from my app, so please forgive any errors. Also note that if you rotate to landscape and back, it may not end in the same position you started. For example, say "Peter" is the first visible word in portrait. When you rotate to landscape, "Peter" is the last word on its line, and the first is "Larry". When you rotate back, "Larry" will be visible.

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);
}
三五鸿雁 2024-10-31 02:25:24

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)

TextView can save and restore its state for you. If you aren't able to use that, you can disable that and explicitly call the methods:

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)

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

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

}

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

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文