v7 Support Preference 라이브러리 사용하기

구글의 안드로이드는 매년 새로운 버전이 나오면서 새로운 기능을 제공하는 API를 발표한다. 새로운 버전이다 보니 이전의 버전에서 새로운 기능 또는 UI 등을 사용하기 힘든 상황이다. 그래서 구글은 Android Support 라이브러리(Support 라이브러리)들을 제공해서 하위 버전에서도 상위 버전의 기능과 UI를 사용할 수 있게 지원한다. 그래서 안드로이드 개발자들은 기본 API와 더불어 Support 라이브러리를 살펴봐야 하는 이중고(?)를 겪게 있다. 이 글에서는 Support 라이브러리 중의 하나인 v7 버전의 preference 라이브러리를 사용하는 방법과 약간의 팁을 살펴보자.

preference_01
그림 1, Android SDK Manager 툴 일부

그림 1에서 Android Support Library는 23.1.1 버전이 설치된 것을 확인할 수 있다. 그래서 Support 라이브러리 버전은 v4든 v7이든 23.1.1 버전을 사용한다는 것도 알 수 있다. 이 라이브러리는 %android_home%\extras\android\support 폴더에서 확인할 수 있다.

1. 환경설정

그래들(Gradle) 빌드 파일(Build.gradle)에 아래와 같은 의존 라이브러리가 필요하다.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile 'com.android.support:support-v4:23.1.1'
    compile 'com.android.support:recyclerview-v7:23.1.1'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:preference-v7:23.1.1'
}

2. Preference xml 파일 추가

안드로이드에서 설정 화면 역시 xml 파일로 구성한다. 다른 UI와 다르게 목록의 형태로만 구성할 수 있도록 되어 있다. 기존의 Preference는 내부에서 ListView를 사용하고 있지만, v7의 경우에는 RecyclerView를 사용한다. 그래서 그래들 빌드 파일의 의존성에 v7의 다른 라이브러리가 필요한 것이다. 그리고 아래와 같은 설정 파일은 app/res/xml/ 아래에 위치해야 한다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <android.support.v7.preference.PreferenceCategory android:title="카테고리1">
        <android.support.v7.preference.SwitchPreferenceCompat
            android:key="pf_folder_display_option"
            android:icon="@mipmap/ic_launcher"
            android:title="카테 타이틀 01"
            android:summary="summary"
            android:defaultValue="false" />

        <android.support.v7.preference.SwitchPreferenceCompat
            android:icon="@mipmap/ic_launcher"
            android:title="카테 타이틀 02"
            android:summary="summary"
            android:defaultValue="false" />

        <android.support.v7.preference.SwitchPreferenceCompat
            android:icon="@mipmap/ic_launcher"
            android:title="summary"
            android:summary="summary"
            android:defaultValue="true" />
    </android.support.v7.preference.PreferenceCategory>

    <android.support.v7.preference.PreferenceCategory android:title="카테고리2">
        <android.support.v7.preference.SwitchPreferenceCompat
            android:title="SwitchPreferenceCompat 타이틀"
            android:summary="SwitchPreferenceCompat Summary"
            android:icon="@mipmap/ic_launcher"
            android:defaultValue="true" />
    </android.support.v7.preference.PreferenceCategory>

    <android.support.v7.preference.PreferenceCategory android:title="카테고리3">
        <android.support.v7.preference.Preference
            android:title="타이틀 02"
            android:summary="Summary"
            />

        <android.support.v7.preference.Preference
            android:title="타이틀 03"
            android:summary="Summary"
            />

        <android.support.v7.preference.Preference
            android:title="@string/app_name"
            android:summary="Summary"
            />
    </android.support.v7.preference.PreferenceCategory>
</android.support.v7.preference.PreferenceScreen>

3. 액티비티(Activiy) 예제

예제 프로젝트의 SettingsActivity.java 소스는 아래와 같다. 이 소스는 간단하게 아래의 PreferenceFragmentCompat을 상속해서 구현하고 있는 클래스로 화면을 구성하는 소스이다.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment(), null).commit();
    }
}

4. SettingsFragment 예제

이 클래스는 PreferenceFragmentCompat를 상속해서 실제 Preference 화면을 구성하는 xml을 로딩하는 소스이다. 기존에 사용하던 PreferenceFragment에서는 onCreate() 메서드에서 xml을 로딩했지만, PreferenceFragmentCompat 에서는 onCreatePreferences() 메서드를 사용한다.

import android.os.Bundle;
import android.support.v7.preference.PreferenceFragmentCompat;

public class SettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle bundle, String s) {
        addPreferencesFromResource(R.xml.settings);
    }
}

5. 스타일(styles.xml) 추가

위 과정이 끝나면 테마에 preference 테마를 추가할 필요가 있다. 아래의 수정된 styles.xml 에서 AppTheme의 preferenceTheme 요소의 값으로 @style/PreferenceThemeOverlay를 사용하고 있는 것을 알 수 있다.

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="preferenceTheme">@style/PreferenceLocalTheme</item>
    </style>
    <style name="PreferenceLocalTheme" parent="@style/PreferenceThemeOverlay" />
</resources>

이제 위 과정의 결과로 아래와 같은 멋진(?) 화면을 확인할 수 있다.

preference_02
그림 2, v7 Preference 라이브러리를 사용한 설정 화면

그림 2를 살펴보면, 롤리팝의 머터리얼 디자인 테마와 홀로 테마가 섞여 있다는 것을 알 수 있다. 그래서 조금 더 머터리얼 디자인의 모습을 가지도록 UI를 변경해 보자.

6. 스타일(style.xml) 변경

위 결과 화면을 보면, v7 Preference 기본 UI가 머터리얼(Material) 디자인이라고 보기에는 구리다. 그래서 스타일을 변경해서 UI를 개선하는 방법을 살펴보자.

6.1 android.support.v7.preference.PreferenceCategory의 Text 스타일 변경

아래와 같이 PreferenceCategory에 보여지는 TextView의 스타일을 변경한다.

<style name="ListSeparatorTextView">
  <item name="android:textSize">16sp</item>
  <!--item name="android:textStyle">bold</item-->
  <item name="android:textColor">@color/accent</item>
  <item name="android:paddingTop">16dp</item>
  <item name="android:layout_marginBottom">16dp</item>
</style>

6.2 Preference의 Title과 Summary 스타일 변경

이 Preference의 Title은 textAppearanceLarge를 style로 사용하고 있고, Summary는 textAppearanceMedium을 style로 사용하고 있다. 그래서 위 설정화면의 Title과 Summary가 크게 느껴진다. 그래서 이 두개의 스타일을 변경해 보자.

<style name="LargeText">
   <item name="android:textSize">16sp</item>
</style>
<style name="MediumText">
   <item name="android:textSize">11sp</item>
   <item name="android:typeface">sans</item>
</style>

위 과정으로 변경된 전체 styles.xml은 아래와 같다.

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="preferenceTheme">@style/PreferenceLocalTheme</item>
    </style>

    <style name="AppThemePreference" parent="AppTheme">
        <item name="android:listSeparatorTextViewStyle">@style/ListSeparatorTextView</item>
        <item name="android:textAppearanceLarge">@style/LargeText</item>
        <item name="android:textAppearanceMedium">@style/MediumText</item>
    </style>

    <style name="PreferenceLocalTheme" parent="@style/PreferenceThemeOverlay" />

    <style name="ListSeparatorTextView">
        <item name="android:textSize">16sp</item>
        <!--item name="android:textStyle">bold</item-->
        <item name="android:textColor">@color/colorPrimary</item>
        <item name="android:paddingTop">16dp</item>
        <item name="android:layout_marginBottom">16dp</item>
    </style>

    <style name="LargeText">
        <item name="android:textSize">16sp</item>
    </style>

    <style name="MediumText">
        <item name="android:textSize">11sp</item>
        <item name="android:typeface">sans</item>
    </style>

</resources>

위 스타일로 변경된 스타일의 화면은 다음과 같다.
preference_03

위 스타일에서 설정을 가지고 있는 액티비티는 AppThemePreference를 테마로 사용하면 된다. 이 테마안에 보면 android:textAppearanceLarge나 android:textAppearanceMedium이 테마 전역으로 사용하는 요소이기 때문에 이 테마를 사용하는데는 주의를 해야 한다.

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.