안드로이드 PreferenceFragment로 환경설정 만들기

안드로이드 앱에서 환경설정은 필수요소이다. 이런 환경설정 부분을 만드는 방법은 여러 가지가 있겠지만, 대표적으로 안드로이드에서 제공하는 PreferenceFragment 클래스를 사용하는 방법을 정리해 보고자 한다.

앱의 환경설정을 위해서는 액티비티에서 설정화면을 구성하고, 그 화면에서 발생하는 다양한 사용자 이벤트를 처리하여 설정한 데이터를 영속적으로 저장해야 한다. PreferenceFragment 클래스 사용하면 위와 같은 부분을 쉽게 처리 할 수 있다.

큰 맥락

1.환경설정 화면 레이아웃 XML을 만든다. 2.PreferenceFragment를 이용하여 환경설정 화면에서 발생하는 이벤트 처리 로직이 들어간다.
3.환경설정 용 액티비티를 하나 만들고 레이아웃을 fragment로 바꾼다.


PreferenceFragment로 앱의 환경설정 구현 1단계: 화면단 만들기

  • res 폴더 하위에 values 폴더에 arrays.xml 파일을 만들고 환경설정에서 사용할 문자열 배열 데이터를 저장한다.

settings_preference.xml

arrays.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="array_voice">
<item>카톡</item>
<item>카톡왔숑</item>
<item>카톡카톡</item>
<item>카카오톡</item>
</string-array>
</resources>

  • res 폴더 하위에 xml 폴더를 만든다. -> 해당 폴더에 settings_preference.xml 파일을 만든다. settings_preference.xml 파일은 안드로이드 앱의 환결설정 화면의 레이아웃을 표현한다.

루트태그로 PreferenceScreen를 갖는다.

태그종류 설명
PreferenceScreen 설정화면 단위, 중첩 가능하며 중첩된 내용은 별도의 화면에 나옴
PreferenceCategory 설정 여러 개를 시각적으로 묵어서 표현
CheckboxPreference 체크박스가 나오는 설정
EditTextPreference 글 입력을 위한 설정
ListPreference 항목 다이얼로그를 위한 설정
MultiSelectListPreference 항목 다이얼로그인데 체크박스가 자동 추가되어 여러 선택 가능
RingtonPreference 알림음 선택을 위한 설정
SwitchPreference 스위치를 이용한 설정

settings_preference.xml

settings_preference.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory android:title="메시지 알림">
<SwitchPreference
android:key="message"
android:title="메시지 알림"/>

<PreferenceScreen
android:key="keyword_screen"
android:title="키워드 알림"
android:summary="사용안함">

<SwitchPreference
android:defaultValue="false"
android:key="keyword"
android:summary="등록된 키워드가 포함된 메시지는 채팅방 알림이 꺼져 있어도 푸시 알림을 받게 되어 키워드는 강조되어 보여 집니다."
android:title="키워드 알림"/>
<ListPreference
android:entries="@array/array_voice"
android:entryValues="@array/array_voice"
android:key="keyword_sound_list"
android:summary="카톡"
android:title="키워드 전용 알림음"
android:dependency="keyword"
/>

</PreferenceScreen>

<SwitchPreference
android:key="sound"
android:title="소리"/>
<ListPreference
android:entries="@array/array_voice"
android:entryValues="@array/array_voice"
android:key="sound_list"
android:summary="카톡"
android:title="알림음음"
/>

</PreferenceCategory>

</PreferenceScreen>

settings_preference.xml 파일의 안드로이드 스튜디오에서 Design으로 보면 다음과 같이 환경설정 화면을 볼 수 있다.

settings_preference.xml 디자인

Preference개열의 태그는 안드로이드의 환경설정 스타일의 UI를 제공하며, 위 화면의 환경설정 내용의 상태가 변경되면 자동으로 SharedPreferences 객체로 true 혹은 false 값을 영속적으로 저장하기 때문에 개발자의 수고를 덜어준다. 환경설정 상태 값이 저장될 때 키값은 XML 속성 중 key에 지정한 값을 이용한다.

ListPreference를 보면 entries와 entryValues 속성값이 존재한다. 이 속성값은 배열 리소스로 등록해야 하기 때문에, 앞서 arrays.xml 파일을 만든 것이다.


PreferenceFragment로 앱의 환경설정 구현 2단계: 환경설정 화면 제어 클래스 만들기

  • 원하는 패키지에 SettingPreferenceFragment.java 를 만들고 PreferenceFragment를 extends 한다. SettingPreferenceFragment.java는 앞서 만든 settings_preference.xml와 연결되어 만들어둔 환경설정 화면과 그 이벤트 처리등을 담당하게 된다. 크게 onCreate부분에서는 이미 저장된 환경설정 내용을 가져와, 그 내용들을 환경설정의 summary부분에 셋팅해준다. 그리고 prefs.registerOnSharedPreferenceChangeListener(prefListener); 로 연결된 리스너 SharedPreferences.OnSharedPreferenceChangeListener()를 통해서 사용자가 환경설정 하는 순간의 이벤트 처리를 한다.

예제에 있는 프로젝트 패키지는 원하는대로 수정하길 바란다.

SettingPreferenceFragment.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.hanumoka.android.pomoguru;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.annotation.Nullable;
import android.widget.BaseAdapter;

/**
* Created by amagr on 2018-01-01.
*/

public class SettingPreferenceFragment extends PreferenceFragment {

SharedPreferences prefs;

ListPreference soundPreference;
ListPreference keywordSoundPreference;
PreferenceScreen keywordScreen;


@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

addPreferencesFromResource(R.xml.settings_preference);
soundPreference = (ListPreference)findPreference("sound_list");
keywordSoundPreference = (ListPreference)findPreference("keyword_sound_list");
keywordScreen = (PreferenceScreen)findPreference("keyword_screen");

prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());

if(!prefs.getString("sound_list", "").equals("")){
soundPreference.setSummary(prefs.getString("sound_list", "카톡"));
}

if(!prefs.getString("keyword_sound_list", "").equals("")){
keywordSoundPreference.setSummary(prefs.getString("keyword_sound_list", "카톡"));
}

if(prefs.getBoolean("keyword", false)){
keywordScreen.setSummary("사용");
}

prefs.registerOnSharedPreferenceChangeListener(prefListener);

}// onCreate

SharedPreferences.OnSharedPreferenceChangeListener prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals("sound_list")){
soundPreference.setSummary(prefs.getString("sound_list", "카톡"));
}

if(key.equals("keyword_sound_list")){
keywordSoundPreference.setSummary(prefs.getString("keyword_sound_list", "카톡"));
}

if(key.equals("keyword")){

if(prefs.getBoolean("keyword", false)){
keywordScreen.setSummary("사용");

}else{
keywordScreen.setSummary("사용안함");
}

//2뎁스 PreferenceScreen 내부에서 발생한 환경설정 내용을 2뎁스 PreferenceScreen에 적용하기 위한 소스
((BaseAdapter)getPreferenceScreen().getRootAdapter()).notifyDataSetChanged();
}

}
};

}


PreferenceFragment로 앱의 환경설정 구현 3단계: 빈 액티비티를 통해 환경설정 화면 열기

  • 이번 3단계에서는 이미 만들어진 환경설정 내용을 화면에 보여주기위해 액티비티에 연결하는 부분이다. 간단하므로 SettingActivity 액티비티와 그 레이아웃 activity_setting.xml의 소스로 설명을 대신한다. 역시 예제에 있는 프로젝트 패키지는 원하는대로 수정하길 바란다.
SettingActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.hanumoka.android.pomoguru.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.hanumoka.android.pomoguru.R;

public class SettingActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
}
}

activity_setting.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/settings_fragment"
android:name="com.hanumoka.android.pomoguru.SettingPreferenceFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

activity_setting.xml는 일반적인 액티비티의 레이아웃이 아니라 fragment라는 태그를 사용한다. 중요한 부분은 android:name 속성에 2단계에서 만든 환경설정 제어 클래스를 등록한다. 이제 완성이다 SettingActivity 액티비티를 동작 시켜보자.

SettingActivity 실행화면

자동으로 설정된 값들을 영속적으로 저장하고 있기때문에, 앱을 종료후 다시 접속해도 그 환경설정 데이터가 지워지지 않고 유지된다.

지금까지의 환경설정 부분의 구조를 보면

arrays.xml ---> settings_preference.xml ---> SettingPreferenceFragment.java ---> activity_setting.xml ---> SettingActivity.java

위와 같이 연결된 구조이다. arrays.xml같은 경우 ListPreference, MultiSelectListPreference를 사용하지 않는다면 필요가 없을 수도 있다.