設定の変更の検出

設定の変更の検出

基本的に設定を変えたらリアルタイムで処理するため
変更したら検出できるようにする必要がある

設定の変更を検出するには
変更を検出したいPreferenceへ
registerOnSharedPreferenceChangeListener
を設定すると変更を検出できる

registerOnSharedPreferenceChangeListener
を実装するには
まずクラスへ

extends PreferenceFragment implements OnSharedPreferenceChangeListener

を追記

そして、onCreate()の中で、設定画面のリソースファイルを読み込む

addPreferencesFromResource(R.xml.pref);

そして
onResume()
inPause()にもリスナーを追記する

@Override
public void onResume(){
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause(){
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}

さらに変更を検知したときの動作を実装

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){

if(PREF_CUSTOMIZE_DIALOG.equals(key)){
String date = sharedPreferences.getString(key,null);

Toast.makeText(getActivity(), "選択した時間: "+date, Toast.LENGTH_SHORT).show();
}
}

今回はトーストで時間を表示している

設定画面の名称や説明を動的変更するには

設定画面の名称や説明を動的変更するには

Preferenceクラスの
setTitle()でタイトルの変更

setSummary()で説明の変更が可能

これは、レイアウトファイルではなくJavaで行う

まず、クラスへ必要なソースを追加する

extends PreferenceFragment implements OnSharedPreferenceChangeListener

を追加する

そして、onCreate()へ

addPreferenceFromResource(R.xml.pref);

でリソースファイルを読み込む

そして、PreferenceManagerクラスの
findPreference()
を使うことで
Preferenceインスタンスを取得

そして、取り出したインスタンスへ対して
setTitle()
setSummary()
を実行して書き換える

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

Preference preference = getPreferenceManager().findPreference(“setting_key”);

if(preference != null){
preference.setTitle(“タイトル変更: setTitle()で変更”);
preference.setSummary(“説明変更: setSummary()で変更”);
}
}
[/xml]

とりあえず、簡単な変更だけと
WiFiの有効化したらチェック項目の文字を変えるなど
用途はいろいろある

チェック形式の設定画面作成 

チェック形式の設定画面作成 

チェック形式の設定は
主に、複数項目を設定するのに使う

たとえば、ホテルを探したり
お店を探すときに条件を複数指定しておけばスムーズに探すことができる

チェック項目の追加には
PreferenceCategoryの中へ
CheckboxPreferenceを追加することでできるようになる

コードにすると

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

<PreferenceCategory
android:title="設定画面">

<CheckboxPreference
android:key="Checkbox_key"
android:summary="位置情報の取得"
android:title="GPSを使用する"/>

</PreferenceCategory>

</PreferenceScreen>

これで、設定画面にチェック項目ができる

選択式の設定画面の追加

選択式の設定画面の追加

設定値をあらかじめ用意した候補から
ラジオボタンなどで1つ選択するなら
PreferenceCategoryの中へ
ListPreferenceを追加することでできる

使い方としては、モード変更とか、言語選択など

これも作成したレイアウトファイルを編集することになる

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

<PreferenceCategory android:title="設定画面">

<ListPreference
android:dialogTitle="リストダイアログタイトル"
android:entries="@array/list_entries"
android:entryValues="@array/list_entryvalues"
android:key="list_key"
android:summary="リスト設定"
android:title="現在の設定"/>

</PreferenceCategory>

</PreferenceScreen>

これで、リスト一覧がでる設定ダイアログがでるようになる

設定画面にテキスト入力の追加

設定画面にテキスト入力の追加

設定画面に
テキスト入力の追加をすることで
駅名とか検索キーワードを入れることができる

テキスト項目の追加は
preferencefileに
EditPreference要素を追加することで可能になる

これは、PreferenceCategoryの中へ書く
PreferenceCategoryごとに設定扱いになるので
ここへ書くことになる

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

<PreferenceCategory android:title="設定画面">

<EditPreference
android:dialogTitle="編集ダイアログ"
android:key="edittext_key"
android:summary="入力設定"
android:title="設定"/>
</PreferenceCategory>

</PreferenceScreen>

これで、設定画面に文字入力ができるようになる

設定画面の作成

設定画面の作成

設定画面とは言っても
Androidの設定画面ではなく
アプリの設定画面

例えば、日付とか乗り換えのための駅名などなど
本来、位置情報とかWebApiなどで
オートでやれればベストだけど
まずは人力から

設定画面の作成には
preferencefileを作成して
プログラム側で
PreferenceFragmentを拡張
そして作成したpreferencefileを読み込んで実装する

まずは、preferencefile作成だけど
これはxmlファイルで
res/xml/
へ作成する

とりあえず、ファイル名はpref.xml

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

<PreferenceCategory 
android:title="設定画面">

</PreferenceCategory>
</PreferenceScreen>

ソースの解説を加えると
PreferenceCategoryの中に
設定画面に設置したい項目を定義していく
なお、PreferenceCategoryは複数定義が可能で
android:title=””
で設定した文字列がタイトルとして表示されることになる

次に、設定画面の作成
これは
作成したpreferencefileを読み込む
PreferenceFragmentを作成してActivityへ追加する

まずは、onCreate()へ追加

getFragmentManager().beginTransaction().replace(android.R.id.content, 
new MyPreferenceFragment()).commit();

ActionBar actionbar = getActionBar();
actionbar.setHomeButtonEnabled(true);

setHomeButtonEnabled(true)
で戻るボタンの設置

そして、PreferenceFragmentの作成

public static class MyPreferenceFragment extends PreferenceFragment{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);

addPreferencesFromResource(R.xml.pref);
}
}

これで、設定画面が作成できる

メニュー表示の動的変更

メニュー表示の動的変更

メニューを動的変更する例として
アプリが編集モードになったときなどには
メニューを隠したり、切り替えをする

メニュー表示を変更するには
Activityクラスの
invalidateOptionsMenu()
を使う

まずは、通常どおりにメニューを作成する
これは、レイアウトファイルなので
res/menu/
の直下へ作成する

<menu
xmlns:android="http://scheams.android.com/apk/res/android">

<item
android:id="@+id/action_search"
android:icon="@android:drawable/ic_menu_search"
android:title="検索"
android:showAsAction="ifRoom|withText"/>
</menu>

これでメニューの作成
ちなみに、
showAsAction=””
は、|で複数パターンの指定が可能

復習すると
ifRoom
ActionBarの領域に余裕があるなら
表示

withText
余裕があって表示できたら文字も表示

となる
つまり、
showAsAction=”ifRoom|withText”
なので
画面が小さくて表示できないなら
メニューボタンへ格納
そうでないならメニューアイコンと文字を表示
としている

次に、JavaでActivityの定義

mSwitch = (Switch)findViewById(R.id.searchMode);
mSwitch.setOnCheckedChangeListener(this);

次は、メニューの書き換え
メニューをクリックしたタイミングで
invalidateOptionsMenu()
を実行することで、メニューの書き換えをする

invalidateOptionsMenu()が実行されると
Activityの
onCreateOptionsMenu()

onPrepareOptionsMenu()
が再実行され
画面の状況に応じて
MenuItemが書き換えられる

ソースは

@Override
public boolean onCreateOptionsMenu(Menu menu){

getMenuInflater().inflate(R.menu.dynamic_menu, menu);
return super.onCreateOptionsMenu(menu);

}

@Override
public void onCheckedChanged(CompoundButton v , boolean isChecked){

int id = v.getId();
if(id == R.id.searchMode){
invalidateOptionsMenu();
}
}

@Override
public boolean onPrepareOptionsMenu(Menu menu){
MenuItem search = menu.findItem(R.id.action_search);
search.setVisible(mSwitch.isChecked());
return super.onPrepareOptionsMenu(menu);
}

となる

メニュー表示の制御

メニュー表示の制御

メニューの表示、非表示の制御方法は2つ

1アクションオーバーフローの利用

2android:visible=””でfalseを指定する

一般的には、アクションオーバーフローを使い
使うときに、ActionBarをタップすることでメニュー表示する

これに対して、
android:visible=”false”
とすると、タップしても表示されない

今回やるのは
アクションオーバーフローのほう

アクションオーバーフローは
ActionBarに表示しきれないアイテムをまとめたボタンのこと

基本的には、よく使うメニューは
ActionBarへ表示しておいて
あまり使わないものは
ActionOverflowへ隠しておくのが一般的

この制御は、
レイアウトファイルのXMLファイルで
android:showAsAction=””
を指定する

指定できるのは
never
ActionBarへ表示せず
常にActionOverflowへ配置

ifRoom
ActionBarの表示領域に余裕があるなら
ActionBarへ表示
もしないのならActionOverflowへ配置する

withText
ActionItemとして表示されるときに
android:title=””に設定した値も同時に表示する

always
常にActionBarへ表示する
ただし、レイアウトが崩れる可能性がある

何も指定しないとnever扱いになる

ActionBarに表示するときには、基本的にわかりやすくアイコンにすることが多い

<menu xmlns:android="http://scheams.android.com/apk/res/android">

<item
android:icon="@android.drawable/ic_menu_share"
android:showAsAction="never"
android:title="showAsAction: never"/>

<item
android:icon="@android.drawable/ic_menu_call"
android:showAsAction="ifRoom"
android:title="showAsAction: ifRoom"/>

<item
android:icon="@android.drawable/ic_menu_compass"
android:showAsAction="withText"
android:title="showAsAction: withText"/>

<item
android:icon="@android.drawable/ic_menu_agenda"
android:showAsAction="always"
android:title="showAsAction: always"/>
</menu>

Androidはデバイスごとに画面の大きさがかわるため
端末ごとにifRoomにして対応するか
もしくはシンプルに
neverで統一したほうが使いやすい

ActionBarへSpinner設置

ActionBarへSpinner設置

ActionBarにはSpinnerを設置できる機能が標準で搭載されている

ただし、見た目はSpinnerだけど
ドロップダウンナビゲーションと呼ばれる

Spinnerを使うには
ActionBarへ
DropDownNavigation
を使うための宣言をする

この宣言をすることでActionBarに
ナビゲーションがでるようになる

getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

次にタイトルの非表示設定

これは、タイトルを非表示にして
DropDownNavigationをタイトルの代わりに使うため

getActionBar.setDisplayShowTitleEnabled(false);

例えば、Android標準のギャラリーとか
Gmailアプリの場合だと
タイトルの代わりにフィルターになっている

ほかにも探すといろいろなアプリごとの特徴があるので面白い

これで、次にリストへアイテムを追加する
Spinnerなどに設定するAdapterなどと同じように
まずArrayAdapter
文字列を設定したものを用意する

今回はテストデータということで
スマホのosにしてみた

//DropDownListへの追加項目
List<String> list = new ArrayList<String>();
list.add("iOS");
list.add("Android");
list.add("Window");

mAdapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_spinner_dropdown_item,
android.R.id.text,
list
);

getActionBar().setListNavigationCallbacks(mAdapter,this);

次に、指定したActivityへ
OnNavigationListenerをセット

今回はthis

このため、Activityへ

implements OnNavigationListener

を追加する

また、そのほかにも必要なコード追加する

private ArrayAdapter<String> mAdapter;


@Override
public boolean onNavigationItemSelected(int position, long itemId){
String item = mAdapter.getItem(position);
Toast.makeText(this,"この項目を選択したよ", ToastLENGH_SHORT).show();
return false;
}

DropDownNavigationは、画面遷移のためのインターフェースとして使われることが多く
Google製アプリでよく使われる
Google Mapなら画面左下にあり
Gmailなら画面左上にある

いろいろなアプリを見てレイアウトを参考にすると
より使いやすいアプリになる

ActionBarへメニュー追加

ActionBarへメニュー追加

最近のハードウェアではメニューボタンがなくなりつつあるため
ActionBarへメニューを表示するのがほとんど

WordPress とかGmailなどのアプリでも
画面の右上がメニューになっている

ActionBarへメニューを表示するには
以下のコードを追加する

@Override
public boolean onCreateOptionsItemMenu(Menu menu){
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item){
int itemId = item.getItemId();
if(itemId == R.id.action_setting){
Toast.makeText(this, "設定ボタン",Toast.LENGH_SHORT).show();
}
return  super.onOptionsItemSelected(item);
}

メニューのリソースファイルは
res/menu
の下へ作る

今回なら
R.menu.main
としている

これは、
res/menu/main.xml
を指している

ソースは

<menu xmlns:android="http://scheams.android.com/apk/res/android">
<item
android:id="@+id/action_setting"
android:orderInCategory="100"
android:showAsAction="never"
android:title="setting"/>
</menu>

android:orderInCategory=””
は、メニューアイテムの重ねる順番で
この数値が大きいものが上になる

これについては
http://kamiyasu2.blog.fc2.com/blog-entry-3.html
を参考にさせていただきました

android:showAsAction=”never”
は、メニューボタンを押したときのみ
メニューが表示される設定

これについては
http://zaya3.blog.fc2.com/blog-entry-92.html
を参考にさせていただきました

詳しい解説については
http://developer.android.com/guide/topics/resources/menu-resource.html
が参考になります