Лучший способ: сохранить и восстановить позицию TextView в ScrollView
я хочу, чтобы после изменения ориентации устройства верхняя линия на экране, когда в портрете остается верхней линией на экране в ландшафте. И наоборот.
поскольку ширина экрана, вероятно, будет отличаться между портретом и пейзажем, ширина строки текста, что означает также ширину TextView
и ScrollView
, будет меняться. Таким образом, линейная обертка будет отличаться в разных конфигурациях экрана (портрет против пейзажа, большой против малого). Этот line-break будет находиться в разных местах в разных случаях.
три не подходит решения для вашей справки. Также объясняются их недостатки.
во-первых, самый основной подход:
(1), просто сохраняя y-смещение в пикселе
пожалуйста, взгляните на: http://eliasbland.wordpress.com/2011/07/28/how-to-save-the-position-of-a-scrollview-when-the-orientation-changes-in-android/
почему это не столь совершенной:
в портрете, линии обернуты.
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_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_2_Word_A
(вверху экрана) в портрете при сохранении. При изменении ландшафта, он будет показывать Line_3_Word_A
(at экран сверху). (из-за две-линии-смещение-в-пиксель сверху.)
тогда я придумываю подход,
(2) путем сохранения процента прокрутки
@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()));
}
});
}
работает отлично если и только если длина каждой строки одинакова.
почему это не столь совершенной:
в портрете, линии обернуты.
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
представьте, что Вы читаете Line_2_Word_A
(вверху экрана) в портрете при сохранении. При изменении ландшафта, он будет показывать Line_3_Word_A
(вверху экрана). (потому что он прокручивается на 50%.)
затем я нашел этот подход, который действительно
(3) сохранение первой видимой строки
пожалуйста, взгляните на (первый ответ):как восстановить положение прокрутки textview после экрана ротация?
почему это не столь совершенной:
в портрете, линии обернуты.
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
представьте, что Вы читаете Line_1_Word_E
(вверху экрана) в портрете при сохранении. При изменении ландшафта, он будет показывать Line_3_Word_A
(вверху экрана). (потому что это третья линия.)
идеальный был бы, в ландшафте, показ Line_1_Word_A
(а также Line_1_Word_E
) в верхней части экрана.
не могли бы вы предложить идеальный подход?
Edit:
после нескольких мыслей, является ли метод (3) идентичным методу (1) на самом деле? :-/
Edit 2:
Ну, я только что придумал другой не-так-идеально-еще-более-идеально подход, чем выше три:
(4) на основе абзацев хранение
разделение абзацев (или блоков текстов) на различные объекты TextView.
затем с помощью кодов, таких как метод (3), или любым другим способом нетрудно определить, какой абзац (или блок), т. е. какой объект TextView, в настоящее время находится в верхней части экрана.
затем восстановите и прокрутите вниз до этого абзаца (или блока). Бинго!
как я уже сказал, это не подходит. Но, по крайней мере, пользователи могут вернитесь к тому абзацу (или блоку), который он/она читал. Ему / ей просто нужно немного заглянуть вниз, чтобы найти эту конкретную линию. (или, возможно, еще лучше напомнить читателям несколько предыдущих строк, т. е. чтение с начала абзаца.) я знаю, что это может быть ужасно плохо, если у нас есть длинный длинный длинный абзац : -/
Ну, мы действительно можем "улучшить" этот метод. Сделайте это до уровня word, слово TextView. Так что это логически "идеально". Но, думаю, это это не мудрый выбор.
П. С. ванная комната-это всегда самое лучшее место для "мозговой атаки" ( -:
я еще ищу ваш идеальный ответ!!
1 ответов
ВАУ ВАУ ВАУ-Эй, ребята! я так горжусь тем, что у меня есть идеальное решение для этого сейчас * * * * *
ВГ.... (простите, я слишком взволнован. Если вы найдете какие-либо ошибки/ошибки/слабость на нем, пожалуйста, дайте мне ваши ценные предложения и, пожалуйста, не стесняйтесь исправить меня. :-)
завязывай. Вот, держи !!!
@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);
}
});
}
вот именно. :-)
Если это помогает вам, пожалуйста, хлопайте в ладоши. - это важно!!
и если вы хотите, нажмите на этот маленький вертикальный треугольник. (сначала убедитесь, что вы хлопнули в ладоши!)
спасибо,
midnite