Android 最好的方法:节省和;恢复ScrollView中的TextView位置
我想要的是,当设备改变方向时,纵向屏幕上的顶线仍然是横向屏幕上的顶线。反之亦然 由于纵向和横向屏幕的宽度可能不同,因此文本的线宽(也就是Android 最好的方法:节省和;恢复ScrollView中的TextView位置,android,android-layout,textview,android-orientation,android-scrollview,Android,Android Layout,Textview,Android Orientation,Android Scrollview,我想要的是,当设备改变方向时,纵向屏幕上的顶线仍然是横向屏幕上的顶线。反之亦然 由于纵向和横向屏幕的宽度可能不同,因此文本的线宽(也就是TextView和ScrollView的宽度)会有所不同。因此,在不同的屏幕配置(纵向与横向、大屏幕与小屏幕)中,换行将不同。在不同的情况下,断线将位于不同的位置 有三个不太完美的解决方案供您参考。也解释了它们的缺点 首先,最基本的方法是: (1) 只需以像素为单位存储y偏移 请看: 为什么这不是那么完美: 在肖像画中,线条被包裹 Line_1_Word_A
TextView
和ScrollView
的宽度)会有所不同。因此,在不同的屏幕配置(纵向与横向、大屏幕与小屏幕)中,换行将不同。在不同的情况下,断线将位于不同的位置
有三个不太完美的解决方案供您参考。也解释了它们的缺点
首先,最基本的方法是: (1) 只需以像素为单位存储y偏移 请看: 为什么这不是那么完美: 在肖像画中,线条被包裹
Line_1_Word_A Line_1_Word_B Line_1_Word_C
Line_1_Word_D
Line_2_Word_A Line_2_Word_B Line_2_Word_C
Line_2_Word_D
Line_3_Word_A Line_3_Word_B Line_3_Word_C
Line_3_Word_D
Line_1_Word_A Line_1_Word_B
Line_1_Word_C Line_1_Word_D
Line_1_Word_E Line_1_Word_F
Line_2_Word_A
Line_3_Word_A
Line_4_Word_A
Line_1_Word_A Line_1_Word_B
Line_1_Word_C Line_1_Word_D
Line_1_Word_E Line_1_Word_F
Line_2_Word_A
Line_3_Word_A
Line_4_Word_A
在风景画中,线条不被包裹
想象一下,在保存的同时,在纵向中阅读行2\u字A
(在屏幕顶部)。当更改为横向时,它将显示行\u 3\u单词\u A
(在屏幕顶部)。(因为两条线在像素上从顶部偏移。)
然后我想出了一个方法 (2) 通过保存滚动百分比 当且仅当每条线的长度相同时,此方法才能完美工作 为什么这不是那么完美: 在肖像画中,线条被包裹
Line_1_Word_A Line_1_Word_B Line_1_Word_C
Line_1_Word_D
Line_2_Word_A Line_2_Word_B Line_2_Word_C
Line_2_Word_D
Line_3_Word_A Line_3_Word_B Line_3_Word_C
Line_3_Word_D
Line_1_Word_A Line_1_Word_B
Line_1_Word_C Line_1_Word_D
Line_1_Word_E Line_1_Word_F
Line_2_Word_A
Line_3_Word_A
Line_4_Word_A
Line_1_Word_A Line_1_Word_B
Line_1_Word_C Line_1_Word_D
Line_1_Word_E Line_1_Word_F
Line_2_Word_A
Line_3_Word_A
Line_4_Word_A
在风景画中,线条不被包裹
想象一下,在保存的同时,在纵向中阅读行2\u字A
(在屏幕顶部)。当更改为横向时,它将显示行\u 3\u单词\u A
(在屏幕顶部)。(因为它滚动了50%。)
然后我发现这个方法确实 (3) 存储第一个可见行 请看(第一个答案): 为什么这不是那么完美: 在肖像画中,线条被包裹
Line_1_Word_A Line_1_Word_B Line_1_Word_C
Line_1_Word_D
Line_2_Word_A Line_2_Word_B Line_2_Word_C
Line_2_Word_D
Line_3_Word_A Line_3_Word_B Line_3_Word_C
Line_3_Word_D
Line_1_Word_A Line_1_Word_B
Line_1_Word_C Line_1_Word_D
Line_1_Word_E Line_1_Word_F
Line_2_Word_A
Line_3_Word_A
Line_4_Word_A
Line_1_Word_A Line_1_Word_B
Line_1_Word_C Line_1_Word_D
Line_1_Word_E Line_1_Word_F
Line_2_Word_A
Line_3_Word_A
Line_4_Word_A
在风景画中,线条不被包裹
想象一下,在保存时,在纵向中阅读行1\u单词E
(在屏幕顶部)。当更改为横向时,它将显示行\u 3\u单词\u A
(在屏幕顶部)。(因为这是第三行。)
一个完美的方法是,在横向视图中,在屏幕顶部显示行单词A
(以及行单词E
)
你能建议一个完美的方法吗
编辑: 经过几番思考,方法(3)与方法(1)实际上是相同的吗-/
编辑2: 好吧,我刚刚提出了另一种不太完美但比上述三种更完美的方法: (4) 基于段落的存储 将段落(或文本块)分隔为不同的TextView对象 然后,通过类似方法(3)的代码或任何其他方式,不难检测当前屏幕顶部的段落(或块),即哪个TextView对象 然后还原并向下滚动到该段落(或块)。宾果 正如我所说,它并不完美。但至少用户可以回到他/她正在阅读的段落(或区块)。他/她只需往下看一眼就可以找到那一行。(或者最好用前面几行来提醒读者,即从段落的开头开始阅读。)我知道如果我们有一个很长的段落,可能会非常糟糕:-/ 实际上,我们可以“改进”这种方法。把它降到单词级,一个单词一个文本视图。因此,它在逻辑上是“完美的”。但是,我想,这不是一个明智的选择 洗手间总是头脑风暴的最佳场所(-:
我仍然在寻找你的完美答案!!我很自豪地说,我现在找到了一个完美的解决方案 Sh…(对不起,我对此太激动了。如果您发现任何错误/bug/弱点,请给我您的宝贵建议,并请随时纠正我。:-) 少说废话,给你
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
final ScrollView scrollView = (ScrollView) findViewById(R.id.Trial_C_ScrollViewContainer);
final TextView textView = (TextView) scrollView.getChildAt(0);
final int firstVisableLineOffset = textView.getLayout().getLineForVertical(scrollView.getScrollY());
final int firstVisableCharacterOffset = textView.getLayout().getLineStart(firstVisableLineOffset);
outState.putInt(ScrollViewContainerTextViewFirstVisibleCharacterOffset, firstVisableCharacterOffset);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
final int firstVisableCharacterOffset = savedInstanceState.getInt(ScrollViewContainerTextViewFirstVisibleCharacterOffset);
final ScrollView scrollView = (ScrollView) findViewById(R.id.Trial_C_ScrollViewContainer);
scrollView.post(new Runnable() {
public void run() {
final TextView textView = (TextView) scrollView.getChildAt(0);
final int firstVisableLineOffset = textView.getLayout().getLineForOffset(firstVisableCharacterOffset);
final int pixelOffset = textView.getLayout().getLineTop(firstVisableLineOffset);
scrollView.scrollTo(0, pixelOffset);
}
});
}
就这样。:-)
如果对你有帮助,请拍手。取最小android设备的像素密度,然后乘以设备的纵向宽度。然后计算出适合该行的单词数,并相应地换行(您可能希望将其保存并在
onrestoreinnstancestate()
中使用)。您希望在纵向和横向中实现相同的换行-对吗?感谢@g00dy的回复。但在大多数情况下,纵向和横向的线条环绕(水平宽度)并不相同。如果是相同的,我们没有头痛:-)是的,我理解:-)但是我仍然不确定你是否想要相同的线包装用于纵向和横向-请首先确认。相同的线包装是否意味着在每条线的同一点断线?对于这一点,不。@midnite:我的解决方案考虑是否在顶部显示部分线,并将其恢复,以便在旋转后再次显示相同部分的线。如果第一行是完全可见的,它反而(重新)存储可见的顶部填充部分。我喜欢你的热情!你为什么不直接用getScrollY呢?谢谢隐马尔可夫模型。。。AFAI大多数文本(网页除外)只是垂直滚动。修改这些代码来处理水平滚动也不难:)ScrollView
(以及任何与此相关的视图)必须有一个id才能被Android持久化。你不应该这么做。在scrollview中添加id将强制android保存/恢复其状态,包括滚动位置。看看这个:这也适用于NestedScrollView
@dnkoutso:当定义@+id
强制Android保持滚动位置时,它不考虑单词包装@midnite解决方案几乎完美地工作(由于文本重新排列,出现了一些像素脱落,但并不严重)。