Goodroid

GoodroidはAndroidアプリ開発のための情報をコラムやブログで紹介するサイトです。


設定画面を作成する
ここでは設定画面を作成する方法を確認していきます。

設定値を端末内に保存させるためには「プリファレンス(Preference)」というものを使います。 保存できる型はboolean, float, int long Stringの5種類で、エディットテキストで入力した値、チェックボックスでオンオフ、リストで選択した値など、以下の4種類の項目を簡単に保存することができます。

項目 種類
ListPreference リストから選択
EditTextPreference 文字を入力
RingtonePreference 着信メロディから選択
CheckBoxPreference チェックボックス

プリファレンスのデータは、値の名前(キー)と値を組み合わせて作り、端末内の「/data/data/パッケージ名/shared_prefs/ファイル名.xml」にXML形式で保存されます。

サンプルでは、まず現在の設定値を表示するアクティビティ(ConfigActivity.java)を作成し、設定画面に「PreferenceActivity」を継承したアクティビティ(Preference.java)を作成しています。また、preference.xmlで設定項目を記述しています。

設定するデータに関してですが、プリファレンスでリスト(ListPreference)を使用する場合、リストに表示する値を「entries」、実際にデータとして登録される値を「entryvalues」という2つの配列を用意して、arrays.xmlで定義しています。

以下にプロジェクトのファイル構成を載せます。(画像クリックで拡大)



▼ConfigActivity.javaでは現在の設定値を表示するとともに、端末のメニューボタン押下で「設定」を表示し、ボタン押下で設定画面へ遷移します。

ConfigActivity.java
package goodroid.sample.config;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class ConfigActivity extends Activity{

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

	// 保存されたデータを読み込む
	SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);

	// 値の取得
	String param_list = p.getString("list", "Unselected");
	String param_edittext = p.getString("edittext", "Unselected");
	String param_ringtone = p.getString("ringtone", "Unselected");
	boolean param_checkbox = p.getBoolean("checkbox", false);

	TextView t1 = (TextView)findViewById(R.id.text1);
	TextView t2 = (TextView)findViewById(R.id.text2);
	TextView t3 = (TextView)findViewById(R.id.text3);
	TextView t4 = (TextView)findViewById(R.id.text4);

	t1.setText("リスト:" + param_list);
	t2.setText("エディットテキスト:" + param_edittext);
	t3.setText("リングトーン:" + param_ringtone);
        t4.setText("チェックボックス:" + param_checkbox);
    }

    // メニューボタンを最初にクリックした時に実行されるメソッド
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // メニューを生成します。
        menu.add(Menu.NONE, (Menu.FIRST), Menu.NONE, "設定");
        return super.onCreateOptionsMenu(menu);
    }

    // メニューボタンをクリックされるたびに実行されるメソッド
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        return super.onPrepareOptionsMenu(menu);
    }

    // メニューのアイテムが選択された時に実行されるメソッド
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch(item.getItemId()){
    	case 1:
            Intent intent = new Intent(ConfigActivity.this, Preference.class);
            startActivity(intent);
            return true;

    	default:
    		break;
        }
    	return false;
    }
}

▼Preference.javaが実際の設定画面で、リストはチェックボックスなどの選択した値をサマリーに反映しています。

Preference.java
package goodroid.sample.config;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.RingtonePreference;
import android.widget.Button;
import android.view.View;
import android.widget.Toast;

public class Preference extends PreferenceActivity 
                                    implements OnPreferenceChangeListener{

    // Preference
    private ListPreference list;
    private EditTextPreference edittext;
    private RingtonePreference ringtone;
    private CheckBoxPreference checkbox;

    @Override
    public void onCreate(Bundle bundle) {

	super.onCreate(bundle);
	setContentView(R.layout.pref);
	addPreferencesFromResource(R.xml.preference);

        // Preferenceの取得
	list = (ListPreference)findPreference("list");
	edittext = (EditTextPreference)findPreference("edittext");
	ringtone = (RingtonePreference)findPreference("ringtone");
        checkbox = (CheckBoxPreference)findPreference("checkbox");

	// リスナーを設定する
	list.setOnPreferenceChangeListener(this);
	edittext.setOnPreferenceChangeListener(this);
	ringtone.setOnPreferenceChangeListener(this);
        checkbox.setOnPreferenceChangeListener(this);

	// 保存されたデータを読み込む
	SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);

	// 値の取得
	String param_list = p.getString("list", "Unselected");
	String param_edittext = p.getString("edittext", "Unselected");
	String param_ringtone = p.getString("ringtone", "Unselected");
	boolean param_checkbox = p.getBoolean("checkbox", false);

	// デフォルト値の設定
	list.setDefaultValue(param_list);
	edittext.setDefaultValue(param_edittext);
	ringtone.setDefaultValue(param_ringtone);
	checkbox.setDefaultValue(param_checkbox);

	// サマリーの設定
	setSummary(list, param_list);
	setSummary(edittext, param_edittext);
	setSummary(ringtone, param_ringtone);
	setSummary(checkbox, param_checkbox);

	Button button = (Button) findViewById(R.id.button);

	// ボタン押下時の処理
	button.setOnClickListener(new View.OnClickListener() {
	    public void onClick(View v) {
		try {
	    	    Intent intent = new Intent(Preference.this, ConfigActivity.class);
		    startActivity(intent);
		    finish();
		} catch (Exception e) {
		    Toast.makeText(getApplicationContext(),
                        "ERROR\n" + e.getMessage(), Toast.LENGTH_LONG).show();
		}
            }
	});
    }

    // リストの値が変更されたときに呼ばれる
    public boolean onPreferenceChange(android.preference.Preference preference,	
        Object newValue) {

	if(newValue != null){

	    // newValueの型でサマリーの設定を分ける
	    if(newValue instanceof String){

	        // preferenceの型でサマリーの設定を分ける
	        if(preference instanceof ListPreference)
	            setSummary((ListPreference)preference, (String)newValue);
	        else if(preference instanceof EditTextPreference)
		    setSummary((EditTextPreference)preference, (String)newValue);
	        else if(preference instanceof RingtonePreference)
		    setSummary((RingtonePreference)preference, (String)newValue);

	    }else if(newValue instanceof Boolean){
		setSummary((CheckBoxPreference)preference, (Boolean)newValue);
	    }
	    return true;
	}
	return false;
    }

    // Summaryを設定(リスト)
    public void setSummary(ListPreference lp, String param){

	if(param == null){
    	    lp.setSummary("Unselected");
	}else{
	    lp.setSummary("Selected「" + param + "」");
	}
	param = null;
    }

    // Summaryを設定(エディットテキスト)
    private void setSummary(EditTextPreference ep, String param) {

        if(param == null){
	    ep.setSummary("Unselected");
        }else{
	    ep.setSummary("Selected「" + param + "」");
        }
	param = null;
    }

    // Summaryを設定(リングトーン)
    private void setSummary(RingtonePreference rp, String param) {

        if(param == null){
	    rp.setSummary("Unselected");
        }else{
	    rp.setSummary("Selected「" + param + "」");
        }
        param = null;
    }

    // Summaryを設定(チェックボックス)
    public void setSummary(CheckBoxPreference cp, Boolean param){

	cp.setSummary("Selected「" + param + "」");
	param = false;
    }

    // Activity破棄時に実行
    public void onDestroy(){
        super.onDestroy();
	list.setOnPreferenceChangeListener(null);
	edittext.setOnPreferenceChangeListener(null);
	ringtone.setOnPreferenceChangeListener(null);
	checkbox.setOnPreferenceChangeListener(null);

	list = null;
	edittext = null;
	ringtone = null;
        checkbox = null;
    }

    // Activityの再開時に実行
    public void onRestart(){
 	super.onRestart();
	list.setEnabled(true);
	edittext.setEnabled(true);
	ringtone.setEnabled(true);
	checkbox.setEnabled(true);
    }

    // Activityの停止時に実行
    public void onStop(){
	super.onStop();
	list.setEnabled(false);
	edittext.setEnabled(false);
	ringtone.setEnabled(false);
	checkbox.setEnabled(false);
    }
}

▼main.xmlは最初の設定値表示画面のレイアウトを記述しています。

res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/text1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/text2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/text3"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/text4"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/text5"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="\n\n設定変更はメニューボタンから行ってください。"/>

</LinearLayout>

▼pref.xmlでは、設定画面の一番下にある「設定完了」ボタンを表示するためのレイアウトを記述しています。

res/layout/pref.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <ListView android:id="@android:id/list" android:layout_width="fill_parent"
  	android:layout_height="fill_parent" android:layout_weight="1" />

    <LinearLayout android:layout_width="fill_parent"
	android:background="#aaaaaa"	
        android:gravity="center_horizontal"
	android:paddingTop="5dip"
	android:layout_height="wrap_content" >

	<Button android:id="@+id/button"
	    android:layout_width="120dip"
	    android:layout_height="wrap_content"
	    android:text=" 設 定 完 了 " />
    </LinearLayout>
</LinearLayout>

▼preference.xmlでは設定項目を記述しています。

res/xml/preference.xml
<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android">

  <PreferenceCategory
    android:title="@string/cate_title">

    <ListPreference
    	android:key="list"
    	android:title="リストタイトル"
    	android:summary="リストサマリー"
    	android:entries="@array/list_entries"
    	android:entryValues="@array/list_entryValues"
    />

    <EditTextPreference
        android:key="edittext"
        android:title="エディットテキストタイトル"
        android:summary="エディットテキストサマリー"
        android:dialogTitle="ダイアログタイトル"
    />

    <RingtonePreference
        android:key="ringtone"
        android:title="リングトーンタイトル"
        android:summary="リングトーンサマリー"
        android:showDefault="true"
    />

    <CheckBoxPreference
    	android:key="checkbox"
    	android:title="チェックボックスタイトル"
    	android:summary="チェックボックスサマリー"
    />

  </PreferenceCategory>

</PreferenceScreen>

▼array.xmlではリストに表示するための配列(アイテム)を定義しています。

res/values/array.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string-array name="list_entries">
	<item>リスト1</item>
	<item>リスト2</item>
	<item>リスト3</item>
	<item>リスト4</item>
	<item>リスト5</item>
    </string-array>

    <string-array name="list_entryValues">
	<item>1</item>
	<item>2</item>
	<item>3</item>
	<item>4</item>
	<item>5</item>
    </string-array>

</resources>

▼AndroidManifest.xmlでは、設定画面を追加したので21行目~23行目を追加しています。

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="goodroid.sample.config"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ConfigActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="Preference"
                  android:label="@string/app_name">
        </activity>
    </application>

</manifest>


実行結果

9230 views | コメント:2 | 2012-06-30
コメント
Commented by TK at 2013-04-08 12:28:28
はじめまして、TKと申します。

最近開発を始めたばかりなのですが、いろいろな文献をみたり、ネットで調べたりして、このページにたどり着きました。様々なサンプルを拝見しいつもお世話になっています。少しご教授願えたらと思ってコメントさせていただきます。
現在、メインの画面上にラジオボタンで設定を選べるようにして、ボタンを押すとその設定どおり、挙動するようなアプリを作成しています。
起動してそのラジオボタンの選択を変化させて実行後、アプリを終了し、次回起動時には、当然初期設定であるラジオボタン、としているラジオボタンが選択されている状態になります。これを次回起動時には先ほど変化させたラジオボタンが選択された状態で起動したいと考えております。多くの説明では設定画面は設定画面のactivityを指定していますが、設定画面は今回作りたくなく、メインの画面上でそれらを行いたいです。preferenceを用いるのは分かるのですが、クリックしたときに選択しているラジオボタンを記憶させて、次回起動時にそれを反映させる方法がどうしても分かりません。どうかご教授願えないでしょうか?長い文章になってしまい連続投稿申し訳ありませんでした。もし解説いただけるのであれば、この投稿にアドレスを付けましたのでそちらに何か送っていただけたら幸いです。
Commented by KI at 2013-04-14 15:06:35
管理人のKIです。
お返事が遅くなり申し訳ありません。
また、HPの関係でコメントが切れてしまった件も重ねてお詫びいたします。
※1つにまとめさせていただきました。

確かに、Preferenceを用いる方法ではActivityと一緒に表示することはできません。Goodroidでは履歴画面を作成する場合などにはアプリ内にSQLiteを使ったデータベースを作成して対応しております。TK様が作成したい画面は履歴画面とは違うかと思いますが、データベースにラジオボタンの設定値を保持しておけば、次回アプリ起動時にその内容を取得して、再設定することも可能だと思われます。
質問の回答となったかは微妙ですが、参考までにデータベース作成方法のリンクを貼らせていただきます。また、なにかあればお気軽にコメント投稿ください。
http://goodroid.fc2-rentalserver.com/index.php?mode=public&action=techno&pid=115
コメントの投稿
名前 (必須)

メールアドレス (非公開)

本文(必須)

パスワード (必須)
(半角数字4桁)