На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Hsilgos
  
> Подстройка под размер экрана в Android Activity , + новый вопрос по воссозданию активити
    Всем привет!

    В моем приложении на Android есть TableLayouts, с помощью которого выводится несколько идентичных строк полей, которые пользователь должен заполнить. Пока делал логику, на размеры как-то внимания мало обращал, поставил езде фиксированные размеры по ширине с помощью android:layout_width, в пикселях. Но у шефа девайс с большим разрешением, по ширине у него все эти контролы в сумме занимают половину от всей ширины экрана, смотрится не очень. К тому же, уже есть необходимость и налаживать интерфейс, чтобы вообще было видно, на что это все будет похоже.

    Ширину текстовых полей для ввода пользователем данных планирую рассчитывать от ширины экрана, как определенные проценты, уже с шефом обсудили, какие именно. Например, на поле, куда вводится самый длинный текст - 70 процентов от ширины экрана, и еще два поля - 18% и 12%, как-то так. Но пока что не могу сообразить, как и где мне ширину полей задавать, обработчик какого события и от какого компонента надо ставить. Ведь тут еще важно учесть, что пользователь может повернуть девайс набок, и тогда было бы хорошо тоже подстроить все контролы, так как высота экрана сменится на ширину, и наоборот.

    И еще думаю по поводу TableLayoyt, как мне корректно менять ширину столбцов? Меняя ширину отдельных элементов? Или есть какой-то общий механизм?
    Сообщение отредактировано: Homez -
      Цитата Homez @
      Например, на поле, куда вводится самый длинный текст - 70 процентов от ширины экрана, и еще два поля - 18% и 12%, как-то так.

      Это что, поля в одну строку? :o Ужас какой.

      Вот как делается форма ввода в Андроиде:
      user posted image

      Сверху лейбл (TextView), внизу контрол для ввода на всю ширину.

      Для этого и LinearLayout достаточно.

      Если девайс поворачивается, то приложение в Андроиде перезапускается полностью (если конечно принудительно не обработать эту ситуацию, но смысла в этом обычно нету для простых приложений).
        Цитата [S]mike @
        Если девайс поворачивается, то приложение в Андроиде перезапускается полностью (если конечно принудительно не обработать эту ситуацию, но смысла в этом обычно нету для простых приложений).


        Что-то впервые я слышу об этом. Это что, если не обрабатывать поворот экрана, то все, что в программе было, сбрасывается нафиг?

        Наверно, мне стоило указать, какие поля-то для ввода, то есть, чего именно. Так, как Вы нарисовали - я и сам умею, делал такое:)

        Так вот, дело в том, что я говорю о полях для заполнения адреса, а именно - название улицы, номер дома и номер корпуса, три поля. Неужели вы думаете, что стоит вот так и поле для номера дома, и поле для корпуса размещать на отдельной строке и вытягивать на всю ширину? На оба этих поля хватило бы и 30 % ширины экрана. Дело в том, что промежуточных точек поездки (приложение для заказа такси) может быть до 7 включительно + 2 поля для начального и конечного адреса. Это как бы зверски пришлось прокручивать экран?

        Так что вопрос не отвечен никак. Как обрабатывать поворот экрана, получая при этом новую ширину? И как подстраивать ширину столбцов в TableLayout?
          Цитата Homez @
          Что-то впервые я слышу об этом. Это что, если не обрабатывать поворот экрана, то все, что в программе было, сбрасывается нафиг?

          Вот почему я и говорю, что нужно хотя бы в общих чертах изучить систему, под которую пытаетесь программировать. В Андроиде не работают привычные методы программирования под Windows и другие десктопные ОС. Это система, разработанная с нуля именно для мобильных приложений.

          Андроид приложение _не имеет_ контроля над своим жизненным циклом. То есть должно быть готово в любой момент быть закрытым системой. Для чего и существует такое понятие как Activity Lifecycle. По ссылке подробно объясняется, когда нужно сохранять/загружать параметры приложения (onPause/onCreate) и дается понятие, как это делать (см. Saving Persistent State).

          В случае поворота экрана старый экземпляр Activity освобождается. Он должен сохранить свое состояние. Затем система запускает новый экземпляр и приложение должно загрузить свое предыдущее состояние, таким образом изменение ориентации экрана должно проходить незаметно для конечного пользователя. Но все это отдается на откуп программисту :)

          Цитата Homez @
          Наверно, мне стоило указать, какие поля-то для ввода, то есть, чего именно. Так, как Вы нарисовали - я и сам умею, делал такое:)

          Ну и по сути это единственно верный и идеологически правильный вариант: простой в реализации и привычный для пользователя. Максимум - можно поместить несколько полей ввода в одну строку (при помощи параметра weight в LinearLayout). Но извращаться с их размерами не стОит - система сама все рассчитает. Почему еще это важно - из вопросов производительности и отсутствия дерганий в интерфейсе. Лайауты специально оптимизированы для всего этого.

          Вот как лучше всего сделать:
          Прикреплённая картинка
          Прикреплённая картинка


          Лэйаут:
          ExpandedWrap disabled
            <?xml version="1.0" encoding="utf-8"?>
            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
             
                <TextView
                    android:id="@+id/textView1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Название улицы" />
             
             
                <AutoCompleteTextView
                    android:id="@+id/autoCompleteTextView1"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:ems="10"
                    android:text="Льва Толстого" >
             
                    <requestFocus />
                </AutoCompleteTextView>
             
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:baselineAligned="false" >
             
                    <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:orientation="vertical" >
             
                        <TextView
                            android:id="@+id/textView2"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="Номер дома" />
             
                        <AutoCompleteTextView
                            android:id="@+id/autoCompleteTextView2"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:text="72" />
                    </LinearLayout>
             
                    <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:orientation="vertical" >
             
                        <TextView
                            android:id="@+id/textView3"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="Номер корпуса" />
             
                        <AutoCompleteTextView
                            android:id="@+id/autoCompleteTextView3"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:text="1" />
                    </LinearLayout>
                </LinearLayout>
             
            </LinearLayout>


          Чем плохо? Я не представляю, как на стандартной ширине экрана телефона (480 пикселей) будет отображаться 3 поля, причем одно совсем не короткое - улица (!).

          Если же непременно нужно в одну строку для экономии места, тогда берется ListView в котором с помощью адаптера отображается перечень точек маршрута. По клику пользователь может отредактировать точку маршрута в отдельном диалоге. Предусмотреть кнопку или меню для добавления точки маршрута. Но извращаться с интерфейсом редактирования таким образом не стоит:
          Цитата
          И еще думаю по поводу TableLayoyt, как мне корректно менять ширину столбцов? Меняя ширину отдельных элементов? Или есть какой-то общий механизм?

          Еще и потому что Layout плохо подходит для отображения динамических списков - для этого предназначены ListView, GridView и прочие.

          Можно конечно сделать интерфейс редактирования прямо в ListView (как в одну, так и в 2 строки), но от количества полей ввода будет рябить в глазах.
            Цитата Homez @
            Так что вопрос не отвечен никак. Как обрабатывать поворот экрана, получая при этом новую ширину? И как подстраивать ширину столбцов в TableLayout?

            Обрабатывать поворот экрана не нужно. Пишется кастомная вьюха и обрабатывается событие onMeasure. Ширина столбцов в TableLayout определяется шириной элементов. Но связываться с этим еще раз не советую ;)
              Редактирование в отдельном диалоге в программе конкурента видел, это неудобно. Шеф тоже считает, что редактирование должно производиться прямо в форме.

              480 пикселей - это не так уж и мало. Насчет техники с layout_weight я подумаю. Где-то я это уже использовал. Вроде бы для того, чтобы кнопка заказа отображалась в самом низу экрана, а не прижималась ко все компонентам на форме. Посмотрим, насколько это универсально и можно ли делать неравные соотношения длины полей. Спасибо за пример!

              Да, Вы правы, про Life Cycle надо почитать. И насчет поворота экрана - то же. Но если у меня будет работать с помощью системы весов, тогда и поворот экрана должен происходить для меня незаметно.
                С весами прокатило, вот лэйаут именно таблицы с точками поездки:

                ExpandedWrap disabled
                  <TableLayout
                          android:id="@+id/ordersTable"
                          android:layout_height="wrap_content" android:layout_width="fill_parent"
                          android:layout_weight="1" >
                          
                          <Spinner
                          android:id="@+id/spService"
                          android:layout_width="fill_parent"
                          android:layout_height="wrap_content" />
                          
                          <TableRow >
                              <TextView
                              android:id="@+id/tvFrom"
                              android:layout_width="wrap_content"
                              android:layout_height="wrap_content"
                              android:text="A">></TextView>
                              <View
                                  android:layout_height="fill_parent"
                                  android:layout_width="10px" />
                              <EditText
                                  android:id="@+id/edObjFrom"
                                  android:layout_width="0px"
                                  android:layout_height="wrap_content"
                                  android:layout_weight="70"
                                  android:text="метро Автово"
                                  android:maxLines="1"/>
                              <EditText
                                  android:id="@+id/edHouseFrom"
                                 android:layout_width="0px"
                                 android:layout_weight="18"
                                  android:layout_height="wrap_content"
                                  android:maxLines="1" />
                              <EditText
                                  android:id="@+id/edCorpFrom"
                                  android:layout_width="0px"
                                  android:layout_weight="12"
                                  android:layout_height="wrap_content"
                                  android:maxLines="1" />  
                              
                          </TableRow>
                          
                          <TableRow android:id="@+id/trTo">
                               <TextView
                              android:layout_width="wrap_content"
                              android:layout_height="wrap_content"
                              android:text="B" />
                              <View
                                  android:layout_height="fill_parent"
                                  android:layout_width="10px" />
                              <EditText
                                  android:id="@+id/edObjTo"
                                  android:layout_width="0px"
                                  android:layout_height="wrap_content"
                                  android:text="метро Чернышевская"
                                  android:layout_weight="70"
                                  android:maxLines="1" />
                              <EditText
                                  android:id="@+id/edHouseTo"
                                  android:layout_width="0px"
                                  android:layout_height="wrap_content"
                                  android:layout_weight="18"
                                  android:maxLines="1" />
                              <EditText
                                  android:id="@+id/edCorpTo"
                                  android:layout_width="0px"
                                  android:layout_height="wrap_content"
                                  android:layout_weight="12"
                                  android:maxLines="1" />  
                              
                          </TableRow>
                      </TableLayout>


                Чтобы ширина полей не менялась в зависимости от объема введенного в каждое поле текста, я задал для каждого android:layout_width="0px", видел где-то именно такую установку, наверно, на StackOvarflow, в теме, как раз касающейся схожей с моей проблемы.

                Добавлено
                А насчет поворота [S]mike оказался прав. Шеф немного покрутил. Пользовательский ввод вроде бы не теряются, но расчетные данные все сбросились:( Что ж, буду разбираться, как это пресечь.
                  Уже решил, эту проблему с поворотом и прочим, написав свой код для onSaveInstanceState() и onRestoreInstanceState(). Слава богу, что у меня задействовно не так много переменных.

                  Однако долго буксовал вот на чем. У меня есть в деятельности свой onItemSelected(), который, естественно, вызывается при пользовательском выборе в спиннере. Увидев, что он вызывается и просто при установке дефолтного значения, я написал там код, который устанавливает значения пары переменных, а также меняет текст для кнопки и может сбрасывать текст в информационном TextView. Это текст с расчетными данными поездки, и он должен затираться, когда пользователь сделал хоть одно изменение в данных формы - это значит, что поездка должна быть пересчитана. Это все работало чудесно. Но вот зато при перезагрузке деятельности при смене ориентации экрана я долго не мог понять, почему никак не отображается этот информационный текст с расчитанными данными поездки, хотя значения всех переменных были восстановлены.

                  Потом понял, почему. onItemSelected() срабатывал после onRestoreInstanceState(). А там всегда выполнялся код для сброса текста. Я обошел этот так: в самом начале onRestoreInstanceState() устанавливал некую переменную bLoaded в false, а текст с обработчике выбора в спиннере, как и некоторые другие действия, выполнял только по значению truе в этой переменной. Соответсвенно, true в нее я ставил в конце любого вызова обработчика выбора в спиннере.

                  Ну а если предположить, что по некоторым обстоятельствам onItemSelected() вызывается дважды еще до того, как закончено воссоздание формы? Тогда этот проверочный код пришлось бы усложнить. Но должен же быть способ как-то в коде определить, воссоздана ли уже форма, или этот процесс еще не завершен, чтобы можно было отделить ввод пользователя от автоматических событий, посылаемых системой?

                  Так что вопрос снова помечаю как незакрытый, решил отдельную тему не создавать.
                    Можно устанавливать значения по-умолчанию для интерфейса и в onCreate, еще до того как устанавливаются обработчики. Недаром же Bundle с сохраненным состоянием передается и туда...
                    Сообщение отредактировано: [S]mike -
                      Цитата [S]mike @
                      еще до того как устанавливаются обработчики

                      Ах, об этом я не подумал! Точно!
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0354 ]   [ 16 queries used ]   [ Generated: 27.04.24, 11:55 GMT ]