Я хочу, чтобы при изменении ориентации устройства верхняя строка на экране, когда в Portrait остается верхней строкой на экране в Landscape. И наоборот.
Поскольку ширина экрана может быть разной между Portrait и Landscape, ширина строки текста, а это означает также ширину TextView
и ScrollView
, будет отличаться. Таким образом, перенос строк будет отличаться в разных конфигурациях экрана (Portrait and Landscape, large vs. small). Разрыв линии будет в другом положении в разных случаях.
Для вашей справки есть три не очень совершенных решения. Также объяснили их недостатки.
Во-первых, самый простой подход:
(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
(вверху экрана) в Portrait при сохранении. Когда он будет изменен на Landscape, он Line_3_Word_A
(сверху экрана). (Из-за двухстрочного смещения в пикселях сверху).
Затем я придумываю подход,
(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
(вверху экрана) в Portrait при сохранении. Когда он будет изменен на Landscape, он Line_3_Word_A
(сверху экрана). (Потому что он прокручивается на 50%.)
Затем я нашел такой подход, который действительно
(3) Сохранение первой видимой строки
Пожалуйста, взгляните на (первый ответ): Как восстановить положение прокрутки текста после поворота экрана?
Почему это не так прекрасно:
В портрете строки завернуты.
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
(вверху экрана) в Portrait при сохранении. Когда он будет изменен на Landscape, он Line_3_Word_A
(сверху экрана). (Потому что это третья строка.)
Идеально было бы в Пейзаже, показывая Line_1_Word_A
(а также Line_1_Word_E
) на экране.
Не могли бы вы предложить идеальный подход?
Редактировать:
После нескольких мыслей, действительно ли метод (3) идентичен методу (1)? : -/
Изменить 2:
Ну, я только что придумал еще один не очень совершенный, но еще более совершенный подход, чем предыдущие три:
(4) Сохранение на основе абзаца
Разделение абзацев (или блоков текстов) на разные объекты TextView.
Затем по кодам, подобным методу (3), или любым другим способом, нетрудно определить, какой абзац (или блок), т.е. Какой объект TextView, в настоящее время находится в верхней части экрана.
Затем восстановите и прокрутите список до этого абзаца (или блока). Бинго!
Как я уже сказал, это не так прекрасно. Но, по крайней мере, пользователи могут вернуться к тому абзацу (или блоку), который он читал. Он/она просто должен немного подглядеть, чтобы найти эту конкретную линию. (Или может быть даже лучше напомнить читателям несколько предыдущих строк, то есть прочитать с начала абзаца.) Я знаю, что это может быть ужасно плохо, если у нас длинный длинный абзац: -/
Ну, мы можем "улучшить" этот метод. Сделайте это до уровня слова, слово TextView. Поэтому он логически "совершенен". Но, я думаю, это не разумный выбор.
PS ванная всегда лучшее место для мозгового штурма (-: