Как стать автором
Обновить

Иконифицированное окно настроек (Preferences)

Время на прочтение 4 мин
Количество просмотров 6.2K
Все видели настройки в Android аппаратах — меню с иконками. Это стандартный PreferencesActivity, только вот стандартными функциями Андроида такого эффекта достичь невозможно.
Что бы получить такой внешний вид, используем код, позаимствованный из системного приложения Settings.apk, благо open-source это позволяет сделать.



И так, нам понадобится:
1. Класс IconPreferenceScreen.java;
2. Файл attrs.xml в папке values;
3. Лэйаут preference_icon.xml;
4. Свой класс PreferencesActivity.java;
5. Файл с настройками приложения preferences.xml



Первые 3 файла находятся в исходниках приложения настроек, но приведу их текст в топике.

Класс IconPreferenceScreen.java:
public class IconPreferenceScreen extends Preference {

    private Drawable mIcon;

    public IconPreferenceScreen(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IconPreferenceScreen(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setLayoutResource(R.layout.preference_icon);
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.IconPreferenceScreen, defStyle, 0);
        mIcon = a.getDrawable(R.styleable.IconPreferenceScreen_icon);
    }

    @Override
    public void onBindView(View view) {
        super.onBindView(view);
        ImageView imageView = (ImageView) view.findViewById(R.id.icon);
        if (imageView != null && mIcon != null) {
            imageView.setImageDrawable(mIcon);
        }
    }

    public void setIcon(Drawable icon) {
        if ((icon == null && mIcon != null) || (icon != null && !icon.equals(mIcon))) {
            mIcon = icon;
            notifyChanged();
        }
    }

    public Drawable getIcon() {
        return mIcon;
    }
}


Файл attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="IconPreferenceScreen">
        <attr name="icon" format="reference" />
    </declare-styleable>
</resources>


Лэйаут preference_icon.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+android:id/iconpref"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical" 
    android:paddingRight="?android:attr/scrollbarSize">
    <ImageView android:id="@+id/icon" 
    android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="6dip"
        android:layout_marginRight="6dip" 
        android:layout_gravity="center" />
    <RelativeLayout android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="2dip"
        android:layout_marginRight="6dip" 
        android:layout_marginTop="6dip"
        android:layout_marginBottom="6dip" 
        android:layout_weight="1">
        <TextView android:id="@+android:id/title"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"
            android:singleLine="true" 
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:ellipsize="marquee" 
            android:fadingEdge="horizontal" />
        <TextView android:id="@+android:id/summary"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"
            android:layout_below="@android:id/title" 
            android:layout_alignLeft="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:maxLines="2" />
    </RelativeLayout>
</LinearLayout>


Далее в класс PreferencesActivity.java необходимо добавить строки, которые описывают данные пункты.
addPreferencesFromResource(R.xml.preferences);
IconPreferenceScreen test = (IconPreferenceScreen) findPreference("key");
Resources res = getResources();
Drawable icon = res.getDrawable(R.drawable.icon1);
test.setIcon(icono1);


А в сам файл настроек preferences.xml сами IconPreferenceScreen
<com.example.app.IconPreferenceScreen 
                android:title="IconPreferenceScreen"
                android:key="key" />




Но так как IconPreferenceScreen не является стандартным PreferenceScreen и в него нельзя добавлять другие элементы, то добавим обработку клика по нему и открытие активити.

test.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
			@Override
			public boolean onPreferenceClick(Preference preference) {
				startActivity(new Intent(PreferencesActivity.this, PreferencesActivity2.class));
				return true;
			}
		});


Вот собственно и все.
В качестве бонуса можно сделать окно настроек в виде диалога, добавив в Manifest к активити настроек следующий код:
 android:theme="@android:style/Theme.Dialog"


А так же можно сделать диалог без заголовка, для чего создать файл styles.xml со следующим содержанием:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="NoTitleDialog" parent="android:style/Theme.Dialog">
   <item name="android:windowNoTitle">true</item>
</style>   
</resources>


и прописав в Manifest к активити

 android:theme="@style/NoTitleDialog"




Плюсы этого подхода:
-Возможность делать красивые пункты настроек, а так же стандартные виджеты на подобии CheckBox размещать в одном окне;
-Визуальная эстетичность.
Минусы:
-Необходимость создания дополнительных активити для использования их с IconPreferenceScreen в отличии от стандартного PreferenceScreen.

Ссылки на загрузку:
1. Исходный код примера;
2. Пример приложения (apk).
В примере 3 активити, первое с использованием IconPreferenceScreen и стилем Theme.Dialog, второе (открывается по клику на любое из двух иконифицированных пунктов) стандартный PreferencesActivity с стандартными виджетами и стилем NoTitleDialog, третье с IconPreferenceScreen и стандартными виджетами без указания стиля, как раз такой вид и используется в настройках Android.

Да сделаем же красивыми окна настроек в своих приложениях, украсим мир!
Теги:
Хабы:
+49
Комментарии 16
Комментарии Комментарии 16

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн