Поиск по этому блогу

понедельник, 4 февраля 2013 г.

Работа с настройками в Android

Сегодня я хочу с вами поделиться некоторым опытом работы с настройками в android. Это будет небольшой туториал для начинающих ну и собсно что-то такое куда можно будет заглянуть накануне когда понадобятся настройки и скопипастить нужный кусок к себе в проект.
Начну с того что для примера мы напишем недопрограмму в которой будет всего два файла: файл настроек и главная активность в которой будет показываться что выбрали. Все будет просто, на главной активносте будет поле текстовое в котором можно будет писать текст, и текствью который нам никак не пригодится. На активности будет меню для перехода в настройки.
Для начала создаем проект и открываем наш main.xml, сейчас мы туда впилим нашу разметку главной активити. Вот так вот она будет выглядеть:

main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:textColor="#fff"
        android:text="Тут будут отображаться ваши изменения из настроек" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/textView1"
        android:ems="10"
        android:inputType="textMultiLine" />
</RelativeLayout>


Смотреться на телефоне в дневном режиме вот так будет:


Дальше в созданном MainActivity добавляем меню:

MainActivity
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
public class MainActivity extends Activity {
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
        
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                et = (EditText) findViewById(R.id.editText1);
        }
        
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {

                menu.add(Menu.NONE, 1, 0, "Настройки");
                return super.onCreateOptionsMenu(menu);
        }
        
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {

                switch (item.getItemId()) {
                        case 1: {
                                Intent intent = new Intent(this, PrefsActivity.class);
                                startActivity(intent);
                        }
                }
                return true;
        }
}


Далее нам нужно создать подпапочку res/xml и внутри этой папки создать файл prefs.xml. Начнем мы с CheckBoxPreference.

CheckBoxPreference

preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        <!--Поле по которому будем считывать данные, так называемый ключ-->
        android:key="night"
        android:title="Ночной режим"
        android:summary="Включить темную подсветку текста"
        <!--Будет активен или не активен-->
        android:defaultValue="false" /></PreferenceScreen>


Тут мы добавили обычный чекбокс для включения или отключения ночного режима в программе на едит тексте.

Дальше создаем файл PrefsAcitivity, его мы унаследуем не просто от активити а от PreferenceActivity для того что бы он определялся как активность настроек и сохранял все что мы там будет вытворять. Он будет выглядеть вот так вот:

PrefsActivity
import android.content.Intent;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
public class PrefsActivity extends PreferenceActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
        }
}


Дальше нужно добавить эту активность в AndroidManifest так как если не добавите то и не откроете её.

AndroidManifest
<activity android:name="com.preferencesexample.PrefsActivity"></activity>


Теперь давайте добавим в нашу главную активность обработку этого чекбокса который мы создали в настройках. Для этого нам нужно создать метод onResume() в котором будем все это красотень обрабатывать. Далее я не буду приводить весь код, а только метод onResume() в котором собственно и будет все происходить.

Для начала нам нужно объявить переменные для работы с настройками и с нашим текстовым полем. В шапке файла MainActivity добавляем вот такие поля:

SharedPreferences prefs;
EditText et;


В onCreate() же нам нужно эти поля идентифицировать что бы их можно было использовать так что далее пишем


@Override
        public void onCreate(Bundle savedInstanceState) {
        
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                et = (EditText) findViewById(R.id.editText1);
        }


Ну а теперь создаем метод onResume() в самом низу нашего файла и начинаем оживлять нашу разметку.

Начнем мы с чекбокса, он у нас должен вводить и выводить в/из ночного режима, давайте это реализуем:

MainActivity
@Override
public void onResume() { 
    //идентифицировали наши настройки теперь можем их использовать
    prefs = PreferenceManager.getDefaultSharedPreferences(this); 
    //режим для вида поля ввода (ночной дневной)
    if (prefs.getBoolean("night", false)) {// night - наше поле в prefs.xml, false - не активно.
        et.setBackgroundColor(Color.BLACK);  //задаем черный цвет фона для edittext
        et.setTextColor(Color.YELLOW);       //задаем желтый цвет текста
    } else {                                 // если true
        et.setBackgroundColor(Color.WHITE);  // и так далее
        et.setTextColor(Color.BLACK);
    }
    super.onResume();
}


Теперь если вы запустите и попробуете поставить / убрать в настройках галочку у вас будет меняться фоновый цвет в едит тексте.

EditTextPreference
И так научились мы менять цвет поля из настроек давайте теперь научимся увеличивать шрифт из них. Для этого нам понадобится EditTextPreference который позволяет вводить нам произвольные числа и разный текст, но так как мы хотим ввести размер то будем вводить только цифры. 

preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:key="night"
        android:title="Ночной режим"
        android:summary="Включить темную подсветку текста"
        android:defaultValue="false" />
    
        <EditTextPreference
            android:key="text_size"
            android:title="Размер шрифта"
            android:summary="Устанавливает новый размер шрифта"
            android:defaultValue="14"
            android:dialogTitle="Введите размер шрифта (от 10 до 32)" />
</PreferenceScreen>


Все также как и в чекбоксе то же поля ключ, то же название и т.д. Как нам получить параметр который будет введен в поле EditTextPreferences? А вот так! 

MainActivity
@Override
public void onResume() { 
        prefs = PreferenceManager.getDefaultSharedPreferences(this); 
        //режим для вида поля ввода (ночной дневной)
    if (prefs.getBoolean("night", false)) {
        et.setBackgroundColor(Color.BLACK);
        et.setTextColor(Color.YELLOW);
    } else {
        et.setBackgroundColor(Color.WHITE);
        et.setTextColor(Color.BLACK);
    }
    // читаем размер шрифта из EditTextPreference 
    float fSize = Float.parseFloat(prefs.getString("text_size", "20")); 
    // применяем настройки в текстовом поле 
    et.setTextSize(fSize);
    super.onResume();
}


Вот таким образом мы получим цифры из текстбокса которые введет пользователь в настройках.
Выглядит вот так


ListPreference
Теперь мы хотим менять стиль текста, он у нас может быть жирный, курсивный, подчеркнутый и полужирный курсив. Для того что бы такое сделать нам нужно добавить в наши настройки ListPreference который позволяет создавать списки с радибаттонами или с чекбоксами. 

Для того что бы создать список нам нужно создать массив этих вариантов. Создаем файл text_style.xml в папке res/values и пишем в нем вот такой вот массив:

text_style.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
        <string-array name="font_style">
                <item>Обычный</item>
                <item>Полужирный</item>
                <item>Курсив</item>
                <item>Полужирный+Курсив</item>
        </string-array>
</resources>


Дальше в файле preferences.xml нам нужно создать ListPreferences и задать ему генерировать массив из этого файла.

Теперь наш preferences.xml будет выглядеть вот так:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:key="night"
        android:title="Ночной режим"
        android:summary="Включить темную подсветку текста"
        android:defaultValue="false" />
    
        <EditTextPreference
            android:key="text_size"
            android:title="Размер шрифта"
            android:summary="Устанавливает новый размер шрифта"
            android:defaultValue="14"
            android:dialogTitle="Введите размер шрифта (от 10 до 32)" />
        
        <ListPreference
                android:key="text_style"
                android:title="Стиль для шрифта"
                android:summary="Устанавливает стиль для шрифта"
                android:defaultValue="1"
                <!--Наш массив с данными-->
                android:entries="@array/font_style"
                android:entryValues="@array/font_style"
                android:dialogTitle="Выберите стиль для шрифта" />
</PreferenceScreen>


Теперь для обработки этого элемента немного видоизменим наш onResume() добавим туда еще пару строк кода для обработки / чтения параметров.

MainActivity
@Override
public void onResume() { 
        prefs = PreferenceManager.getDefaultSharedPreferences(this); 
        //режим для вида поля ввода (ночной дневной)
    if (prefs.getBoolean("night", false)) {
        et.setBackgroundColor(Color.BLACK);
        et.setTextColor(Color.YELLOW);
    } else {
        et.setBackgroundColor(Color.WHITE);
        et.setTextColor(Color.BLACK);
    }
    // читаем размер шрифта из EditTextPreference 
    float fSize = Float.parseFloat(prefs.getString("text_size", "20")); 
    // применяем настройки в текстовом поле 
    et.setTextSize(fSize);
    
    // читаем стили текста из ListPreference 
    String regular = prefs.getString("text_style", "");
    int typeface = Typeface.NORMAL; 

    if (regular.contains("Полужирный")) 
        typeface += Typeface.BOLD; 

    if (regular.contains("Курсив")) 
        typeface += Typeface.ITALIC; 

    // меняем настройки в EditText 
    et.setTypeface(null, typeface);
    super.onResume();
}


Из комментариев понятно что и как тут происходит. Выглядеть вот так будет:


Ну теперь давайте добавим последний элемент который я очень долго искал но все таки нашел как его сделать, это кнопка перехода из настроек на другую активность, например вам захотелось в настройках добавить какую-то сложную функцию например как калибровка экрана, для этого вы создали активность и в ней делаете все что вам нужно, для того что бы перейти из настроек на эту активность вам нужно создать кнопку в preferences.xml.

<Preference android:title="Вернуться на главное окно" android:key="button"/>


И дальше в файле PrefsActivity нужно написать метод который будет обрабатывать клик, в нашем случае мы будем переходить обратно на нашу активность, но вообще это делается для скрытых настроек.

PrefsActivity
import android.content.Intent;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
public class PrefsActivity extends PreferenceActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
            
            //обрабатываем нажатие кнопки в настройках
            Preference button = (Preference)findPreference("button");
                button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                    @Override
                    public boolean onPreferenceClick(Preference arg0) { 
                        Intent intent = new Intent(PrefsActivity.this, MainActivity.class);
                                startActivity(intent);
                        return true;
                    }
                });
        }
}


Собственно это все что я хотел рассказать про настройки, там еще есть уйма разных елементов но это основные которые я использовал и которые я буду использовать в дальнейшем. Спасибо за внимание, исходник проекта лежит ниже.

Сами настройки будут вот так выглядеть:


Скачать с GitHub & Скачать с Dropbox