четвер, 25 жовтня 2012 р.

Нестандартный диалог настроек Андроид.

Android - Настройки приложения

 В андроиде существует мощный фреймворк для работы с настройками приложения. Как говорит http://developer.android.com, надо стремиться к использованию оного, дабы пользователь мог контролировать приложение стандартным способом, а не конфузиться в интерфейсе уникальном и непознанном :-) Для настроек, значения которых описываются простыми типами (будь то строки, буль или число), Preference API справляеться "на ура", однако в жизни часто так бывает, что для всеобъемлющего счастья нехватает самую малость - чуть больше, чем есть сейчас :) Итак, сегодня поговорим о том как организовать интерфейс для сохранения более комплексных сущностей. Предположим, мы создаём некое клиентское приложение, в настройках которого надо реализовать возможность ввести адрес вебсервиса. Как известно - веб-адрес имеет следующую структуру:
Символьное_Имя_или_IP_адрес[:Порт(не обязательно)]
Отсюда следует, что у нас настройка "адрес" будет состоять из двух частей - собсно адреса и порта. Итак, начнём...



  1.UI Первым делом надо продумать пользовательский интерфейс под это дело. Благо - в нашем случае всё довольно просто. Должно получиться что-то такое:

 Не будем претендовать на сверхоптимальный UI, напишем следующее:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"    
    android:layout_height="wrap_content" 
    android:gravity="center"
    android:layout_gravity="center"
    android:layout_margin="10dp"
    android:padding="10dp">
    
    <LinearLayout android:orientation="horizontal" 
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">
        <TextView android:text="@string/preferences_webservice_address" 
        android:id="@+id/preference_webservice_address_legend" 
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        style="@style/RegularLightLabel"/>

   <EditText android:id="@id/preference_webservice_address"
       android:layout_width="0dp"
       android:layout_weight="2"
       android:layout_height="wrap_content"
       android:lines="1" />
    </LinearLayout>
    
    <LinearLayout android:orientation="horizontal"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">
        <TextView android:id="@+id/preference_webservice_port_legend"
            android:text="@string/preferences_webservice_port"
            android:layout_gravity="right"
            android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        style="@style/RegularLightLabel" />
        <EditText
            android:id="@id/preference_webservice_port"
            android:layout_width="0dp"
            android:layout_weight="2"
            android:layout_height="wrap_content"/>
    </LinearLayout>"
</LinearLayout>
И сохраним в файл /res/xml/preferences.xml

  2. Класс диалога. Теперь нам необходимо написать класс, унаследованый от DialogPreference, который будет отображать наш диалог настроек. Некоторые нюансы: - необходимо в перегруженом методе onClick загрузить наш UI из xml-файла:
public WebServicePreferences(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setDialogLayoutResource(R.layout.preferences_network); }
- желательно в перегруженом onCreateDialogView сохранить в локальных переменных елементы управления диалога - проще потом будет выцарапать из них модифицированые значения настроек:
@Override protected View onCreateDialogView() { View root = super.onCreateDialogView(); //создать диалог и вернуть корневой елемент pref_address = (EditText)root.findViewById(R.id.preference_webservice_address); pref_port = (EditText)root.findViewById(R.id.preference_webservice_port); return root; }
- не забываем создать методы-аксесоры для значений настроек - чтобы можно было внести/выдрать значения извне. - перегружаем метод onClick, в котором сохраняем значения в локальных переменных и вызываем слушатель измененний(если нажата кнопка Окей):
@Override public void onClick(DialogInterface dialog, int which) {
 switch (which) {
 case Dialog.BUTTON_POSITIVE: //Тыцнули кнопку Ок.Читаем значения в переменные 

pref_address_value = pref_address.getText().toString();
 pref_port_value = pref_port.getText().toString();
 //вызываем слушатель
 callChangeListener(null);
 break;

 case Dialog.BUTTON_NEUTRAL:
 //... если вдруг...
 break;

 case Dialog.BUTTON_NEGATIVE:
 //... пользователь сказал "не-а..."
 break;
 default: //этого никогда не произойдёт, но всё же вызываем родительскую реализацию... 
super.onClick(dialog, which);
 break;

}
 }

3. Явление настроек на данном этапе(а может быть, нам с этого этапа и следовало начинать) нам следует реализовать явление, унаследованое от PreferenceActivity, и написать графический интерфейс для него. Нюансы: - в onCreate, грузим наш интерфейс из xml:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); }
- реализовываем интерфейс OnPreferenceChangeListener (слушатель, который мы вызываем из onClick нашего диалога - как раз и описываеться этим интерфейсом)

 В результате получилось следующее:

 которое, при нажатии на пункт Address, превращаеться в
а если написать какую-то пургу вместо адреса, увидим следующее:

Немає коментарів:

Дописати коментар