[Android] レイアウト (1) レイアウトの概要 ================================================================================ Android では、4 種類のレイアウトがある。 LinearLayout ウィジェットを縦または横に並べて配置(ボックス・モデル) RelativeLayout 他のウィジェットとの相対位置を基にして自分を配置 (ルールベース・モデル) TableLayout テーブル形式でウィジェットを配置(グリッド・モデル) FrameLayout ひとつのウィジェットを配置 参考 ソフトウェア技術ドキュメントを勝手に翻訳 Android 開発ガイド > フレームワークトピック > 6. ユーザインターフェイス > 6.b 共通レイアウトオブジェクト http://www.techdoctranslator.com/android/guide/ui/layout-objects レイアウトは、ViewGroup と、ViewGroup.LayoutParams で特徴づけられる。 また、それぞれのレイアウトは、ViewGroup.LayoutParams から継承される xxx.LayoutParams がある。(xxx は、AbsListView、RelativeLayout、LinearLayout、 FrameLayout) それぞれの継承関係は以下のとおり。 ================ AbsListView --- .LayoutParams | ---------------- | x | y | ================ | | ============= =================== | ================ ViewGroup ViewGroup | RelativeLayout .LayoutParms <|--- .MarginLayoutParams <|-+-- .LayoutParms ------------ ------------------- | ---------------- height marginBottom | above weidth marginLeft | below ============ marginRight | alignLeft marginTop | alignRight =================== | toLeftOf | torightOf | centerHorizontal | centerVertical | ================ | | | ================ | LinearLayout | .LayoutParms | ---------------- | gravity | weight | ================ | | | ================ | FrameLayout --- .LayoutParms ---------------- gravity ================ 画面のサイズは、要求サイズと実サイズの 2 種類ある。それぞれ、つぎのメソッドで取 得できる。 ・サイズを取得する View クラスのメソッド --- int getMeasuredWidth() 要求している幅 int getMeasuredHeight() 要求している高さ int getWidth() 実際の幅 int getHeight() 実際の高さ --- □ ViewGroup クラス java.lang.Object + android.view.View + android.view.ViewGroup ウィジェットを取りまとめることができるビューのスーパークラス。 XML 属性(属性名の前に、名前空間プレフィックス android: がつく) --- android:addStatesFromChildren android:alwaysDrawnWithCache android:animateLayoutChanges android:animationCache android:clipChildren android:clipToPadding android:descendantFocusability android:layoutAnimation android:persistentDrawingCache --- □ ViewGroup.LayoutParams クラス java.lang.Object + android.view.ViewGroup.LayoutParams ViewGroup の内部クラスで、画面のサイズに関するスーパークラス。 XML 属性(属性名の前に、名前空間プレフィックス android: がつく) --- android:layout_height ビューの高さ android:layout_width ビューの幅 --- 属性の値 --- 属性値 値 説明 fill_parent -1 他のウィジェットの処理後にあまっている部分もすべて使うサイズ match_parent -1 fill_parent と同じ(Android2.2 以降ではこちらが推奨) wrap_content -2 ウィジェットが入るサイズ。ウィジェットが大きいときは折り返す 値 正数 単位つきの実正数を指定 --- △ 実正数の単位 Dimension http://developer.android.com/intl/ja/guide/topics/resources/more-resources.html#Dimension --- dp Density-independent Pixels - dpiを基本にした相対的な単位。 160dpi の画面では、1dp = 1px となる sp Scale-independent Pixels - フォントサイズを基本にした相対的な単位。 pt Points - 物理的な画面での大きさ (1/72 inch = 1 pt) px Pixels - 物理的な画面でのドット数 mm Millimeters - 物理的な画面での大きさ in Inches - 物理的な画面での大きさ --- □ ViewGroup.MarginLayoutParams java.lang.Object + android.view.ViewGroup.LayoutParams + android.view.ViewGroup.MarginLayoutParams ViewGroup.LayoutParams のサブクラスで、レイアウトのマージンに関するクラス。 XML 属性(属性名の前に、名前空間プレフィックス android: がつく) --- android:layout_marginBottom android:layout_marginLeft android:layout_marginRight android:layout_marginTop --- Java では、 void setMargins(int left, int top, int right, int bottom) メソッドを使って動的に変更できる。 以上
[Java] アナグラムを作る ================================================================================ アナグラム (anagram) とは、言葉遊びのひとつ。単語または文の中の文字をいくつか入れ替えることによってまったく別の意味にさせる遊びである。 (ウィキペディア、http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%8A%E3%82%B0%E3%83%A9%E3%83%A0 より) ただ、今回のプログラムは、意味はなく、文字を入れ替えるだけである。 ただし、つぎの点には気をつけた。 ・同じ文字列にならない ・単語の先頭に行頭禁則和字が来ない 行頭禁則和字は以下の文字とする。 ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎ 実際に必要なメソッドは、つぎの 2 つ。 public static String anagram(String s) 文字列のアナグラムを作る。 private static boolean isIllegalCharacters(List<Character> list) 不正な文字列かどうか判断する。 これとは別に、単なる配列検索のユーティリティとして、つぎのメソッドを用意した。 private static int search(char[] a, char key) 配列から値を検索する。 □ Anagram.java --- import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class Anagram { public static void main(String[] args) { System.out.println(anagram("")); System.out.println(anagram("ア")); System.out.println(anagram("アイスクリーム")); System.out.println(anagram("ドック")); System.out.println(anagram("キャット")); } /** * 文字列のアナグラムを作る。 * ただし、アナグラムを作れないような文字数のときは、その文字列をそのまま返す。 * * @param s * 文字列 * @return s のアナグラム */ public static String anagram(String s) { if (s.length() < 2) { return s; } List<Character> list = new ArrayList<Character>(); for (char c : s.toCharArray()) { list.add(c); } char[] cs; do { // 同じ文字列でないようにする do { // 不正な文字列でないようにする Collections.shuffle(list); } while (isIllegalCharacters(list)); cs = new char[list.size()]; for (int i = 0; i < cs.length; i++) { cs[i] = list.get(i); } } while (String.valueOf(cs).equals(s)); return String.valueOf(cs); } /** * 不正な文字列かどうか判断する。 * ここでは、行頭禁則文字があると、不正な文字列とする。 * 行頭禁則和字は以下の文字 * ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎ * @param list * 文字列を表すリスト * @return 不正な文字列であれば、true */ private static boolean isIllegalCharacters(List<Character> list) { final char[] START_LINE_ILLEGAL_CHARACTERS = { 'ヽ', 'ヾ', 'ー', 'ァ', 'ィ', 'ゥ', 'ェ', 'ォ', 'ッ', 'ャ', 'ュ', 'ョ', 'ヮ', 'ヵ', 'ヶ', 'ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ', 'っ', 'ゃ', 'ゅ', 'ょ', 'ゎ', }; return search(START_LINE_ILLEGAL_CHARACTERS, list.get(0)) != -1; } /** * 指定された char 値の配列から指定された値を検索する。 * @param a 検索される配列 * @param key 検索される値 * @return 配列に検索キーがある場合は検索キーのインデックス。 検索キーがリストにない場合は -1. */ private static int search(char[] a, char key) { for (int i = 0; i < a.length; i++) { if (a[i] == key) { return i; } } return -1; } } --- □ 実行結果例 --- リアイクースム ドクッ キットャ --- 以上
[Android] フォント ================================================================================ ■ 組込みのフォント つぎの 4 つのフォントが組込みで使える。 normal sans serif monospace これらは、android:typeface 属性で出てくるものである。 ただし、日本語のフォントは変わらないみたい。 また、フォントのスタイルには、つぎの 3 つがある。 normal bold italic ■ フォントの追加 また、使いたいフォントを、Android 実機に追加して使用することもできる。 フォントは True Type Font(ttf ファイル)を assets フォルダーの中に入れる。 今回は、assets フォルダーの中に fonts フォルダーを作り、ダウンロードしてきた 3 つの ttf ファイルを入れて、それをボタンによってサイクリックに換えている。 フォントは しねきゃぷしょん http://chiphead.jp/font.htm よりダウンロードしたものを使っている。 字幕フォント cinecaption227.ttf ファミコン・フォント FAMania2.6.ttf トンパ文字 tompa1.50.ttf 設定としては、ttf ファイルを assets フォルダーに入れたら、プログラムでは、以下の ようにするだけ。 Typeface tf = Typeface.createFromAsset(getAssets(), ttfファイルへのパス); ウィジェット.setTypeface(tf); これらの指定は、ウィジェット全体に適用する。 --- ★ 文章の中の一部だけを変更したいような場合は、HTML などを使う必要があるかもしれ ない。 --- --- ★ 実機の機種によって、追加したフォントが使えたり使えなかったりする。字幕みたい なフォント cinecaption227.ttf が、IdeaPad A1 では使えて、Dell Streak では使えな い。ただし、例外が出るわけではなく、対応する文字がないという感じ。なぜ? なお、エミュレーターでも出なかった。 --- ▲ アクティビティ ダウンロードしてきたフォントを、ボタンがクリックされるたびにサイクリックに変更す る。 □ TrueTypeFont01Activity.java --- package jp.marunomaruno.android.truetypefont; import android.app.Activity; import android.graphics.Typeface; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class TrueTypeFont01Activity extends Activity { private int fontIndex = 0; // (1) private String[] names; private String[] descriptions; private Typeface[] typefaces; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); names = getResources().getStringArray(R.array.fontName); // (2) descriptions = getResources().getStringArray(R.array.fontDescription); // (3) String[] files = getResources().getStringArray(R.array.fontFile); // (4) typefaces = new Typeface[files.length]; for (int i = 1; i < typefaces.length; i++) { typefaces[i] = Typeface.createFromAsset(getAssets(), "fonts/" + files[i]); // (5) } typefaces[0] = Typeface.DEFAULT; // (6) } public void onClickNextFont(View view) throws Exception { try { fontIndex++; // (7) fontIndex %= names.length; // (8) TextView fontName = (TextView) findViewById(R.id.fontName); fontName.setText(names[fontIndex]); TextView fontText = (TextView) findViewById(R.id.fotTtext); fontText.setTypeface(typefaces[fontIndex]); // (9) fontText.setText(String.format("%s%n%s%n", getString(R.string.hello), descriptions[fontIndex])); } catch (Exception e) { // (10) e.printStackTrace(); throw e; } } } --- (1)(7)(8) サイクリックに変更するためのインデックス インデックスの定義 private int fontIndex = 0; // (1) フォントが使われるたびにインクリメントして、フォントの数で割った余りをふたたび使 うようにする。 fontIndex++; // (7) fontIndex %= names.length; // (8) (2)(3)(4) フォント名、ファイル名、フォントを使った文章を取得 res/values/strings.xml に、string-array 要素として設定してある。 names = getResources().getStringArray(R.array.fontName); // (2) descriptions = getResources().getStringArray(R.array.fontDescription); // (3) String[] files = getResources().getStringArray(R.array.fontFile); // (4) (5) Typeface オブジェクトの生成 typefaces[i] = Typeface.createFromAsset(getAssets(), "fonts/" + files[i]); // (5) (6) デフォルト・フォントを設定 typefaces[0] = Typeface.DEFAULT; // (6) (9) Typeface オブジェクトの設定 fontText.setTypeface(typefaces[fontIndex]); // (9) (10) 例外の処理 フォントのファイル (ttf ファイル)がないときは、RuntimeException がスローされる。 メッセージはつぎのとおり。 java.lang.RuntimeException: native typeface cannot be made キャッチして、スタックトレースだけ出し、今回は、そのままスローしなおす。 catch (Exception e) { // (10) □ Typeface クラス java.lang.Object + android.graphics.Typeface フォントを管理するクラス。 定数としては、フォントのタイプを表すものと、組込みのフォントが用意されている。 定数 --- int BOLD int BOLD_ITALIC int ITALIC int NORMAL Typeface DEFAULT Typeface DEFAULT_BOLD Typeface MONOSPACE Typeface SANS_SERIF Typeface SERIF --- ttf ファイルを指定して、フォントを生成する。 メソッド --- static Typeface create(String familyName, int style) static Typeface create(Typeface family, int style) static Typeface createFromAsset(AssetManager mgr, String path) static Typeface createFromFile(String path) static Typeface createFromFile(File path) static Typeface defaultFromStyle(int style) int getStyle() final boolean isBold() final boolean isItalic() --- ▲ レイアウト □ 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:layout_width="fill_parent" android:layout_height="wrap_content" android:text="normal アイスクリーム" android:textAppearance="?android:attr/textAppearanceLarge" android:typeface="normal" /> <!-- (1) --> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="sans アイスクリーム" android:textAppearance="?android:attr/textAppearanceLarge" android:typeface="sans" /> <!-- (2) --> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="serif アイスクリーム" android:textAppearance="?android:attr/textAppearanceLarge" android:typeface="serif" /> <!-- (3) --> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="monospace アイスクリーム" android:textAppearance="?android:attr/textAppearanceLarge" android:typeface="monospace" /> <!-- (4) --> <TextView android:id="@+id/fontName" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/defaultFont" android:textAppearance="?android:attr/textAppearanceLarge" /> <!-- (5) --> <Button android:id="@+id/nextFontButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClickNextFont" android:text="@string/nextFontButton" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/fotTtext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:textAppearance="?android:attr/textAppearanceLarge" /> <!-- (6) --> </LinearLayout> --- (1)(2)(3)(4) 組込みフォントを表示 android:typeface 属性を使って、それぞれ、組込みフォントを表示している。 normal sans serif monospace (5) android:typeface 属性なし デフォルトは normal かな。 (6) 追加フォントの文字を表示 上記サンプルでは使っていないが、太字などにする android:textStyle 属性もある。 以下の値が指定できる。 normal bold italic 複数の値を指定したいときは、パイプ(|) を使って指定する。 ▲ リソース □ res/values/strings.xml --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, TrueTypeFont01Activity!</string> <string name="app_name">TrueTypeFont01</string> <string name="defaultFont">デフォルトのフォント</string> <string name="nextFontButton">次のフォント</string> <string-array name="fontName"> <item>@string/defaultFont</item> <item>字幕フォント</item> <item>ファミコン・フォント</item> <item>トンパ文字</item> </string-array> <string-array name="fontFile"> <item>-</item> <item>cinecaption227.ttf</item> <item>FAMania2.6.ttf</item> <item>tompa1.50.ttf</item> </string-array> <string-array name="fontDescription"> <item>@string/defaultFont</item> <item>字幕みたいなフォント</item> <item>ファミコンもどきのフォント</item> <item>阿葵悪安伊亥一壱丑浦英猿岡億下加夏賀介角</item> <!-- トンパ文字に対応する文字が少ないため、適当な文字列 --> </string-array> </resources> -- なお、トンパ文字に対応する文字が少ないため、適当な文字列を記述している。 フォントの説明によると、現在は 150 文字を登録している、とのこと。 以上
[Android] フォント
================================================================================
■ 組込みのフォント
つぎの 4 つのフォントが組込みで使える。
normal
sans
serif
monospace
これらは、android:typeface 属性で出てくるものである。
ただし、日本語のフォントは変わらないみたい。
また、フォントのスタイルには、つぎの 3 つがある。
normal
bold
italic
■ フォントの追加
また、使いたいフォントを、Android 実機に追加して使用することもできる。
フォントは True Type Font(ttf ファイル)を assets フォルダーの中に入れる。
今回は、assets フォルダーの中に fonts フォルダーを作り、ダウンロードしてきた 3
つの ttf ファイルを入れて、それをボタンによってサイクリックに換えている。
フォントは
しねきゃぷしょん
http://chiphead.jp/font.htm
よりダウンロードしたものを使っている。
字幕フォント cinecaption227.ttf
ファミコン・フォント FAMania2.6.ttf
トンパ文字 tompa1.50.ttf
設定としては、ttf ファイルを assets フォルダーに入れたら、プログラムでは、以下の
ようにするだけ。
Typeface tf = Typeface.createFromAsset(getAssets(), ttfファイルへのパス);
ウィジェット.setTypeface(tf);
これらの指定は、ウィジェット全体に適用する。
---
★ 文章の中の一部だけを変更したいような場合は、HTML などを使う必要があるかもしれ
ない。
---
---
★ 実機の機種によって、追加したフォントが使えたり使えなかったりする。字幕みたい
なフォント cinecaption227.ttf が、IdeaPad A1 では使えて、Dell Streak では使えな
い。ただし、例外が出るわけではなく、対応する文字がないという感じ。なぜ?
なお、エミュレーターでも出なかった。
---
▲ アクティビティ
ダウンロードしてきたフォントを、ボタンがクリックされるたびにサイクリックに変更す
る。
□ TrueTypeFont01Activity.java
---
package jp.marunomaruno.android.truetypefont;
import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class TrueTypeFont01Activity extends Activity {
private int fontIndex = 0; // (1)
private String[] names;
private String[] descriptions;
private Typeface[] typefaces;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
names = getResources().getStringArray(R.array.fontName); // (2)
descriptions = getResources().getStringArray(R.array.fontDescription); // (3)
String[] files = getResources().getStringArray(R.array.fontFile); // (4)
typefaces = new Typeface[files.length];
for (int i = 1; i < typefaces.length; i++) {
typefaces[i] = Typeface.createFromAsset(getAssets(), "fonts/"
+ files[i]); // (5)
}
typefaces[0] = Typeface.DEFAULT; // (6)
}
public void onClickNextFont(View view) throws Exception {
try {
fontIndex++; // (7)
fontIndex %= names.length; // (8)
TextView fontName = (TextView) findViewById(R.id.fontName);
fontName.setText(names[fontIndex]);
TextView fontText = (TextView) findViewById(R.id.fotTtext);
fontText.setTypeface(typefaces[fontIndex]); // (9)
fontText.setText(String.format("%s%n%s%n",
getString(R.string.hello), descriptions[fontIndex]));
} catch (Exception e) { // (10)
e.printStackTrace();
throw e;
}
}
}
---
(1)(7)(8) サイクリックに変更するためのインデックス
インデックスの定義
private int fontIndex = 0; // (1)
フォントが使われるたびにインクリメントして、フォントの数で割った余りをふたたび使
うようにする。
fontIndex++; // (7)
fontIndex %= names.length; // (8)
(2)(3)(4) フォント名、ファイル名、フォントを使った文章を取得
res/values/strings.xml に、string-array 要素として設定してある。
names = getResources().getStringArray(R.array.fontName); // (2)
descriptions = getResources().getStringArray(R.array.fontDescription); // (3)
String[] files = getResources().getStringArray(R.array.fontFile); // (4)
(5) Typeface オブジェクトの生成
typefaces[i] = Typeface.createFromAsset(getAssets(), "fonts/"
+ files[i]); // (5)
(6) デフォルト・フォントを設定
typefaces[0] = Typeface.DEFAULT; // (6)
(9) Typeface オブジェクトの設定
fontText.setTypeface(typefaces[fontIndex]); // (9)
(10) 例外の処理
フォントのファイル (ttf ファイル)がないときは、RuntimeException がスローされる。
メッセージはつぎのとおり。
java.lang.RuntimeException: native typeface cannot be made
キャッチして、スタックトレースだけ出し、今回は、そのままスローしなおす。
catch (Exception e) { // (10)
□ Typeface クラス
java.lang.Object
+ android.graphics.Typeface
フォントを管理するクラス。
定数としては、フォントのタイプを表すものと、組込みのフォントが用意されている。
定数
---
int BOLD
int BOLD_ITALIC
int ITALIC
int NORMAL
Typeface DEFAULT
Typeface DEFAULT_BOLD
Typeface MONOSPACE
Typeface SANS_SERIF
Typeface SERIF
---
ttf ファイルを指定して、フォントを生成する。
メソッド
---
static Typeface create(String familyName, int style)
static Typeface create(Typeface family, int style)
static Typeface createFromAsset(AssetManager mgr, String path)
static Typeface createFromFile(String path)
static Typeface createFromFile(File path)
static Typeface defaultFromStyle(int style)
int getStyle()
final boolean isBold()
final boolean isItalic()
---
▲ レイアウト
□ 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:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="normal アイスクリーム"
android:textAppearance="?android:attr/textAppearanceLarge"
android:typeface="normal" /> <!-- (1) -->
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="sans アイスクリーム"
android:textAppearance="?android:attr/textAppearanceLarge"
android:typeface="sans" /> <!-- (2) -->
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="serif アイスクリーム"
android:textAppearance="?android:attr/textAppearanceLarge"
android:typeface="serif" /> <!-- (3) -->
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="monospace アイスクリーム"
android:textAppearance="?android:attr/textAppearanceLarge"
android:typeface="monospace" /> <!-- (4) -->
<TextView
android:id="@+id/fontName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/defaultFont"
android:textAppearance="?android:attr/textAppearanceLarge" /> <!-- (5) -->
<Button
android:id="@+id/nextFontButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClickNextFont"
android:text="@string/nextFontButton"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/fotTtext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
android:textAppearance="?android:attr/textAppearanceLarge" /> <!-- (6) -->
</LinearLayout>
---
(1)(2)(3)(4) 組込みフォントを表示
android:typeface 属性を使って、それぞれ、組込みフォントを表示している。
normal
sans
serif
monospace
(5) android:typeface 属性なし
デフォルトは normal かな。
(6) 追加フォントの文字を表示
上記サンプルでは使っていないが、太字などにする android:textStyle 属性もある。
以下の値が指定できる。
normal
bold
italic
複数の値を指定したいときは、パイプ(|) を使って指定する。
▲ リソース
□ res/values/strings.xml
---
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, TrueTypeFont01Activity!</string>
<string name="app_name">TrueTypeFont01</string>
<string name="defaultFont">デフォルトのフォント</string>
<string name="nextFontButton">次のフォント</string>
<string-array name="fontName">
<item>@string/defaultFont</item>
<item>字幕フォント</item>
<item>ファミコン・フォント</item>
<item>トンパ文字</item>
</string-array>
<string-array name="fontFile">
<item>-</item>
<item>cinecaption227.ttf</item>
<item>FAMania2.6.ttf</item>
<item>tompa1.50.ttf</item>
</string-array>
<string-array name="fontDescription">
<item>@string/defaultFont</item>
<item>字幕みたいなフォント</item>
<item>ファミコンもどきのフォント</item>
<item>阿葵悪安伊亥一壱丑浦英猿岡億下加夏賀介角</item>
<!-- トンパ文字に対応する文字が少ないため、適当な文字列 -->
</string-array>
</resources>
--
なお、トンパ文字に対応する文字が少ないため、適当な文字列を記述している。
フォントの説明によると、現在は 150 文字を登録している、とのこと。
以上
[Android] インテント (2) - アクティビティからの結果の受け取り ================================================================================ インテントを使って呼び出したアクティビティから、結果を受け取ることができる。 呼び出す側: ・startActivityForResult() メソッドを使ってアクティビティを起動する ・onActivityResult() メソッドをオーバーライドして、結果を受け取ったときの処理を記述する 呼び出された側: ・必要に応じて、結果を戻すためのインテント・オブジェクトを生成して、データを設定する ・setResult() メソッドで、結果コードや戻すデータを設定する ・finish() メソッドで、アクティビティを終了する ■ 呼び出す側 ▲ アクティビティ インテント起動ボタンを押下したら、startActivityForResult() メソッドを使ってアクティビティを起動する。 onActivityResult() メソッドをオーバーライドして、結果を受け取ったときの処理を記述する。このとき、単語が指定されていれば、この単語を逆順にした文字列を表示する。 単語が指定されていなければ、その旨のメッセージを表示する。 □ Intent02Activity.java --- package jp.marunomaruno.android.intent; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.TextView; public class Intent02Activity extends Activity { private static final int REQUEST_REVERSE_ACTIVITY = 1; // (1) /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } /** * 暗黙的にインテントを起動する。 * * @param view */ public void onClickImplisitButton(View view) { EditText edit1 = (EditText) findViewById(R.id.editText1); Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra("message", edit1.getText()); startActivityForResult(intent, REQUEST_REVERSE_ACTIVITY); // (2) } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // (3) super.onActivityResult(requestCode, resultCode, data); // (4) TextView text1 = (TextView) findViewById(R.id.text1); switch (requestCode) { // (5) case REQUEST_REVERSE_ACTIVITY: // (6) switch (resultCode) { // (7) case Activity.RESULT_OK: // (8) String reverse = data.getStringExtra("reverse"); text1.setText(reverse); break; case RESULT_FIRST_USER + OtherActivity.NO_WORDS: // (9) text1.setText(R.string.noWordsMessage); break; default: text1.setText(String.format("onActivityResult() resultCode=%d", resultCode)); break; } break; default: text1.setText(String.format("onActivityResult() requestCode=%d", requestCode)); break; } } } --- (1) 逆順文字列作成のためのインテント要求コードを定義する private static final int REQUEST_REVERSE_ACTIVITY = 1; // (1) これは、startActivityForResult() メソッドで指定する。これによって、アクティビティから結果が戻ってきたら、この値を確認することで、どのインテントを使ってアクティビティを呼び出したかがわかる。 (2) 結果を受け取るためのインテントを起動する 要求コードを指定する。 startActivityForResult(intent, REQUEST_REVERSE_ACTIVITY); // (2) (3)(4) インテントの結果を受け取る Activity クラスのこのメソッドをオーバーライドする。 protected void onActivityResult(int requestCode, int resultCode, Intent data) { // (3) requestCode: startActivityForResult() で指定した要求コード resultCode: 戻りコード data: データ スーパークラスの同メソッドを呼び出す。 super.onActivityResult(requestCode, resultCode, data); // (4) (5) 要求コードによって処理を切り分ける switch (requestCode) { // (5) (6) 逆順文字列作成の要求コード case REQUEST_REVERSE_ACTIVITY: // (6) (7) 結果の戻りコードによって処理を切り分ける switch (resultCode) { // (7) Activity クラスで定義している結果コードは次の 3 つ。 --- int RESULT_CANCELED 0 キャンセルされた int RESULT_FIRST_USER 1 自分で定義する結果コードの最初の値 int RESULT_OK -1 結果成功 --- したがって、自分で定義する結果コードは 1 から順番に振る方がよい。 (8) 結果が OK のときの処理 case RESULT_OK: // (8) (9) 単語が指定していなかったときの処理 case RESULT_FIRST_USER + OtherActivity.NO_WORDS: // (9) 値としては、RESULT_FIRST_USER は 1 で、OtherActivity.NO_WORDS は 1 にしているので、2 となっている。 (RESULT_FIRST_USER は加えなくても大丈夫) ▲ レイアウト □ res/layout/main.xml ※前回のプロジェクトと同じ ■ 呼び出される側 ▲ アクティビティ 受け取った文字列の逆順文字列を送る。 受け取った文字列が空でなければ、逆順文字列を作る。そのときの結果コードは RESULT_OK (値は -1)。 文字列が空だったら、結果コードとして、2 (= RESULT_FIRST_USER + NO_WORDS) を設定して返す。 □ OtherActivity.java --- package jp.marunomaruno.android.intent; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class OtherActivity extends Activity { public static final int NO_WORDS = 1; // (1) private String message; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); Intent intent = getIntent(); TextView text1 = (TextView) findViewById(R.id.otherTextView1); message = intent.getCharSequenceExtra("message").toString(); text1.setText(message); } public void onClickBackButton(View view) { Intent returnIntent = new Intent(); // (2) returnIntent.putExtra("reverse", reverse(message)); // (3) if (message.length() > 0) { setResult(RESULT_OK, returnIntent); // (4) } else { setResult(RESULT_FIRST_USER + NO_WORDS, returnIntent); // (5) } finish(); // (6) } /** * 文字列を逆並び順にした文字列を返す。 * @param s 文字列 * @return 逆並び順にした文字列 */ private String reverse(String s) { return new StringBuilder(s).reverse().toString(); } } --- (1) 文字列が空のときの結果コード public static final int NO_WORDS = 0; // (1) (2)(3) 戻すためのデータを設定する そのためのインテント・オブジェクトを生成する。 Intent returnIntent = new Intent(); // (2) インテントにデータを設定する。このとき、逆並び順の文字列を作る。 returnIntent.putExtra("reverse", reverse(message)); // (3) (4) 空の文字列でなければ、結果コード RESULT_OK とする setResult(RESULT_OK, returnIntent); // (4) (5) 空の文字列のとき、その旨の結果コードを指定する setResult(RESULT_FIRST_USER + NO_WORDS, returnIntent); // (5) (6) アクティビティを終わる finish(); // (6) ▲ レイアウト 呼び出し元のアクティビティに戻るボタンをつけた。 □ res/layout/other.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/otherTextView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" /> <Button android:id="@+id/backButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClickBackButton" android:text="@string/backButtonLabel" /> </LinearLayout> --- ■ マニュフェスト ※前回のプロジェクトと同じ ■ リソース □ res/values/strings.xml --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Intent02</string> <string name="implicitButtonLabel">逆並び順文字列を作る</string> <string name="backButtonLabel">確認</string> <string name="noWordsMessage">単語が指定されていません。</string> </resources> --- 以上
[Android] インテント (1) - インテントを使ったアクティビティの呼び出し ================================================================================ インテントは、プログラムの実行に関する情報を管理するメッセージである。 プログラムの実行時に、実行に関する情報がインテントというメッセージにまとめられる。 このインテントを発行することで、プログラムを実行させることができる。また、逆に、 プログラムには、自身が受け取れるインテントの種類を記述できる。 インテントは、つぎの主要な情報によって構成している。 ・アクション 動作 ・カテゴリー インテントに対する追加のメタデータ ・データ インテントに与えるデータで、URI として表現 ・エクストラ Bundle 型のインテントに渡されるデータ ・フラグ アクティビティの起動方法 ・タイプ MIME タイプ(操作したいリソースの種類) ・コンポーネント インテントを利用するパッケージやクラスを明示的に指定 アクションとカテゴリーは単なる文字列で表現している。 データは Uri オブジェクトで定義する。Uri オブジェクトは、RFC3986 で定義された URI である。 インテントには、メッセージの送信先の指定方法によって、次の 2 つの種類がある。 ・明示的インテント メッセージを送る相手のプログラムのクラス名を直接指定する ・暗示的(暗黙的)インテント 相手のプログラムにさせたいこと(アクション)、そのときに必要なデータを指定すること で、システムが自動的にプログラムを指定する。暗黙的インテントで、アクティビティが インテントを受け取るためには、つぎの暗黙的なルーティング 3 つの条件をすべて満た している必要がある。 コンストラクターとしては、以下のようなものがある。 Intent(String action) Intent(String action, Uri uri) また、メソッドで設定するには、以下のものがある。 Intent setAction(String action) Intent setData(Uri data) Intent setDataAndType(Uri data, String type) Intent setType(String type) Intent putExtra(String name, 型 value) Intent putExtra(String name, 型[] value) 暗黙的なルーティング ・アクティビティは指定されたアクションをサポートする ・MIME タイプが指定されている場合、アクティビティはそれをサポートする ・アクティビティはインテントで指定されたカテゴリーをすべてサポートする インテントの起動は、Activity クラスの startActivity(インテント) を使う。また、結果を受け取りたい場合は、 startActivityForResult(インテント, リクエスト・コード) を使う。また、結果は、 onActivityResult(int requestCode, int resultCode, Intent data) をオーバーライドする。 呼び出された側のアクティビティでは、戻りコードは、 setResult(戻りコード, インテント); を使って設定する。 アクションとデータの例 ------------------- --------------------------- -------------------------------- アクション データ 動作 ------------------- --------------------------- -------------------------------- ACTION_VIEW http://アドレス ブラウザーで指定するURL content://contacts/people/ 内臓の電話帳を表示 geo:軽度,緯度 地図を表示 geo:0,0?q=住所 地図を表示 ACTION_CALL tel://電話番号 電話をかける ACTION_DIAL tel://電話番号 ダイヤル画面を表示 ACTION_EDIT URI URIで示されるアドレス長を編集 ACTION_WEB_SEARCH 検索文字列 ブラウザーを開き、Googleで検索 ------------------- --------------------------- -------------------------------- Intents and Intent Filters http://developer.android.com/intl/ja/guide/topics/intents/intents-filters.html ソフトウェア技術ドキュメントを勝手に翻訳 Android 開発ガイド > フレームワークトピック > 4. インテントとインテントフィルタ https://sites.google.com/a/techdoctranslator.com/jp/android/guide/intents-filters ■ 呼び出す側 同じアプリケーション内で、画面を切り替えるサンプル。 画面はアクティビティ・オブジェクトなので、ある画面から別の画面に切り替えるのに、 このインテントを使って行う。 ▲ アクティビティ テキスト・フィールドから取得した文字列を、つぎの画面に渡す。 このとき、つぎの画面の起動方法として、明示的にインテントを指定する方法と、暗黙的 にインテントを指定する 2 つの方法を使っている。 □ Intent01Activity.java --- package jp.marunomaruno.android.intent; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.EditText; public class Intent01Activity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } /** * 明示的にインテントを起動する。 * * @param view */ public void onClickExplisitButton(View view) { EditText edit1 = (EditText) findViewById(R.id.editText1); Intent intent = new Intent(this, OtherActivity.class); // (1) intent.putExtra("message", edit1.getText()); // (2) startActivity(intent); // (3) } /** * 暗黙的にインテントを起動する。 * * @param view */ public void onClickImplisitButton(View view) { EditText edit1 = (EditText) findViewById(R.id.editText1); Intent intent = new Intent(Intent.ACTION_SEND); // (4) intent.putExtra("message", edit1.getText()); startActivity(intent); } } --- (1) 明示的にインテント・オブジェクトを生成する コンテキストとクラスを明示的に指定してインテント・オブジェクトを生成する。 Intent intent = new Intent(this, OtherActivity.class); // (1) 明示的にインテント・オブジェクトを生成するコンストラクター --- Intent(Context packageContext, Class<?> cls) --- または、空のインテント・オブジェクトを作って、つぎのメソッドでクラスを設定する。 --- Intent setClass(Context packageContext, Class<?> cls) Intent setClassName(Context packageContext, String className) Intent setClassName(String packageName, String className) --- 自分のアプリケーションでないものなどは、3 番目のメソッドを利用して指定することも できる。たとえば、ブラウザーなどはつぎのように指定することができる。 setClassName("com.android.browser", "com.android.browser.BrowserActivity") (2) 渡すデータを設定する Uri オブジェクト以外のデータは、つぎのように、putExtra() メソッドを利用して、つ ぎのアクティビティに渡すことができる。 putExtra() の第 1 引数には、渡すデータを意味する文字列。 intent.putExtra("message", edit1.getText()); // (2) データの取得側では、この "message" をキーとして、データを取得する。 なお、汎用のキーとして、Intent クラスの定数に、EXTRA_xxx という形でキーが用意さ れているので、それを使うこともできる。 ・Extra データ設定関係のメソッド(スカラーのもののみ) --- Intent putExtra(String name, boolean value) Intent putExtra(String name, byte value) Intent putExtra(String name, double value) Intent putExtra(String name, char value) Intent putExtra(String name, int value) Intent putExtra(String name, float value) Intent putExtra(String name, long value) Intent putExtra(String name, short value) Intent putExtra(String name, CharSequence value) Intent putExtra(String name, String value) Intent putExtra(String name, Serializable value) --- (3) アクティビティを起動する startActivity() メソッドにより、つぎのアクティビティを起動する。 startActivity(intent); // (3) なお、指定されたアクティビティがない場合、 android.content.ActivityNotFoundException がスローされる。 (4) 暗黙的にインテント・オブジェクトを生成する 何をするべきものなのかというアクションを指定して、インテント・オブジェクトを生成 する。 Intent intent = new Intent(Intent.ACTION_SEND); // (4) 暗黙的にインテント・オブジェクトを生成するコンストラクター --- Intent(String action) Intent(String action, Uri uri) --- ▲ レイアウト 明示的と暗黙的にインテントを起動するボタン。 □ 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" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" /> <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" > <requestFocus /> </EditText> <Button android:id="@+id/explisitButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClickExplisitButton" android:text="@string/explicitButtonLabel" /> <Button android:id="@+id/implisitButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClickImplisitButton" android:text="@string/implicitButtonLabel" /> </LinearLayout> --- ■ 呼び出される側 ▲ 呼び出されるアクティビティのクラス これは、単に渡されたデータをテキスト・ビューに設定して表示するだけのプログラム。 □ OtherActivity.java --- package jp.marunomaruno.android.intent; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; public class OtherActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); Intent intent = getIntent(); // (1) TextView text1 = (TextView) findViewById(R.id.otherTextView1); text1.setText(intent.getCharSequenceExtra("message").toString()); // (2) } } --- (1) インテントを取得する Intent intent = getIntent(); // (1) (2) データを取得する putExtra(String, CharSequence) で設定したデータは、getCharSequenceExtra(String) で取得する。 text1.setText(intent.getCharSequenceExtra("message").toString()); // (2) ・Extra データ設定関係のメソッド(スカラーのもののみ) --- boolean getBooleanExtra(String name, boolean defaultValue) byte getByteExtra(String name, byte defaultValue) char getCharExtra(String name, char defaultValue) double getDoubleExtra(String name, double defaultValue) float getFloatExtra(String name, float defaultValue) int getIntExtra(String name, int defaultValue) long getLongExtra(String name, long defaultValue) short getShortExtra(String name, short defaultValue) CharSequence getCharSequenceExtra(String name) String getStringExtra(String name) Serializable getSerializableExtra(String name) --- ▲ レイアウト main のアクティビティから受け取った文字列を表示するだけのレイアウト。 □ res/layout/other.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/otherTextView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> --- ■ Intent クラス java.lang.Object + android.content.Intent プログラムの実行に関する情報を管理するメッセージのクラス。 ・アクティビティ関係の標準アクション --- ACTION_MAIN メインプログラムの起動 ACTION_VIEW ユーザーデータの表示 ACTION_ATTACH_DATA 添付データがついた ACTION_EDIT データの編集 ACTION_PICK データからの取り出し ACTION_CHOOSER チューザーの表示 ACTION_GET_CONTENT コンテントの取得 ACTION_DIAL データをもとにダイアルする ACTION_CALL 電話をかける ACTION_SEND データの送信 ACTION_SENDTO メッセージの送信 ACTION_ANSWER 電話がかかってきた ACTION_INSERT 指定のコンテナにデータを追加 ACTION_DELETE データの削除 ACTION_RUN データの実行 ACTION_SYNC 同期の開始 ACTION_PICK_ACTIVITY アクティビティの選択 ACTION_SEARCH 検索 ACTION_WEB_SEARCH Web 検索 ACTION_FACTORY_TEST ファクトリーテスト用 --- ・ブロードキャストの標準アクション --- ACTION_TIME_TICK 現在の時刻が変更された ACTION_TIME_CHANGED 時間が変更された ACTION_TIMEZONE_CHANGED タイムゾーンが変更された ACTION_BOOT_COMPLETED 起動の完了 ACTION_PACKAGE_ADDED パッケージの追加 ACTION_PACKAGE_CHANGED パッケージの変更 ACTION_PACKAGE_REMOVED パッケージの削除 ACTION_PACKAGE_RESTARTED パッケージのリストア ACTION_PACKAGE_DATA_CLEARED パッケージ・データの初期化 ACTION_UID_REMOVED ユーザーID の削除 ACTION_BATTERY_CHANGED バッテリー状況の変更 ACTION_POWER_CONNECTED 電源接続 ACTION_POWER_DISCONNECTED バッテリー起動への切替 ACTION_SHUTDOWN シャットダウン --- ・主なカテゴリー --- CATEGORY_DEFAULT 標準カテゴリ CATEGORY_BROWSABLE ブラウザから安全に起動することが可能 CATEGORY_TAB TabActivity 内のタブ CATEGORY_LAUNCHER ホーム画面のアイコンから起動可能 CATEGORY_INFO パッケージ情報が提供されている CATEGORY_HOME ホームスクリーンを表示する CATEGORY_PREFERENCE プリファレンスパネルがターゲット CATEGORY_TEST テストとして使用 --- ・拡張データ --- EXTRA_ALARM_COUNT EXTRA_BCC EXTRA_CC EXTRA_CHANGED_COMPONENT_NAME EXTRA_DATA_REMOVED EXTRA_DOCK_STATE EXTRA_DOCK_STATE_HE_DESK EXTRA_DOCK_STATE_LE_DESK EXTRA_DOCK_STATE_CAR EXTRA_DOCK_STATE_DESK EXTRA_DOCK_STATE_UNDOCKED EXTRA_DONT_KILL_APP EXTRA_EMAIL EXTRA_INITIAL_INTENTS EXTRA_INTENT EXTRA_KEY_EVENT EXTRA_PHONE_NUMBER EXTRA_REMOTE_INTENT_TOKEN EXTRA_REPLACING EXTRA_SHORTCUT_ICON EXTRA_SHORTCUT_ICON_RESOURCE EXTRA_SHORTCUT_INTENT EXTRA_STREAM EXTRA_SHORTCUT_NAME EXTRA_SUBJECT EXTRA_TEMPLATE EXTRA_TEXT EXTRA_TITLE EXTRA_UID --- ・フラグ --- FLAG_ACTIVITY_BROUGHT_TO_FRONT FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TOP FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS FLAG_ACTIVITY_FORWARD_RESULT FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY FLAG_ACTIVITY_MULTIPLE_TASK FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NO_ANIMATION FLAG_ACTIVITY_NO_HISTORY FLAG_ACTIVITY_NO_USER_ACTION FLAG_ACTIVITY_PREVIOUS_IS_TOP FLAG_ACTIVITY_REORDER_TO_FRONT FLAG_ACTIVITY_RESET_TASK_IF_NEEDED FLAG_ACTIVITY_SINGLE_TOP FLAG_ACTIVITY_TASK_ON_HOME FLAG_DEBUG_LOG_RESOLUTION FLAG_EXCLUDE_STOPPED_PACKAGES FLAG_FROM_BACKGROUND FLAG_GRANT_READ_URI_PERMISSION FLAG_GRANT_WRITE_URI_PERMISSION FLAG_INCLUDE_STOPPED_PACKAGES FLAG_RECEIVER_REGISTERED_ONLY FLAG_RECEIVER_REPLACE_PENDING --- ・コンストラクタ- --- Intent() Intent(Intent o) Intent(String action) Intent(String action, Uri uri) Intent(Context packageContext, Class<?> cls) Intent(String action, Uri uri, Context packageContext, Class<?> cls) --- ・主なメソッド --- Intent addCategory(String category) Intent addFlags(int flags) boolean filterEquals(Intent other) int filterHashCode() String getAction() Set<String> getCategories() ComponentName getComponent() Uri getData() String getDataString() int getFlags() static Intent getIntent(String uri) static Intent getIntentOld(String uri) String getPackage() String getScheme() Intent getSelector() Rect getSourceBounds() String getType() boolean hasCategory(String category) boolean hasFileDescriptors() void removeCategory(String category) void removeExtra(String name) Intent setAction(String action) Intent setClass(Context packageContext, Class<?> cls) Intent setClassName(Context packageContext, String className) Intent setClassName(String packageName, String className) Intent setComponent(ComponentName component) Intent setData(Uri data) Intent setDataAndType(Uri data, String type) Intent setFlags(int flags) Intent setPackage(String packageName) Intent setType(String type) String toUri(int flags) --- ・Extra 関係のメソッド --- xxx[] getXxxArrayExtra(String name) xxx getXxxExtra(String name, xxx defaultValue) xxx: boolean, byte, char, double, float, int, long, short ArrayList<Integer> getIntegerArrayListExtra(String name) Yyy[] getYyyArrayExtra(String name) ArrayList<Yyy> getYyyArrayListExtra(String name) Yyy getYyyExtra(String name) Yyy: CharSequence, String Parcelable[] getParcelableArrayExtra(String name) <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) <T extends Parcelable> T getParcelableExtra(String name) Serializable getSerializableExtra(String name) Bundle getBundleExtra(String name) Bundle getExtras() boolean hasExtra(String name) Intent putExtra(String name, xxx[] value) Intent putExtra(String name, xxx value) xxx: boolean, byte, char, double, float, int, long, short Intent putExtra(String name, Yyy value) Intent putExtra(String name, Yyy[] value) Intent putYyyArrayListExtra(String name, ArrayList<Yyy> value) Yyy: CharSequence, String, Parcelable Intent putExtra(String name, Bundle value) Intent putExtra(String name, Serializable value) Intent putExtras(Intent src) Intent putExtras(Bundle extras) Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) Intent replaceExtras(Bundle extras) Intent replaceExtras(Intent src) --- ■ マニュフェスト マニフェストには、2 つのアクティビティ要素が記される。 □ AndroidManifest.xml --- <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="jp.marunomaruno.android.intent" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".Intent01Activity" android:label="@string/app_name" > <!-- (1) --> <intent-filter> <!-- (2) --> <action android:name="android.intent.action.MAIN" /> <!-- (3) --> <category android:name="android.intent.category.LAUNCHER" /> <!-- (4) --> </intent-filter> </activity> <activity android:name=".OtherActivity" android:label="other activity" > <intent-filter> <action android:name="android.intent.action.SEND" /> <!-- (5) --> <category android:name="android.intent.category.DEFAULT" /> <!-- (6) --> </intent-filter> </activity> </application> </manifest> --- (1) アクティビティ <activity android:name=".Intent01Activity" android:label="@string/app_name" > <!-- (1) --> (2) インテント・フィルター このクラスがサポートするアクションやカテゴリーについて指定する。 <intent-filter> <!-- (2) --> この要素の子要素として、つぎの要素が指定できる。 action category data (3)(5) アクション Intent01Activity のアクションを「メインプログラムの起動」にする。これは、アプリ ケーションが最初に表示するアクティビティを意味する。 <action android:name="android.intent.action.MAIN" /> <!-- (3) --> OtherActivity のアクションを「データの送信」にする。 <action android:name="android.intent.action.SEND" /> <!-- (5) --> 指定できるアクションについては、上記の Intent クラスの定数を参考。 定数 ACTION_xxx の xxx 部分が android.intent.action.XXX になる。 (4)(6) カテゴリー Intent01Activity のカテゴリーを「ランチャー」にする。これは、このアクティビティ をランチャーで選択できるようにする。 <category android:name="android.intent.category.LAUNCHER" /> <!-- (4) --> OtherActivity のカテゴリーを「デフォルト」にする。 <category android:name="android.intent.category.DEFAULT" /> <!-- (6) --> 指定できるカテゴリーについては、上記の Intent クラスの定数を参考。 定数 CATEGORY_xxx の xxx 部分が android.intent.category.XXX になる。 ■ リソース □ res/values/strings.xml --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Intent01</string> <string name="explicitButtonLabel">明示的にインテントを起動</string> <string name="implicitButtonLabel">暗黙的にインテントを起動</string> </resources> --- 以上
スッキリわかるJava入門
中山 清喬 (著), 国本 大悟 (著)
http://www.impressjapan.jp/support/aftercare/3086
¥2,730(本体 ¥2,600+税)
単行本(ソフトカバー): 640ページ
出版社: インプレスジャパン (2011/10/7)
言語 日本語
ISBN-10: 4844330861
ISBN-13: 978-4844330868
発売日: 2011/10/7
商品の寸法: 20.8 x 15 x 4.2 cm
第1章 Javaをはじめよう
ようこそJavaの世界へ
Java開発の基礎知識
Javaプログラムの基本構造
第2章 式と演算子
演算子、型の変換
命令実行の文
第3章 条件分岐と繰り返し
条件式の書き方、分岐構文のバリエーション
繰り返し構文のバリエーション
第4章 配列
配列の書き方
多次元の配列
第5章 メソッド
メソッドとは
引数と戻り値の利用
オーバーロード
付録A JDKのインストール
第6章 複数クラスを用いた開発
複数クラスで構成されるプログラム
パッケージに属したクラスの実行方法
第7章 オブジェクト指向をはじめよう
オブジェクト指向を学ぶ理由
オブジェクト指向の全体像と本質
第8章 インスタンスとクラス
クラス定義による効果
インスタンスの利用方法
第9章 さまざまなクラス機構
クラス型と参照
コンストラクタ
静的メンバ
第10章 カプセル化
カプセル化の目的とメリット
第11章 継承
継承の基礎
継承とコンストラクタ
第12章 高度な継承
抽象クラス
インタフェース
第13章 多態性
多態性とは
多態性のメリット
第14章 Javaを支える標準クラス
第15章 例外
エラーの種類と対応策
第16章 まだまだ広がるJavaの世界
付録B エラー解決・虎の巻
付録C JDKバージョンによる違い
中山 清喬 (著), 国本 大悟 (著)
http://www.impressjapan.jp/support/aftercare/3086
¥2,730(本体 ¥2,600+税)
単行本(ソフトカバー): 640ページ
出版社: インプレスジャパン (2011/10/7)
言語 日本語
ISBN-10: 4844330861
ISBN-13: 978-4844330868
発売日: 2011/10/7
商品の寸法: 20.8 x 15 x 4.2 cm
第1章 Javaをはじめよう
ようこそJavaの世界へ
Java開発の基礎知識
Javaプログラムの基本構造
第2章 式と演算子
演算子、型の変換
命令実行の文
第3章 条件分岐と繰り返し
条件式の書き方、分岐構文のバリエーション
繰り返し構文のバリエーション
第4章 配列
配列の書き方
多次元の配列
第5章 メソッド
メソッドとは
引数と戻り値の利用
オーバーロード
付録A JDKのインストール
第6章 複数クラスを用いた開発
複数クラスで構成されるプログラム
パッケージに属したクラスの実行方法
第7章 オブジェクト指向をはじめよう
オブジェクト指向を学ぶ理由
オブジェクト指向の全体像と本質
第8章 インスタンスとクラス
クラス定義による効果
インスタンスの利用方法
第9章 さまざまなクラス機構
クラス型と参照
コンストラクタ
静的メンバ
第10章 カプセル化
カプセル化の目的とメリット
第11章 継承
継承の基礎
継承とコンストラクタ
第12章 高度な継承
抽象クラス
インタフェース
第13章 多態性
多態性とは
多態性のメリット
第14章 Javaを支える標準クラス
第15章 例外
エラーの種類と対応策
第16章 まだまだ広がるJavaの世界
付録B エラー解決・虎の巻
付録C JDKバージョンによる違い
[Android] オプション・メニューとコンテキスト・メニュー ================================================================================ オプション・メニューは、実機によっては、画面とは別にある「メニュー」ボタン押下に よって表示されるコンポーネント。タブレットなどでは、画面上に「メニュー」ボタンが あったりする。 コンテキスト・メニューは、ビューの部品(たとえば、TextView など)を長押しすること で、そのコンポーネント上に表示されるメニューである。 メニューは、その項目数が 6 つ以内のときはグリッド表示され、7 つ以上になったとき は 6 つ目のメニュー項目が「その他」になり、それをクリックすることで、残りのメニ ューが表示される。 つぎの Activity クラスのメソッドをオーバーライドすることで、オプション・メニュー を設定する。 public boolean onCreateOptionsMenu(Menu menu) オプション・メニュー生成時のハンドラー public boolean onMenuOpened(int featureId, Menu menu) オプション・メニューを開いたときのハンドラー public void onOptionsMenuClosed(Menu menu) オプション・メニューを閉じたときのハンドラー public boolean onOptionsItemSelected(MenuItem item) オプション・メニューの項目選択時のハンドラー つぎの Activity クラスのメソッドをオーバーライドすることで、コンテキスト・メニ ューを設定する。 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) コンテキスト・メニュー生成時のハンドラー public void onContextMenuClosed(Menu menu) コンテキスト・メニューを閉じたときのハンドラー public boolean onContextItemSelected(MenuItem item) コンテキスト・メニューの項目選択時のハンドラー なお、コンテキスト(ビュー)とこのコンテキスト・メニューとを紐づけるのは、Activity. registerForContextMenu() メソッドによる。 また、オプション・メニュー、コンテキスト・メニュー共通で、その項目選択時のハンド ラーとして、次のメソッドがある。 public boolean onMenuItemSelected(int featureId, MenuItem item) ▲ アクティビティ 上記のメソッドをオーバーライドして、その動きを確認している。 □ Menu01Activity.java --- package jp.marunomaruno.android.menu; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.TextView; import android.widget.Toast; import jp.marunomaruno.android.menu.R; public class Menu01Activity extends Activity { private static final int TOAST_DURATION = Toast.LENGTH_SHORT; private Context context; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); context = this; // コンテキスト・メニューの設定 TextView text1 = (TextView) findViewById(R.id.text1); registerForContextMenu(text1); // (1) } @Override public boolean onCreateOptionsMenu(Menu menu) { // (2) super.onCreateOptionsMenu(menu); // (3) MenuItem item1 = menu.add("アイスクリーム"); // (4) MenuItem item2 = menu.add("あられ"); SubMenu sub3 = menu.addSubMenu("あずき ..."); // (5) sub3.add("つぶあん"); // (6) sub3.add("こしあん"); return true; // (7) } @Override public boolean onMenuOpened(int featureId, Menu menu) { // (8) String message = String.format( "onMenuOpened(): featureId: %d, menu: ¥"%s¥"", featureId, menu); Toast.makeText(context, message, TOAST_DURATION).show(); System.out.println(message); return super.onMenuOpened(featureId, menu); } @Override public void onOptionsMenuClosed(Menu menu) { // (9) String message = String.format("onOptionsMenuClosed(): menu: ¥"%s¥"", menu); Toast.makeText(context, message, TOAST_DURATION).show(); System.out.println(message); super.onOptionsMenuClosed(menu); } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { // (10) String message = String.format( "onMenuItemSelected(): featureId: %d, item: ¥"%s¥"", featureId, item); Toast.makeText(context, message, TOAST_DURATION).show(); System.out.println(message); return super.onMenuItemSelected(featureId, item); } @Override public boolean onOptionsItemSelected(MenuItem item) { // (11) String message = String.format("onOptionsItemSelected(): item: ¥"%s¥"", item); Toast.makeText(context, message, TOAST_DURATION).show(); System.out.println(message); return super.onOptionsItemSelected(item); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // (12) menu.setHeaderTitle("Context menu"); // (13) MenuItem item1 = menu.add("Apple"); MenuItem item2 = menu.add("Banana"); SubMenu sub3 = menu.addSubMenu("Chocolate ..."); sub3.add("Black"); sub3.add("White"); } @Override public void onContextMenuClosed(Menu menu) { // (14) String message = String.format("onContextMenuClosed(): menu: ¥"%s¥"", menu); Toast.makeText(context, message, TOAST_DURATION).show(); System.out.println(message); super.onContextMenuClosed(menu); } @Override public boolean onContextItemSelected(MenuItem item) { // (15) String message = String.format("onContextItemSelected(): item: ¥"%s¥"", item); Toast.makeText(context, message, TOAST_DURATION).show(); System.out.println(message); return super.onContextItemSelected(item); } } --- (1) ビューのコンポーネントにコンテキスト・メニューを登録する テキスト・ビューに対し、コンテキスト・メニューを登録する。 registerForContextMenu(text1); // (1) ・Activity クラスのメソッド --- void registerForContextMenu(View view) --- (2)(3)(7) オプション・メニューを生成したときの処理 アプリケーション起動時に、オプション・メニューは生成される。 public boolean onCreateOptionsMenu(Menu menu) { // (2) onCreateOptionsMenu() の先頭で、スーパークラスのメソッドを実行する。 super.onCreateOptionsMenu(menu); // (3) メニューが完成したので、true を返す。 return true; // (7) (4) オプション・メニューに項目を追加する onCreateOptionsMenu() メソッドの引数で、Menu オブジェクトが渡ってくるので、これ に対し、add() メソッドを使って、メニューの項目を追加する。 MenuItem item1 = menu.add("アイスクリーム"); // (4) ・Menu に項目を追加する主なメソッド(すべて abstract なので、その記述を省略) --- MenuItem add(CharSequence title) MenuItem add(int groupId, int itemId, int order, int titleRes) MenuItem add(int titleRes) MenuItem add(int groupId, int itemId, int order, CharSequence title) --- groupId 通常は NONE でよい(グループ化するための項目) itemId 項目 ID order メニュー項目を追加する位置(通常は NONE) title, titleRes メニュー項目のテキストの文字列またはリソース ID --- (5)(6) オプション・メニューにサブ・メニューを追加する サブ・メニューを追加するには、addSubMenu() メソッドを使う。この返り値は SubMenu クラスになる。 SubMenu sub3 = menu.addSubMenu("あずき ..."); // (5) ・サブ・メニューを追加するメソッド(すべて abstract なので、その記述を省略) --- SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) SubMenu addSubMenu(CharSequence title) SubMenu addSubMenu(int titleRes) --- addSubMenu() メソッドで作ったサブ・メニューに、add() メソッドを使って項目を追加す る。 sub3.add("つぶあん"); // (6) ・サブ・メニューに項目を追加するメソッド(すべて abstract なので、その記述を省略、 メニューに項目を追加するメソッドと同じ) --- MenuItem add(CharSequence title) MenuItem add(int groupId, int itemId, int order, int titleRes) MenuItem add(int titleRes) MenuItem add(int groupId, int itemId, int order, CharSequence title) --- (8) オプション・メニューを開いたときの処理 onCreateOptionsMenu() メソッドは、アプリケーション起動時に実行されるだけなので、 オプション・メニューが開かれるたびに呼ばれるメソッドがある。 public boolean onMenuOpened(int featureId, Menu menu) { // (8) (9) オプション・メニューを閉じたときの処理 public void onOptionsMenuClosed(Menu menu) { // (9) (10) メニューの項目を選択したときの処理 このメソッドは、オプション・メニュー、コンテキスト・メニューで共通で使える。 まず、このメソッドが動き、その後、オプション・メニューのときは onOptionsItemSelected() メソッドが、コンテキスト・メニューのときは onContextItemSelected() メソッドが動く。 引数の item が選択したメニュー項目になる。 public boolean onMenuItemSelected(int featureId, MenuItem item) { // (10) featureId は、メニューのパネルの ID。 メニュー項目の情報は、以下のメソッドを使って取得する。 ・取得関係の主なメソッド(すべて abstract なので、その記述を省略) --- int getItemId() int getOrder() SubMenu getSubMenu() CharSequence getTitle() CharSequence getTitleCondensed() --- (11) オプション・メニューの項目を選択したときの処理 public boolean onOptionsItemSelected(MenuItem item) { // (11) MenuItem オブジェクトは、オプション・メニュー項目でも、サブ・メニュー項目でも、コ ンテキスト・メニュー項目でも同じである。 (12) コンテキスト・メニューを生成したときの処理 オプション・メニューと違い、コンテキスト・メニューを開くたびにこのメソッドが呼ばれ る。 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // (12) (13) コンテキスト・メニューのタイトルを設定する menu.setHeaderTitle("Context menu"); // (13) (14) コンテキスト・メニューを閉じたときの処理 public void onContextMenuClosed(Menu menu) { // (14) (15) コンテキスト・メニューの項目を選択したときの処理 public boolean onContextItemSelected(MenuItem item) { // (15) △ Menu インターフェース android.view.Menu オプション・メニュー、コンテキスト・メニューで使うインターフェース。 ・主なメソッド(すべて abstract なので、その記述を省略) --- MenuItem add(CharSequence title) MenuItem add(int groupId, int itemId, int order, int titleRes) MenuItem add(int titleRes) MenuItem add(int groupId, int itemId, int order, CharSequence title) SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) SubMenu addSubMenu(CharSequence title) SubMenu addSubMenu(int titleRes) void clear() void close() MenuItem findItem(int id) MenuItem getItem(int index) boolean hasVisibleItems() void removeItem(int id) int size() --- △ SubMenu インターフェース android.view.SubMenu サブメニュー用のインターフェース。サブメニューは、末端のメニューで、この下はメニ ュー項目しか追加できない。 ・主なメソッド(すべて abstract なので、その記述を省略) --- void clearHeader() MenuItem getItem() SubMenu setHeaderIcon(Drawable icon) SubMenu setHeaderIcon(int iconRes) SubMenu setHeaderTitle(CharSequence title) SubMenu setHeaderTitle(int titleRes) SubMenu setHeaderView(View view) SubMenu setIcon(Drawable icon) SubMenu setIcon(int iconRes) --- △ MenuItem インターフェース android.view.MenuItem メニュー項目のインターフェース。 ・主なメソッド(すべて abstract なので、その記述を省略) --- int getItemId() ContextMenu.ContextMenuInfo getMenuInfo() int getOrder() SubMenu getSubMenu() CharSequence getTitle() CharSequence getTitleCondensed() boolean hasSubMenu() boolean isCheckable() boolean isChecked() boolean isEnabled() boolean isVisible() MenuItem setCheckable(boolean checkable) MenuItem setChecked(boolean checked) MenuItem setEnabled(boolean enabled) MenuItem setIcon(Drawable icon) MenuItem setIcon(int iconRes) MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener menuItemClickListener) MenuItem setTitle(CharSequence title) MenuItem setTitle(int title) MenuItem setTitleCondensed(CharSequence title) MenuItem setVisible(boolean visible) --- △ ContextMenu インターフェース android.view.ContextMenu コンテキスト・メニューを使うためには、つぎの手順が必要。 ・ロング・クリックするクライアント・オブジェクトに対して registerForContextMenu(View) を行う。 そして、つぎのメソッドをオーバーライドして、メニュー項目を追加する。 onCreateContextMenu(ContextMenu, View, ContextMenu.ContextMenuInfo) ・主なメソッド(すべて abstract なので、その記述を省略) --- void clearHeader() ContextMenu setHeaderIcon(Drawable icon) ContextMenu setHeaderIcon(int iconRes) ContextMenu setHeaderTitle(CharSequence title) ContextMenu setHeaderTitle(int titleRes) ContextMenu setHeaderView(View view) --- △ ContextMenuInfo インターフェース android.view.ContextMenu.ContextMenuInfo AdapterView などで使うマーカー・インターフェース。 メソッドなどは持っていない。 ▲ レイアウト コンテキスト・メニューを表示するための TextView を定義。 □ 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" android:background="#CCCC00" android:hint="@string/hint" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> --- ▲ リソース □ res/values/strings.xml --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hint">ここを長押しするとコンテキストメニューが出る</string> <string name="app_name">Menu01</string> </resources> --- ▲ ログ メニュー関係のハンドラーの動きを確認。 --- ○ アプリケーション起動時 onCreateOptionsMenu(): menu: "MenuBuilder@46c02638" ○ オプション・メニュー選択時 onMenuOpened(): featureId: 0, menu: "MenuBuilder@46c02638" onMenuItemSelected(): featureId: 0, item: "アイスクリーム" onOptionsItemSelected(): item: "アイスクリーム" onOptionsMenuClosed(): menu: "MenuBuilder@46c02638" ○ オプション・メニューで、サブ・メニュー選択時 onMenuOpened(): featureId: 0, menu: "MenuBuilder@46c02638" onMenuItemSelected(): featureId: 0, item: "あずき ..." onOptionsItemSelected(): item: "あずき ..." onMenuItemSelected(): featureId: 0, item: "つぶあん" onOptionsItemSelected(): item: "つぶあん" ○ コンテキスト・メニュー選択時 onCreateContextMenu(): menu: "ContextMenuBuilder@46c2f3d0" onMenuItemSelected(): featureId: 6, item: "Banana" onContextItemSelected(): item: "Banana" onContextMenuClosed(): menu: "ContextMenuBuilder@46c2f3d0" ○ コンテキスト・メニューで、サブ・メニュー選択時 onCreateContextMenu(): menu: "ContextMenuBuilder@46c43598" onMenuItemSelected(): featureId: 6, item: "Chocolate ..." onContextItemSelected(): item: "Chocolate ..." onMenuItemSelected(): featureId: 6, item: "White" onContextItemSelected(): item: "White" onContextMenuClosed(): menu: "SubMenuBuilder@46c44618" --- ※パッケージ名 "com.android.internal.view.menu." の部分は表示から割愛 以上
Eclipseで学ぶはじめてのJava 第2版(DVD付) [大型本]
木村 聡 (著)
http://www.sbcr.jp/products/4797359039.html
大型本: 472ページ
出版社: ソフトバンククリエイティブ; 第2版 (2010/4/30)
ISBN-10: 479735903X
ISBN-13: 978-4797359039
発売日: 2010/4/30
商品の寸法: 23 x 18.4 x 3 cm
SECTION 1 基礎編
第1章 プログラムについて
第2章 まずは、実行してみる
第3章 Eclipseを使う
第4章 いろいろ表示してみる
●SECTION 2 文法編
第5章 計算してみる
第6章 もし~だったら
第7章 まとまりを持ったデータを扱う
第8章 同じ処理を繰り返す
第9章 これまでのコードを改善する
第10章 クラスを利用する
第11章 コメントとコーディング規約
●SECTION 3 発展編
第12章 オブジェクト指向
第13章 クラスを拡張する
第14章 抽象クラス
第15章 インターフェース
第16章 クラスライブラリを使う
第17章 例外
第18章 アノテーション
第19章 テスト
第20章 デバッグ
付録A プログラミングの準備・セットアップ
付録B クイズの解答
付録C その他の情報
木村 聡 (著)
http://www.sbcr.jp/products/4797359039.html
大型本: 472ページ
出版社: ソフトバンククリエイティブ; 第2版 (2010/4/30)
ISBN-10: 479735903X
ISBN-13: 978-4797359039
発売日: 2010/4/30
商品の寸法: 23 x 18.4 x 3 cm
SECTION 1 基礎編
第1章 プログラムについて
第2章 まずは、実行してみる
第3章 Eclipseを使う
第4章 いろいろ表示してみる
●SECTION 2 文法編
第5章 計算してみる
第6章 もし~だったら
第7章 まとまりを持ったデータを扱う
第8章 同じ処理を繰り返す
第9章 これまでのコードを改善する
第10章 クラスを利用する
第11章 コメントとコーディング規約
●SECTION 3 発展編
第12章 オブジェクト指向
第13章 クラスを拡張する
第14章 抽象クラス
第15章 インターフェース
第16章 クラスライブラリを使う
第17章 例外
第18章 アノテーション
第19章 テスト
第20章 デバッグ
付録A プログラミングの準備・セットアップ
付録B クイズの解答
付録C その他の情報
2012-03-09 更新 2012-03-03 新規 [Android] 標準ウィジェット(1) EditText ================================================================================ Android で文字列データを入力するには、EditText を使う。 この EditText には、いろいろな入力形式が用意されている。 数字だけに限定することもできれば、email で使う文字だけに限定する、また、パスワー ドの入力に使う、ということも可能。 入力した文字列は Editable getText() メソッドを使うが、返り値は Editable 型。通常は toString() メソッドを使って、テキ ストにして使う。 レイアウトの EditText 要素の android:inputType 属性を使ってこれらを制御する。 ------------------- ------------------------------------------------------------ android:inputType 属性 ------------------- ------------------------------------------------------------ 指定値 動作 none 入力不可になります。 text 文字 textCapCharacters すべて大文字 textCapWords 単語の先頭を大文字 textCapSentences 文章の先頭を大文字 textAutoCorrect 文字のスペルミスを自動で修正する textAutoComplete 文字の補完入力する textMultiLine 文字を複数行入力する textImeMultiLine 通常の文字入力時は複数行入力を許可せず、 IMEによって複数行入力を設定 textUri URL textEmailAddress メールアドレス textEmailSubject メールの件名 textShortMessage ショートメッセージ textLongMessage ロングメッセージ textPersonName 人名 textPostalAddress 住所 textPassword パスワード入力 textVisiblePassword パスワード入力(パスワードは表示) textWebEditText HTML textFilter 他のデータでフィルタされた文字 textPhonetic 発音表記 number 数値入力 numberSigned 符号付きの数値 numberDecimal 小数入力 phone 電話番号 datetime 日付時刻 date 日付 time 時刻 ------------------- ------------------------------------------------------------ 参考: Android Wiki* UIコンポーネント/TextView http://wikiwiki.jp/android/?UI%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8%2FTextView#inputType ▲ レイアウト 上記のうちのつぎの属性値を確認する。 textPassword textEmailAddress textMultiLine date number なお、 android:inputType 属性を指定していない場合もあわせて確認する。 □ 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" > <!-- (1) 通常のテキスト --> <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="文字列" > <requestFocus /> <!-- (7) --> </EditText> <!-- (2) パスワード --> <EditText android:id="@+id/password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="password" android:inputType="textPassword" /> <!-- (3) email アドレス --> <EditText android:id="@+id/emailAddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="email address" android:inputType="textEmailAddress" /> <!-- (4) 複数行 --> <EditText android:id="@+id/multilineText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Multiline text" android:inputType="textMultiLine" /> <!-- (5) 日付 --> <EditText android:id="@+id/date" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="date" android:inputType="date" /> <!-- (6) 数値 --> <EditText android:id="@+id/number" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="number" android:inputType="number" /> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClickHandler" android:text="@string/submit" /> <TextView android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> --- ▲ リソース □ res/values/strings.xml --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">TextField01</string> <string name="submit">クリック</string> </resources> --- ▲ アクティビティ □ TextField01Activity.java --- package jp.marunomaruno.android.textfield; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import jp.marunomaruno.android.textfield.R; public class TextField01Activity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void onClickHandler(View view) { EditText edit1 = (EditText) findViewById(R.id.editText1); EditText password = (EditText) findViewById(R.id.password); EditText emailAddress = (EditText) findViewById(R.id.emailAddress); EditText multilineText = (EditText) findViewById(R.id.multilineText); EditText date = (EditText) findViewById(R.id.date); EditText number = (EditText) findViewById(R.id.number); String text = String .format(" edit1=%s%n password=%s%n emailAddress=%s%n multilineText=%s%n date=%s%n number=%s%n", edit1.getText(), password.getText(), emailAddress .getText(), multilineText.getText(), date .getText(), number.getText()); Toast.makeText(this, text, Toast.LENGTH_LONG).show(); TextView text1 = (TextView) findViewById(R.id.text1); text1.setText(text); } } --- △ EditText クラス java.lang.Object + android.view.View + android.widget.TextView + android.widget.EditText ユーザーからの入力をサポートするためのクラス。 レイアウトでは、android:inputType 属性をつけることで、入力値を制限することができ る。 特徴としては、getText() メソッドの返り値の型が Editable 型である。 String 型として、入力した値を取得するには、この返り値のオブジェクトの toString() メソッドを使って取得する必要がある。 ・主なメソッド --- Editable getText() void setText(CharSequence text, TextView.BufferType type) void selectAll() void setEllipsize(TextUtils.TruncateAt ellipsis) void extendSelection(int index) void setSelection(int index) void setSelection(int start, int stop) void setFilters(InputFilter[] filters) final void setHint(CharSequence hint) final void setHint(int resid) void setKeyListener(KeyListener input) void setHorizontallyScrolling(boolean whether) void setHeight(int pixels) void setWidth(int pixels) --- △ Editable インターフェース android.text.Editable テキスト操作に関するインターフェース。 実際に使うためには、toString() メソッドで、テキストにしてから使う場合が多い。 ★疑問 --- EditText の getText() はなぜ Editable 型で返すんだろうか? スーパークラスの TextView は CharSequence なのに。CharSequence は、String でも StringBuilder でも いいので納得できるが。。 --- ■ EditView で、最初からソフトウェアキーボードを表示しておく方法 (2012-03-09 追記) レイアウトか Activity クラスで、目的の EditText にフォーカスを当てておく。 マニフェストの activity 要素で、android:windowSoftInputMode="stateVisible" 属性をつける。 □ レイアウト --- <EditText ... > <requestFocus /> <!-- <= これを指定 --> </EditText> --- □ Activity クラス --- EditText editText = new EditText(this); editText.requestFocus(); // <= フォーカスを当てる(XML での指定でもよい) --- □ AndroidManifest.xml activity 要素に android:windowSoftInputMode 属性を追加 --- <activity android:name=".XxxActivity" android:label="@string/app_name" android:windowSoftInputMode="stateVisible"> // <= これで表示される <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> --- 以上
[Java] UTC 時間と SimpleDateFormat の不思議 ================================================================================ UTC 時間を表示するときに、SimpleDateFormat を使って表示すると、JST 時間で表示さ れる。System.out.printf()で %tT とすると、ちゃん と UTC として表示される。なぜ? オブジェクトは、ただしく UTC として作られている。 □ UTCSample.java --- package jp.rutles.sample; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.TimeZone; public class UTCSample { public static void main(String[] args) { SimpleDateFormat fmt = new SimpleDateFormat( "yyyy 年 M 月 d 日 (E) HH:mm:ss"); Calendar today = Calendar.getInstance(); System.out.println(today); System.out.println(fmt.format(today.getTime())); System.out.printf("%1$tF %1$tT%n%n", today); TimeZone tz = TimeZone.getTimeZone("UTC"); Calendar utc = Calendar.getInstance(tz); System.out.println(utc); System.out.println(fmt.format(utc.getTime())); System.out.printf("%1$tF %1$tT%n%n", utc); } } /* 実行結果 java.util.GregorianCalendar[time=1330561100890,areFieldsSet=true,areAllFieldsSet =true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=324000 00,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayOfWeek=1, minimalDaysInFirstWeek=1,ERA=1,YEAR=2012,MONTH=2,WEEK_OF_YEAR=9,WEEK_OF_MONTH=1, DAY_OF_MONTH=1,DAY_OF_YEAR=61,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR= 9,HOUR_OF_DAY=9,MINUTE=18,SECOND=20,MILLISECOND=890,ZONE_OFFSET=32400000,DST_OFF SET=0] 2012 年 3 月 1 日 (木) 09:18:20 2012-03-01 09:18:20 java.util.GregorianCalendar[time=1330561100906,areFieldsSet=true,areAllFieldsSet =true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings= 0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInF irstWeek=1,ERA=1,YEAR=2012,MONTH=2,WEEK_OF_YEAR=9,WEEK_OF_MONTH=1,DAY_OF_MONTH=1, DAY_OF_YEAR=61,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0, MINUTE=18,SECOND=20,MILLISECOND=906,ZONE_OFFSET=0,DST_OFFSET=0] 2012 年 3 月 1 日 (木) 09:18:20 2012-03-01 00:18:20 */ --- 以上
[Android] フォームの標準ウィジェット(2) 静的な選択関連 - 数値の指定 ================================================================================ ※ 前回、記事サイズの関係で紹介できなかったシークバーとレーティングバーについて紹介する。 選択する以下の ウィジェット(Widget)とそのイベント処理。 ・ボタン(前回紹介) ・チェックボックス(前回紹介) ・トグルボタン(前回紹介) ・ラジオボタン(前回紹介) ・スピナー(前回紹介) ・シークバー ・レーティングバー 上記のウィジェットは、それぞれつぎのクラスを使う。また、そのときに使われるリス ナー・インターフェースも示す。 ------------------ -------------- ---------------------------------------------- ウィジェット クラス リスナー・インターフェース ------------------ -------------- ---------------------------------------------- ボタン Button View.OnClickListener, View.OnLongClickListener View.OnTouchListener チェックボックス CheckBox CompoundButton.OnCheckedChangeListener View.OnClickListener, View.OnLongClickListener View.OnTouchListener トグルボタン ToggleButton CompoundButton.OnCheckedChangeListener View.OnClickListener, View.OnLongClickListener View.OnTouchListener ラジオボタン RadioGroup RadioGroup.OnCheckedChangeListener RadioButton スピナー Spinner AdapterView.OnItemSelectedListener View.OnTouchListener シークバー SeekBar SeekBar.OnSeekBarChangeListener View.OnTouchListener レーティングバー RatingBar RatingBar.OnRatingBarChangeListener View.OnTouchListener ------------------ -------------- ---------------------------------------------- このサンプルは、アプリケーションの起動時に選択する値が決まっているパターンを示す。 ▲ レイアウト □ 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" > <!-- (7) シークバー --> <SeekBar android:id="@+id/seekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" android:progress="50" /> <!-- (8) レーティングバー --> <RatingBar android:id="@+id/ratingBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:rating="2.5" /> </LinearLayout> --- (7) シークバー シークバーは、バー(スライダー)を指でタッチして、伸ばしたり縮めたりして、数値を設 定するウィジェット。EditText と違い、一定の範囲内で数値を設定できる。 <SeekBar android:id="@+id/seekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" android:progress="50" /> android:max 最大値 android:progress 初期状態での設定値 (8) レーティングバー シークバーの一種で、5 段階評価のような感じの指定ができる。 <RatingBar android:id="@+id/ratingBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:rating="2.5" /> android:rating 初期状態での設定値 ▲リソース値 □ res/values/strings.xml ※ 前回と同じ ▲ アクティビティ 単に、Widget にあわせたリスナーを割り当てているだけである。 なお、リスナーはインナー・クラスを使っている。 どのハンドラーが使われたかは、トーストとログで表示している。 □ FormWidgets01Activity.java package jp.marunomarun.android.formwidgets; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.RatingBar; import android.widget.SeekBar; import android.widget.Spinner; import android.widget.Toast; import android.widget.ToggleButton; public class FormWidgets01Activity extends Activity { private static final int TOAST_DURATION = Toast.LENGTH_SHORT; private Context context; // (1) /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); context = this; // (2) OnCheckAndLongClickListener clickListener = new OnCheckAndLongClickListener(); OnTouchListener touchListener = new OnTouchListener(); // シークバー SeekBar seekBar1 = (SeekBar) findViewById(R.id.seekBar1); seekBar1.setOnSeekBarChangeListener(new OnSeekBarListener()); seekBar1.setOnClickListener(clickListener); // 動かないだけ seekBar1.setOnLongClickListener(clickListener); // 動かないだけ seekBar1.setOnTouchListener(touchListener); // レーティングバー RatingBar raitingBar1 = (RatingBar) findViewById(R.id.ratingBar1); raitingBar1.setOnRatingBarChangeListener(new OnRatingBarListener()); raitingBar1.setOnClickListener(clickListener); // 動かないだけ raitingBar1.setOnLongClickListener(clickListener); // 動かないだけ raitingBar1.setOnTouchListener(touchListener); } /** * ボタンのクリック、長クリックに対するリスナー * * @author marunomaruno */ private class OnCheckAndLongClickListener implements View.OnClickListener, View.OnLongClickListener { @Override public void onClick(View v) { String message = String.format( "OnClickListener.onClick() view: %s", v.getTag()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } @Override public boolean onLongClick(View v) { String message = String.format( "OnLongClickListener.onLongClick() view: %s", v.getTag()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); return false; } } /** * タッチに対するリスナー * * @author marunomaruno */ private class OnTouchListener implements View.OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { String message = String.format( "OnTouchListener.onTouch() view: %s, event: %s", v.getTag(), event); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); return false; } } /** * シークバーの変更に対するリスナー * * @author marunomaruno */ private class OnSeekBarListener implements SeekBar.OnSeekBarChangeListener { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { String message = String .format("OnSeekBarChangeListener.onProgressChanged() view: %s, value: %d, fromUser: %b", seekBar.getTag(), progress, fromUser); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } @Override public void onStartTrackingTouch(SeekBar seekBar) { String message = String .format("OnSeekBarChangeListener.onStartTrackingTouch() view: %s, value: %d", seekBar.getTag(), seekBar.getProgress()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } @Override public void onStopTrackingTouch(SeekBar seekBar) { String message = String .format("OnSeekBarChangeListener.onStopTrackingTouch() view: %s, value: %d", seekBar.getTag(), seekBar.getProgress()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } } /** * レーティング・バーの変更に対するリスナー * * @author marunomaruno */ private class OnRatingBarListener implements RatingBar.OnRatingBarChangeListener { @Override public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { String message = String.format( "RatingBar onRatingChanged() rate: %f, fromUser: %b", rating, fromUser); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } } } --- (1)(2) コンテキスト・オブジェクト 内部クラスでトーストを使っているので、このアクティビティ自身(this オブジェクト) を持っていたほうが都合がよい。 private Context context; // (1) context = this; // (2) (●) シークバー シークバーは、バー(スライダー)を指でタッチして、伸ばしたり縮めたりして、数値を設 定するウィジェット。EditText と違い、一定の範囲内で数値を設定できる。 SeekBar seekBar1 = (SeekBar) findViewById(R.id.seekBar1); seekBar1.setOnSeekBarChangeListener(new OnSeekBarListener()); seekBar1.setOnClickListener(clickListener); // 動かないだけ seekBar1.setOnLongClickListener(clickListener); // 動かないだけ seekBar1.setOnTouchListener(touchListener); なお、setOnClickListener()、setOnTouchListener() を指定しても動かない。 クリック時の動き まとめると、ACTION_DOWN > onStartTrackingTouch > onProgressChanged > ACTION_UP > onStopTrackingTouch --- OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c41208 action=0 ...} OnSeekBarChangeListener.onStartTrackingTouch() view: SeekBar, value: 50 OnSeekBarChangeListener.onProgressChanged() view: SeekBar, value: 86, fromUser: true OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c41208 action=1 ...} OnSeekBarChangeListener.onStopTrackingTouch() view: SeekBar, value: 86 --- 長押し時の動き まとめると、ACTION_DOWN > onStartTrackingTouch > ACTION_MOVE > onProgressChanged > ACTION_UP > onStopTrackingTouch --- OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=0 ...} OnSeekBarChangeListener.onStartTrackingTouch() view: SeekBar, value: 50 OnSeekBarChangeListener.onProgressChanged() view: SeekBar, value: 80, fromUser: true OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=2 ...} OnSeekBarChangeListener.onProgressChanged() view: SeekBar, value: 79, fromUser: true OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=2 ...} OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=1 ...} OnSeekBarChangeListener.onStopTrackingTouch() view: SeekBar, value: 79 --- △ SeekBar クラス java.lang.Object + android.view.View + android.widget.ProgressBar + android.widget.AbsSeekBar + android.widget.SeekBar シークバーを管理するクラス。 setMax() で最大値を指定しなければ、0 ~ 100 の範囲での指定になる。 ・メソッド --- void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener l) synchronized void setMax(int max) synchronized int getProgress() synchronized void setProgress(int progress) --- △ SeekBar.OnSeekBarChangeListener インターフェース android.widget.SeekBar.OnSeekBarChangeListener ・メソッド --- abstract void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) abstract void onStartTrackingTouch(SeekBar seekBar) abstract void onStopTrackingTouch(SeekBar seekBar) --- (●) レーティングバー シークバーの一種で、5 段階評価のような感じの指定ができる。 RatingBar raitingBar1 = (RatingBar) findViewById(R.id.ratingBar1); raitingBar1.setOnRatingBarChangeListener(new OnRatingBarListener()); raitingBar1.setOnClickListener(clickListener); // 動かないだけ raitingBar1.setOnLongClickListener(clickListener); // 動かないだけ raitingBar1.setOnTouchListener(touchListener); クック時の動き まとめると、ACTION_DOWN > ACTION_UP > onRatingChanged --- OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c41208 action=0 ...} OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fc70 action=1 ...} RatingBar onRatingChanged() rate: 5.000000, fromUser: true --- 長押し時の動き まとめると、ACTION_DOWN > ACTION_MOVE > ACTION_UP > onClick --- OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fb60 action=0 ...] OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fb60 action=2 ...} OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fb60 action=2 ...] OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c20bd0 action=1 ...] RatingBar onRatingChanged() rate: 1.000000, fromUser: true --- △ RatingBar クラス java.lang.Object + android.view.View + android.widget.ProgressBar + android.widget.AbsSeekBar + android.widget.RatingBar レーティング・バーを管理するクラス。 ・主なメソッド --- int getNumStars() float getRating() float getStepSize() boolean isIndicator() void setIsIndicator(boolean isIndicator) synchronized void setMax(int max) void setNumStars(int numStars) void setOnRatingBarChangeListener(RatingBar.OnRatingBarChangeListener listener) void setRating(float rating) void setStepSize(float stepSize) --- △ RatingBar.OnRatingBarChangeListener インターフェース android.widget.RatingBar.OnRatingBarChangeListener レーティング・バーが変化したときのリスナー・インターフェース。 ・メソッド --- abstract void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) --- 以上
[Android] フォームの標準ウィジェット(1) 静的な選択関連 ================================================================================ ウィジェットは、ホーム画面に追加される小さな機能。 Android では、標準で、いくつかのウィジェットを用意している。これらを使って、デー タを表示したり、入力したり、選択したりすることができる。 選択する以下の ウィジェット(Widget)とそのイベント処理。 ・ボタン ・チェックボックス ・トグルボタン ・ラジオボタン ・スピナー ・シークバー(別記) ・レーティングバー(別記) 上記のウィジェットは、それぞれつぎのクラスを使う。また、そのときに使われるリス ナー・インターフェースも示す。 ------------------ -------------- ---------------------------------------------- ウィジェット クラス リスナー・インターフェース ------------------ -------------- ---------------------------------------------- ボタン Button View.OnClickListener, View.OnLongClickListener View.OnTouchListener チェックボックス CheckBox CompoundButton.OnCheckedChangeListener View.OnClickListener, View.OnLongClickListener View.OnTouchListener トグルボタン ToggleButton CompoundButton.OnCheckedChangeListener View.OnClickListener, View.OnLongClickListener View.OnTouchListener ラジオボタン RadioGroup RadioGroup.OnCheckedChangeListener RadioButton スピナー Spinner AdapterView.OnItemSelectedListener View.OnTouchListener シークバー SeekBar SeekBar.OnSeekBarChangeListener View.OnTouchListener レーティングバー RatingBar RatingBar.OnRatingBarChangeListener View.OnTouchListener ------------------ -------------- ---------------------------------------------- このサンプルは、アプリケーションの起動時に選択する値が決まっているパターンを示す。 ▲ レイアウト □ 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" > <!-- (1) ボタン --> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> <!-- (2) チェックボックス --> <CheckBox android:id="@+id/checkBox1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CheckBox" /> <!-- (3) トグルボタン --> <ToggleButton android:id="@+id/toggleButton1" android:layout_width="180dp" android:layout_height="wrap_content" android:text="ToggleButton" /> <!-- (4) ラジオボタン --> <RadioGroup android:id="@+id/radioGroup1" android:layout_width="wrap_content" android:layout_height="wrap_content" > <RadioButton android:id="@+id/radio0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="@string/listItem0" /> <!-- (5) --> <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/listItem1" /> <RadioButton android:id="@+id/radio2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/listItem2" /> </RadioGroup> <!-- (6) スピナー --> <Spinner android:id="@+id/spinner1" android:layout_width="match_parent" android:layout_height="wrap_content" android:entries="@array/list1" /> </LinearLayout> --- (1) ボタン クリックする、を実現している基本的なユーザー・インターフェースになっているビュー。 クリック時、長いクリック(長押し)時の処理をハンドラーとしてプログラムする。また、 タッチ時の処理もハンドリングできる。 <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> ボタンに限らず、GUI 部品の属性には、android:onClick 属性があり、クリックされたと きに動くハンドラー・メソッドを指定することができる。 今回は、リスナー・クラスを用意して、それぞれの部品の setOnXxxListener() メソッド でリスナーを登録するので、ここでは指定はしていない。 (2) チェックボックス チェックしている状態とチェックしていない状態の 2 つの状態を持つビュー。 チェックボックスをクリックするたびに、この 2 つの状態が入れ替わる。 <CheckBox android:id="@+id/checkBox1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CheckBox" /> android:checked 属性が "true" のとき、最初からチェックがついている状態になる。 (3) トグルボタン トグルボタンは、クリックするたびに状態が OFF/ON を繰り返す種類のボタンである。 <ToggleButton android:id="@+id/toggleButton1" android:layout_width="180dp" android:layout_height="wrap_content" android:text="ToggleButton" /> android:checked 属性が "true" のとき、最初から ON の状態になる。 android:text 要素に値を設定しても表示としては変わらない。表示の文字列をデフォル トの「OFF」「ON」から変更するには、android:textOff 属性と、android:textOn 属性を 使う。 (4)(5) ラジオボタン チェックボックスのように、チェックしている状態とチェックしていない状態の 2 つの 状態を持つビュー。 ただし、グループ化することで、そのグループの中ではひとつだけがチェックしている状 態になる。 同じグループは、RadioGroup 要素で囲む。 <RadioGroup android:id="@+id/radioGroup1" android:layout_width="wrap_content" android:layout_height="wrap_content" > <RadioButton android:id="@+id/radio0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="@string/listItem0" /> <!-- (5) --> android:checked 属性が "true" の項目があれば、それが最初からチェックがついている 状態になる。 (6) スピナー 選択リスト。複数の項目からひとつを選択できるのは、ラジオボタンと同じ。 アプリ起動時に、このリスナーのハンドラーが動く。 <Spinner android:id="@+id/spinner1" android:layout_width="match_parent" android:layout_height="wrap_content" android:entries="@array/list1" /> なにも設定しないと、リストの先頭のものが選択された状態になる。 android:entries 属性に、表示する項目のリストを設定する。 この例のように静的な場合は、リソースの <string-array> 要素で設定している。 ※ なお、最初に選択する項目の指定は、プログラムで指定するしかなさそう。 Spinner.setSelection() に相当する XML 属性がない。 ▲リソース値 □ res/values/strings.xml --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">FormWidgets01</string> <string name="listItem0">アイスクリーム</string> <string name="listItem1">かりんとう</string> <string name="listItem2">さつまいも</string> <string-array name="list1"> <item>@string/listItem0</item> <item>@string/listItem1</item> <item>@string/listItem2</item> </string-array> </resources> --- string-array 要素を使って、Spinner で使う項目を設定している。 ▲ アクティビティ 単に、Widget にあわせたリスナーを割り当てているだけである。 なお、リスナーはインナー・クラスを使っている。 どのハンドラーが使われたかは、トーストとログで表示している。 □ FormWidgets01Activity.java package jp.marunomarun.android.formwidgets; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.RatingBar; import android.widget.SeekBar; import android.widget.Spinner; import android.widget.Toast; import android.widget.ToggleButton; public class FormWidgets01Activity extends Activity { private static final int TOAST_DURATION = Toast.LENGTH_SHORT; private Context context; // (1) /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); context = this; // (2) // ボタン Button button1 = (Button) findViewById(R.id.button1); OnCheckAndLongClickListener clickListener = new OnCheckAndLongClickListener(); OnTouchListener touchListener = new OnTouchListener(); button1.setOnClickListener(clickListener); button1.setOnLongClickListener(clickListener); button1.setOnTouchListener(touchListener); // チェックボックス CheckBox check1 = (CheckBox) findViewById(R.id.checkBox1); check1.setOnCheckedChangeListener(new OnCheckCompoundButtonListener()); check1.setOnClickListener(clickListener); check1.setOnLongClickListener(clickListener); check1.setOnTouchListener(touchListener); // トグルボタン ToggleButton toggle1 = (ToggleButton) findViewById(R.id.toggleButton1); toggle1.setOnCheckedChangeListener(new OnCheckCompoundButtonListener()); toggle1.setOnClickListener(clickListener); toggle1.setOnLongClickListener(clickListener); toggle1.setOnTouchListener(touchListener); // ラジオボタン RadioGroup group1 = (RadioGroup) findViewById(R.id.radioGroup1); group1.setOnCheckedChangeListener(new OnCheckRadioGroupListener()); group1.setOnClickListener(clickListener); // 動かないだけ group1.setOnLongClickListener(clickListener); // 動かないだけ group1.setOnTouchListener(touchListener); // 動かないだけ // スピナー Spinner spinner1 = (Spinner) findViewById(R.id.spinner1); spinner1.setOnItemSelectedListener(new OnItemSelectedSpinnerListener()); // spinner1.setOnClickListener(listener); // RuntimeException) // spinner1.setOnLongClickListener(listener); // RuntimeException spinner1.setOnTouchListener(touchListener); } /** * ボタンのクリック、長クリックに対するリスナー * * @author marunomaruno */ private class OnCheckAndLongClickListener implements View.OnClickListener, View.OnLongClickListener { @Override public void onClick(View v) { String message = String.format( "OnClickListener.onClick() view: %s", v.getTag()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } @Override public boolean onLongClick(View v) { String message = String.format( "OnLongClickListener.onLongClick() view: %s", v.getTag()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); return false; } } /** * タッチに対するリスナー * * @author marunomaruno */ private class OnTouchListener implements View.OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { String message = String.format( "OnTouchListener.onTouch() view: %s, event: %s", v.getTag(), event); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); return false; } } /** * チェックボックス、トグルボタンのクリックに対するリスナー * * @author marunomaruno */ private class OnCheckCompoundButtonListener implements CompoundButton.OnCheckedChangeListener { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { String message = String.format( "OnCheckedChangeListener.onCheckedChanged(): view: %s, %b", buttonView.getTag(), isChecked); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } } /** * ラジオボタンのクリックに対するリスナー * * @author marunomaruno */ private class OnCheckRadioGroupListener implements RadioGroup.OnCheckedChangeListener { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { RadioButton button = (RadioButton) findViewById(checkedId); String message = String.format( "OnCheckedChangeListener.onCheckedChanged(): %s", button .getText()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } } /** * スピナーの選択に対するリスナー * * @author marunomaruno */ private class OnItemSelectedSpinnerListener implements AdapterView.OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Spinner spinner = (Spinner) parent; String item = (String) spinner.getSelectedItem(); String message = String .format("OnItemSelectedListener.onItemSelected() parent: %s, view: %s, %d: %s", parent.getTag(), view.getTag(), position, item); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { String message = String.format( "OnItemSelectedListener.onNothingSelected() parent: %s", parent.getTag()); System.out.println(message); Toast.makeText(context, message, TOAST_DURATION).show(); } } --- (1)(2) コンテキスト・オブジェクト 内部クラスでトーストを使っているので、このアクティビティ自身(this オブジェクト) を持っていたほうが都合がよい。 private Context context; // (1) context = this; // (2) (●) ボタン クリックする、を実現している基本的なユーザー・インターフェースになっているビュー。 クリック、長押し時の処理をハンドラーとしてプログラムする。また、タッチ時の処理も ハンドリングできる。 Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(clickListener); button1.setOnLongClickListener(clickListener); button1.setOnTouchListener(touchListener); クリックは setOnClickListener()、長押しは setOnLongClickListener()、タッチは setOnTouchListener() を使ってそれぞれのリスナー・オブジェクトを設定する。 クリックのときは、OnTouchListener.onTouch() の ACTION_DOWN イベント、そして ACTION_UP が動く。 この戻り値が false のとき、OnClickListener.onClick()。 まとめると、ACTION_DOWN > ACTION_UP > onClick --- OnTouchListener.onTouch() view: Button, event: MotionEvent{46c1fc70 action=0 ...} OnTouchListener.onTouch() view: Button, event: MotionEvent{46c1fc70 action=1 ...} OnClickListener.onClick() view: Button --- 長押しのときは、クリックに加えて、ACTION_MOVE も動く。 まとめると、ACTION_DOWN > ACTION_MOVE > onLongClick > ACTION_UP > onClick --- OnTouchListener.onTouch() view: Button, event: MotionEvent{46c1fb60 action=0 ...} OnTouchListener.onTouch() view: Button, event: MotionEvent{46c1fb60 action=2 ...} OnLongClickListener.onLongClick() view: Button OnTouchListener.onTouch() view: Button, event: MotionEvent{46c1fb60 action=1 ...} OnClickListener.onClick() view: Button --- △ Button クラス java.lang.Object + android.view.View + android.widget.TextView + android.widget.Button クリックして何らかの動作をさせるためのウィジェット。 Button クラス独自のメソッドはなく、スーパークラスである TextView クラスのメソッ ドをそのまま利用している。 クリックに関しては、通常のクリックと、長クリック(長押し)の 2 つの種類がある。 --- void setOnClickListener(View.OnClickListener l) void setOnLongClickListener(View.OnLongClickListener l) void setOnTouchListener(View.OnTouchListener l) --- (*1) TextView のメソッド △ View.OnClickListener インターフェース android.view.View.OnClickListener クリックに関するリスナー・インターフェース。 このハンドラー・メソッドの onClick() の指定は、ウィジェット上で頻繁に使うことが 多いので、レイアウトの XML ファイルでも、android:onClick 属性として用意されてい る。 ・メソッド --- abstract void onClick(View v) --- △ View.OnLongClickListener インターフェース android.view.View.OnLongClickListener 長押しに関するリスナー・インターフェース。 ・メソッド --- abstract boolean onLongClick(View v) --- (●) チェックボックス チェックしている状態とチェックしていない状態の 2 つの状態を持つビュー。 チェックボックスをクリックするたびに、この 2 つの状態が入れ替わる。 CheckBox check1 = (CheckBox) findViewById(R.id.checkBox1); check1.setOnCheckedChangeListener(new OnCheckCompoundButtonListener()); check1.setOnClickListener(clickListener); check1.setOnLongClickListener(clickListener); check1.setOnTouchListener(touchListener); クリック時の動き まとめると、ACTION_DOWN > ACTION_UP > onCheckedChanged > onClick --- OnTouchListener.onTouch() view: CheckBox, event: MotionEvent{46c1fc70 action=0 ...} OnTouchListener.onTouch() view: CheckBox, event: MotionEvent{46c1fc70 action=1 ...} OnCheckedChangeListener.onCheckedChanged(): view: CheckBox, false OnClickListener.onClick() view: CheckBox --- 長押し時の動き まとめると、ACTION_DOWN > ACTION_MOVE > onLongClick > ACTION_UP > onCheckedChanged > onClick --- OnTouchListener.onTouch() view: CheckBox, event: MotionEvent{46c1fb60 action=0 ...] OnTouchListener.onTouch() view: CheckBox, event: MotionEvent{46c1fb60 action=2 ...} OnTouchListener.onTouch() view: CheckBox, event: MotionEvent{46c1fb60 action=2 ...} OnTouchListener.onTouch() view: CheckBox, event: MotionEvent{46c1fb60 action=2 ...} OnLongClickListener.onLongClick() view: CheckBox OnTouchListener.onTouch() view: CheckBox, event: MotionEvent{46c1fb60 action=1 ...} OnCheckedChangeListener.onCheckedChanged(): view: CheckBox, false OnClickListener.onClick() view: CheckBox --- △ CheckBox クラス java.lang.Object + android.view.View + android.widget.TextView + android.widget.Button + android.widget.CompoundButton + android.widget.CheckBox チェックする・外すことができるウィジェット。 ・メソッドなどは、スーパークラスである CompoundButton クラスのメソッドを利用して いる。CheckBox として使うのは、以下のものが主。 --- boolean isChecked() void setChecked(boolean checked) void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener listener) void toggle() --- △ CompoundButton クラス java.lang.Object + android.view.View + android.widget.TextView + android.widget.Button + android.widget.CompoundButton CheckBox や RadioButton、ToggleButton クラスなどの、ボタンをクリックするとそのボ タンの状態も変化する種類のクラスのスーパークラス。 サブクラスとして、次のクラスがある。 CheckBox, RadioButton, Switch, ToggleButton ・主なメソッド --- boolean isChecked() void setButtonDrawable(int resid) void setButtonDrawable(Drawable d) void setChecked(boolean checked) void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener listener) void toggle() --- △ CompoundButton.OnCheckedChangeListener インターフェース android.widget.CompoundButton.OnCheckedChangeListener ボタンの状態が変化したときのリスナー・インターフェース。 ・メソッド --- abstract void onCheckedChanged(CompoundButton buttonView, boolean isChecked) --- isChecked: チェックされていれば true (●) トグルボタン トグルボタンは、クリックするたびに状態が OFF/ON を繰り返す種類のボタンである。 ToggleButton toggle1 = (ToggleButton) findViewById(R.id.toggleButton1); toggle1.setOnCheckedChangeListener(new OnCheckCompoundButtonListener()); toggle1.setOnClickListener(clickListener); toggle1.setOnLongClickListener(clickListener); toggle1.setOnTouchListener(touchListener); クリック時の動き まとめると、ACTION_DOWN > ACTION_UP > onCheckedChanged > onClick --- OnTouchListener.onTouch() view: ToggleButton, event: MotionEvent{46c1fc70 action=0 ...} OnTouchListener.onTouch() view: ToggleButton, event: MotionEvent{46c1fc70 action=1 ...} OnCheckedChangeListener.onCheckedChanged(): view: ToggleButton, false OnClickListener.onClick() view: ToggleButton --- 長押し時の動き まとめると、ACTION_DOWN > ACTION_MOVE > onLongClick > ACTION_UP > onCheckedChanged > onClick --- OnTouchListener.onTouch() view: ToggleButton, event: MotionEvent{46c1fb60 action=0 ...} OnTouchListener.onTouch() view: ToggleButton, event: MotionEvent{46c1fb60 action=2 ...] OnLongClickListener.onLongClick() view: ToggleButton OnTouchListener.onTouch() view: ToggleButton, event: MotionEvent{46c1fb60 action=1 ...] OnCheckedChangeListener.onCheckedChanged(): view: ToggleButton, false OnClickListener.onClick() view: ToggleButton --- △ ToggleButton クラス java.lang.Object + android.view.View + android.widget.TextView + android.widget.Button + android.widget.CompoundButton + android.widget.ToggleButton トグル・ボタンをあらわすクラス。何も指定しなければ、ボタンに表示されるテキストは 「OFF」と「ON」で、図形としてはライトが消えている状態とついている状態。 ・主なメソッド --- CharSequence getTextOff() CharSequence getTextOn() void setChecked(boolean checked) void setTextOff(CharSequence textOff) void setTextOn(CharSequence textOn) void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener listener) --- (●) ラジオボタン チェックボックスのように、チェックしている状態とチェックしていない状態の 2 つの 状態を持つビュー。 ただし、グループ化することで、そのグループの中ではひとつだけがチェックしている状 態になる。 グループ化は RadioGroup クラスを使う。 RadioGroup group1 = (RadioGroup) findViewById(R.id.radioGroup1); group1.setOnCheckedChangeListener(new OnCheckRadioGroupListener()); group1.setOnClickListener(clickListener); // 動かないだけ group1.setOnLongClickListener(clickListener); // 動かないだけ group1.setOnTouchListener(touchListener); // 動かないだけ 選択したときには、とくに OnClickListener.onClick()、OnLongClickListener .onLongClick()、OnTouchListener.onTouch() が動いていない。これは、RadioGroup で はなく、RadioButton オブジェクトで設定するもの。 選択時の動き --- OnCheckedChangeListener.onCheckedChanged(): かりんとう OnCheckedChangeListener.onCheckedChanged(): さつまいも --- △ RadioGroup クラス java.lang.Object + android.view.View + android.view.ViewGroup + android.widget.LinearLayout + android.widget.RadioGroup RadioButton オブジェクトを持つクラス。 ・主なメソッド --- void check(int id) void clearCheck() int getCheckedRadioButtonId() チェックされているボタンがなければ -1 が返る void setOnCheckedChangeListener(RadioGroup.OnCheckedChangeListener listener) --- △ RadioButton クラス java.lang.Object + android.view.View + android.widget.TextView + android.widget.Button + android.widget.CompoundButton + android.widget.RadioButton 個個のラジオボタンを管理するクラス。 ・主なメソッド --- void toggle() --- △ RadioGroup.OnCheckedChangeListener インターフェース android.widget.RadioGroup.OnCheckedChangeListener ラジオボタンのチェック状態が変化したときのリスナー。 ・メソッド --- abstract void onCheckedChanged(RadioGroup group, int checkedId) --- checkedId: チェックされた ラジオボタンのリソース ID (●) スピナー 選択リスト。複数の項目からひとつを選択できるのは、ラジオボタンと同じ。 アプリ起動時に、このリスナーのハンドラーが動く。 --- OnItemSelectedListener.onItemSelected() parent: Spinner, view: null, 0: アイスクリーム --- Spinner spinner1 = (Spinner) findViewById(R.id.spinner1); spinner1.setOnItemSelectedListener(new OnItemSelectedSpinnerListener()); // spinner1.setOnClickListener(clickListener); // RuntimeException) // spinner1.setOnLongClickListener(clickListener); // RuntimeException spinner1.setOnTouchListener(touchListener); 上のサンプルコードにあるように、setOnClickListener()、setOnLongClickListener() を設定すると、実行時に RuntimeException がスローされる。 選択時の動き まとめると、ACTION_DOWN > ACTION_UP > onItemSelected --- OnTouchListener.onTouch() view: Spinner, event: MotionEvent{46c1fc70 action=0 ...} OnTouchListener.onTouch() view: Spinner, event: MotionEvent{46c41208 action=1 ...} OnItemSelectedListener.onItemSelected() parent: Spinner, view: null, 1: かりんとう OnTouchListener.onTouch() view: Spinner, event: MotionEvent{46c41208 action=0 ...} OnTouchListener.onTouch() view: Spinner, event: MotionEvent{46c41208 action=1 ...} OnItemSelectedListener.onItemSelected() parent: Spinner, view: null, 2: さつまいも --- △ Spinner クラス java.lang.Object + android.view.View + android.view.ViewGroup + android.widget.AdapterView<T extends android.widget.Adapter> + android.widget.AbsSpinner + android.widget.Spinner 選択リストを管理するクラス。 ・主なメソッド --- int getBaseline() CharSequence getPrompt() void onClick(DialogInterface dialog, int which) boolean performClick() void setAdapter(SpinnerAdapter adapter) void setEnabled(boolean enabled) void setGravity(int gravity) void setOnItemClickListener(AdapterView.OnItemClickListener l) void setPrompt(CharSequence prompt) void setPromptId(int promptId) --- △ AdapterView クラス java.lang.Object + android.view.View + android.view.ViewGroup + android.widget.AdapterView<T extends android.widget.Adapter> 配列やリストからの値を管理できるタイプのビューのスーパークラス。 直接のサブクラスではないが、つぎのクラスがこのクラスを継承している。 GridView ListView Spinner ・項目選択関係のメソッド --- Object getSelectedItem() long getSelectedItemId() int getSelectedItemPosition() --- なお、このビューには、setOnClickListener() や setOnLongClickListener() で設定す るリスナーは設定できない。実行すると、つぎのメッセージの例外がスロー。 java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead △ AdapterView.OnItemSelectedListener インターフェース 項目を選択したときのリスナー・インターフェース。 アプリケーション起動時に最初に表示されている項目に対して、まず、このリスナーが動 く。 android.widget.AdapterView.OnItemSelectedListener ・メソッド --- abstract void onItemSelected(AdapterView<?> parent, View view, int position, long id) abstract void onNothingSelected(AdapterView<?> parent) --- 以上
[Android] データの取り扱い - ArrayAdapter ================================================================================ データベースから取得したデータを、ListView を使って表示する。 このとき、ArrayAdapter クラスをカスタマイズすることで、オブジェクトの配列やリス ト (List) から、自動的に値を ListView に展開してリスト表示することができる。 基本的な設定・手順は以下のとおり。 ・表示したいレイアウト(main.xml)で、ListView を設定 ・1 行分のレイアウト(row.xml)を設定 ・オブジェクトを設定するためのクラス(ArrayAdapter を継承)を作成 ・コンストラクターで、オブジェクト配列(リスト)を指定 ・getView() メソッドをオーバーライドして、1 行分の項目を紐付け ・ListView.setAdapter() メソッドで、アダプターを ListView に設定 ▲ アクティビティ 変更点は、以下の 2 箇所のみ。 ・ArrayAdapter のサブクラス(ItemListAdapter)のコンストラクターで、row.xml とオブ ジェクトのリストを紐付け ItemListAdapter<Item> adapter = new ItemListAdapter<Item>(this, R.layout.row, itemList); // (1) ・ListView.setAdapter() メソッドで、アダプターを ListView に設定 ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter); // (2) □ Database02Activity.java --- package jp.marunomaruno.android.database; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; public class Database02Activity extends Activity { private EditText name = null; private EditText comment = null; private DatabaseHelper dbHelper = null; private int TOAST_DURATION = Toast.LENGTH_SHORT; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); name = (EditText) findViewById(R.id.name); comment = (EditText) findViewById(R.id.comment); dbHelper = new DatabaseHelper(this); } @Override public void onPause() { super.onPause(); if (dbHelper != null) { // dbHelper.close(); } } public void onFindButtonClick(View view) { List<Item> itemList = dbHelper.select(name.getText()); if (itemList.size() <= 0) { Toast.makeText(this, getString(R.string.notFoundMessage), TOAST_DURATION).show(); return; } name.setText(itemList.get(0).getName()); comment.setText(itemList.get(0).getComment()); ItemListAdapter adapter = new ItemListAdapter(this, itemList); // (1) ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter); // (2) Toast.makeText( this, String.format(getString(R.string.findMultipleMessage), itemList .size()), TOAST_DURATION).show(); } public void onSaveButtonClick(View view) { long id = dbHelper.insert(name.getText(), comment.getText()); name.setText(""); comment.setText(""); if (id > 0) { Toast.makeText(this, String.format(getString(R.string.saveMessage), id), TOAST_DURATION).show(); } else { Toast.makeText(this, getString(R.string.notSaveMessage), TOAST_DURATION).show(); } } public void onUpdateButtonClick(View view) { int count = dbHelper.update(name.getText(), comment.getText()); if (count > 0) { Toast.makeText(this, String.format(getString(R.string.updateMessage), count), TOAST_DURATION).show(); } else { Toast.makeText(this, getString(R.string.notUpdateMessage), TOAST_DURATION).show(); } } public void onRemoveButtonClick(View view) { int count = dbHelper.delete(name.getText()); name.setText(""); comment.setText(""); if (count > 0) { Toast.makeText(this, String.format(getString(R.string.removeMessage), count), TOAST_DURATION).show(); } else { Toast.makeText(this, getString(R.string.notRemoveMessage), TOAST_DURATION).show(); } } } --- (1) ArrayAdapter のサブクラス(ItemListAdapter)のコンストラクターで、オブジェクト のリストを設定 ItemListAdapter adapter = new ItemListAdapter(this, itemList); // (1) (2) ListView.setAdapter() メソッドで、アダプターを ListView に設定 ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter); // (2) ・ListView クラスのアダプターの設定メソッド --- void setAdapter(ListAdapter adapter) --- ▲ アダプター ListView の各行に、リストや配列の要素を割り当てるためのアダプター。 項目が複数あるような場合は、ArrayAdapter クラスを継承して、カスタマイズしたアダ プター・クラスを作って対応する。 手順としては、getView() メソッドをオーバーライドして、そこに、各項目のデータを割 り当てることになる。 □ ItemListAdapter --- package jp.marunomaruno.android.database; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; public class ItemListAdapter extends ArrayAdapter<Item> { // (1) public ItemListAdapter(Context context, List<Item> objects) { // (2) super(context, 0, objects); // (3) } public ItemListAdapter(Context context, Item[] objects) { // (4) super(context, 0, objects); } public ItemListAdapter(Context context, int resource, int textViewResourceId, List<Item> objects) { super(context, resource, textViewResourceId, objects); } public ItemListAdapter(Context context, int resource, int textViewResourceId, Item[] objects) { super(context, resource, textViewResourceId, objects); } public ItemListAdapter(Context context, int resource, int textViewResourceId) { super(context, resource, textViewResourceId); } public ItemListAdapter(Context context, int textViewResourceId, List<Item> objects) { super(context, textViewResourceId, objects); } public ItemListAdapter(Context context, int textViewResourceId, Item[] objects) { super(context, textViewResourceId, objects); } public ItemListAdapter(Context context, int textViewResourceId) { super(context, textViewResourceId); } @Override public View getView(int position, View convertView, ViewGroup parent) { // (5) if (convertView == null) { LayoutInflater layoutInflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); // (6) convertView = layoutInflater.inflate(R.layout.row, null); // (7) } Item item = getItem(position); // (8) TextView id = (TextView) convertView.findViewById(R.id.idInList); // (9) id.setText(String.valueOf(item.getId())); // (10) TextView name = (TextView) convertView.findViewById(R.id.nameInList); name.setText(item.getName()); TextView comment = (TextView) convertView .findViewById(R.id.commentInList); comment.setText(item.getComment()); return convertView; // (11) } } --- public class ItemListAdapter extends ArrayAdapter<Item> { // (1) ArrayAdapter クラスを継承して作る。 ArrayAdapter クラスは、総称型となっているので、今回は、Item 型に限定して作る。 ・ArrayAdapter クラス オブジェクトの配列やリストと、行のレイアウトの項目を紐付けるためのアダプター・ク ラス。 java.lang.Object - android.widget.BaseAdapter - android.widget.ArrayAdapter<T> ・主なコンストラクター --- ArrayAdapter(Context context, int textViewResourceId, T[] objects) ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) ArrayAdapter(Context context, int textViewResourceId, List<T> objects) ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> obje cts) --- ・主なメソッド --- void add(T object) void addAll(Collection<? extends T> collection) void addAll(T... items) void clear() int getCount() T getItem(int position) long getItemId(int position) int getPosition(T item) void insert(T object, int index) void remove(T object) --- (2)(3)(4) 独自コンストラクターの定義 ArrayAdapter クラスのコンストラクターで、使わない引数(textViewResourceId)の分 を除いたコンストラクターを作っておく。基本的に、オブジェクトのリストか、オブジェ クトの配列を受け取れるようにすればよい。 public ItemListAdapter(Context context, List<Item> objects) { // (2) public ItemListAdapter(Context context, Item[] objects) { // (4) ArrayAdapter クラスのコンストラクターを呼び出す。このとき、textViewResourceId は 指定されていないので、0 にしておく。 super(context, 0, objects); // (3) (5) 行項目を設定するメソッドのオーバーライド public View getView(int position, View convertView, ViewGroup parent) { // (5) (6)(7) ビューを取得 アプリケーションが起動した直後の状態なんかでは、convertView が null になっている。 このため、LayoutInflater の inflate() メソッドを使って、ビューのオブジェクトを取 得する必要がある。 LayoutInflater layoutInflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); // (6) convertView = layoutInflater.inflate(R.layout.row, null); // (7) Context.LAYOUT_INFLATER_SERVICE は、レイアウトの動的な描画のために Inflater オブ ジェクトを生成するのに使う定数。 --- View inflate(int resource, ViewGroup root) --- ・LayoutInflater クラス 動的にレイアウトの XML ファイルのオブジェクトを読み込むためのクラス java.lang.Object - android.view.LayoutInflater ・主なメソッド --- View inflate(int resource, ViewGroup root) View inflate(XmlPullParser parser, ViewGroup root) View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) View inflate(int resource, ViewGroup root, boolean attachToRoot) --- (8) position 番目のオブジェクトを取得 getItem() メソッドを使って、リストや配列の position 番目のオブジェクトを取得する。 Item item = getItem(position); // (8) (9)(10) テキストに設定する TextView id = (TextView) convertView.findViewById(R.id.idInList); // (9) id.setText(String.valueOf(item.getId())); // (10) (11) ビューを返す return convertView; // (11) ▲ データベース関係 □ DatabaseHelper.java ※前回のサンプルと同じ ▲エンティティ □ Item.java ※前回のサンプルと同じ ▲レイアウト テーブルの行の一覧を表示するための ListView 要素が追加されている。 □ res/layout/main.xml --- <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="1" > <EditText android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/nameHint" > <requestFocus > </requestFocus> </EditText> <EditText android:id="@+id/comment" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/commentHint" android:inputType="textMultiLine" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/findButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onFindButtonClick" android:text="@string/findButton" /> <Button android:id="@+id/saveButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onSaveButtonClick" android:text="@string/saveButton" /> <Button android:id="@+id/updateButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onUpdateButtonClick" android:text="@string/updateButton" /> <Button android:id="@+id/removeButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onRemoveButtonClick" android:text="@string/removeButton" /> </LinearLayout> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <!-- (1) --> </LinearLayout> --- (1) リスト・ビュー <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <!-- (1) --> 1 行分のデータは、つぎのファイルで定義している。 □ res/layout/row.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="wrap_content" > <TextView android:id="@+id/idInList" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/nameInList" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/commentInList" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> --- ▲ 文字列 ※前回のサンプルと同じ 以上
[Android] データの取り扱い - データベース(SQLite) ================================================================================ データベース(SQLite)を使って、データの照会・保存・変更・削除を行う。 データ(列)は、つぎの 2 つ。 ・名前 ・コメント なお、データベースのテーブルを使うにあたり、このデータを区別するための主キーとし て、ID 列をつける。なお、SQLite では、この「PRIMARY KEY AUTOINCREMENT」の属性を 持った列は、「_id」という列名にする。こうしておくことで、CursorAdapter クラスを 使って ListView にデータを表示させることができる。 ※ただし、CursorAdapter を使うのは、V3.x 以降では推奨されていないようだ。 データベースのテーブル生成文は以下のとおり。 CREATE TABLE item ( _id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT , comment TEXT ) このサンプル・アプリケーションではつぎのことができる。 ・照会 「名前」欄に記述されたものと一致するものをすべて取得するが、表示するのは最初 に取得したものだけ。 ・保存 「名前」「コメント」欄に記述された内容をデータベースのテーブルに保存する。 ・変更 「名前」欄に記述されたものと一致するものすべての「コメント」を、すべて変更す る。 ・削除 「名前」欄に記述されたものと一致するものすべてを削除する。 データベースを扱うクラスとして、DatabaseHelper クラスを作る。これは、 SQLiteOpenHelper クラス(抽象クラス)を継承して作る。 次のメソッドのオーバーライドが必要。 abstract void onCreate(SQLiteDatabase db) abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 今回のクラス --- Database01Activity アクティビティ DatabaseHelper データベース操作 Item エンティティ --- ▲ アクティビティ データベースに関する操作はすべて DatabaseHelper オブジェクトで行っている。 □ Database01Activity.java --- package jp.marunomaruno.android.database; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class Database01Activity extends Activity { private EditText name = null; private EditText comment = null; private DatabaseHelper dbHelper = null; // (1) private int TOAST_DURATION = Toast.LENGTH_SHORT; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); name = (EditText) findViewById(R.id.name); comment = (EditText) findViewById(R.id.comment); dbHelper = new DatabaseHelper(this); // (2) } @Override public void onPause() { super.onPause(); if (dbHelper != null) { // dbHelper.close(); // 呼ばないほうがよい // (3) } } public void onFindButtonClick(View view) { List<Item> itemList = dbHelper.select(name.getText()); // (4) if (itemList.size() <= 0) { Toast.makeText(this, getString(R.string.notFoundMessage), TOAST_DURATION).show(); return; } name.setText(itemList.get(0).getName()); comment.setText(itemList.get(0).getComment()); Toast.makeText( this, (itemList.size() == 1 ? String .format(getString(R.string.findMessage)) : String .format(getString(R.string.findMultipleMessage), itemList.size())), TOAST_DURATION).show(); } public void onSaveButtonClick(View view) { long id = dbHelper.insert(name.getText(), comment.getText()); // (5) name.setText(""); comment.setText(""); if (id > 0) { Toast.makeText(this, String.format(getString(R.string.saveMessage), id), TOAST_DURATION).show(); } else { Toast.makeText(this, getString(R.string.notSaveMessage), TOAST_DURATION).show(); } } public void onUpdateButtonClick(View view) { int count = dbHelper.update(name.getText(), comment.getText()); // (6) if (count > 0) { Toast.makeText(this, String.format(getString(R.string.updateMessage), count), TOAST_DURATION).show(); } else { Toast.makeText(this, getString(R.string.notUpdateMessage), TOAST_DURATION).show(); } } public void onRemoveButtonClick(View view) { int count = dbHelper.delete(name.getText()); // (7) name.setText(""); comment.setText(""); if (count > 0) { Toast.makeText(this, String.format(getString(R.string.removeMessage), count), TOAST_DURATION).show(); } else { Toast.makeText(this, getString(R.string.notRemoveMessage), TOAST_DURATION).show(); } } } --- (1)(2) データベースにアクセスするオブジェクト private DatabaseHelper dbHelper = null; // (1) DatabaseHelper オブジェクトで、データベースを取得しようとしたときに、データベー スがない場合、onCreate() メソッドが動く。 また、データベースのバージョンが変わったときは、onUpgrade() メソッドが動く。 データベースのバージョンは、SQLiteOpenHelper のコンストラクターの引数 int version で指定する。この値が、現在のバージョンが変わったら、このonUpgrade() メソッドが動くことになる。 dbHelper = new DatabaseHelper(this); // (2) (3) データベースを閉じる ただし、これは自分では閉じない方がよいらしい。 // dbHelper.close(); // 呼ばないほうがよい // (3) 参考 「SQLiteDatabase.closeは明示で呼ぶな、Cursor.closeは明示で呼べ」 SQLiteを使う場合の注意点 http://d.hatena.ne.jp/ukiki999/20100524/p1 (4) name で指定されたデータを取得(照会)する 結果は、List オブジェクトで戻る。 List<Item> itemList = dbHelper.select(name.getText()); // (4) (5) name, comment データを挿入する 結果は、主キーの値が戻る。挿入できなかったときは、-1. long id = dbHelper.insert(name.getText(), comment.getText()); // (5) (6) name で指定されたデータを更新する 結果は、更新した行数。 int count = dbHelper.update(name.getText(), comment.getText()); // (6) (7) name で指定されたデータを削除する 結果は、削除した行数。 int count = dbHelper.delete(name.getText()); // (7) ▲ データベース関係 データベースを操作するためのクラス。 SQLiteOpenHelper クラスを継承して、その抽象メソッドであるつぎのメソッドをオー バーライドする。そして、必要に応じて CRUD メソッドを記しておく。 onCreate(SQLiteDatabase db) onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) データベースの CRUD 操作は、getReadableDatabase() メソッド、 getWritableDatabase() メソッドによって、SQLiteDatabase オブジェクトが取得できる ので、このオブジェクトの中のメソッドによる。 □ DatabaseHelper.java --- package jp.marunomaruno.android.database; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.text.Editable; /** * データベースを扱うためのヘルパー・クラス。 * * @author marunomaruno */ public class DatabaseHelper extends SQLiteOpenHelper { // (1) private Context context; private static final String DATABASE_NAME = "item.db"; private static final int DATABASE_VERSION = 1; // (2) public static final String TABLE_NAME = "item"; public static final String ID = "_id"; public static final String NAME = "name"; public static final String COMMENT = "comment"; public static final String[] COLUMN_NAMES = { ID, NAME, COMMENT, }; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); // (3) this.context = context; } @Override public void onCreate(SQLiteDatabase db) { // (4) final String SQL = String.format(context .getString(R.string.createTableFormat), TABLE_NAME, ID, NAME, COMMENT); // (5) System.out.println("DatabaseHelper.onCreate() SQL = " + SQL); db.execSQL(SQL); // (6) } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // (7) db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); // (8) onCreate(db); } /** * 指定されたデータをデータベースに挿入する。 * * @param name * 名前 * @param comment * コメント * @return 主キーの値 */ public long insert(String name, String comment) { String nullColumnHack = null; // NOT NULL列に値が指定されていない場合のデフォルト値 ContentValues values = new ContentValues(); // 挿入する列名と値 // (9) values.put(NAME, name); // (10) values.put(COMMENT, comment); return getWritableDatabase().insert(TABLE_NAME, nullColumnHack, values); // (11) } /** * 指定されたデータをデータベースに挿入する。 * * @param name * 名前 * @param comment * コメント * @return 主キーの値 */ public long insert(Editable name, Editable comment) { return insert(name.toString(), comment.toString()); } /** * 名前で指定されたデータを変更する。 * * @param name * 名前 * @param comment * コメント * @return 変更した行数 */ public int update(String name, String comment) { ContentValues values = new ContentValues(); // 更新する列名と値 values.put(COMMENT, comment); String whereClause = NAME + " = ?"; // 選択条件 // (12) String[] whereArgs = new String[] { name }; // パラメーター・マーカーの値 // (13) return getWritableDatabase().update(TABLE_NAME, values, whereClause, whereArgs); // (14) } /** * 名前で指定されたデータを変更する。 * * @param name * 名前 * @param comment * コメント * @return 変更した行数 */ public int update(Editable name, Editable comment) { return update(name.toString(), comment.toString()); } /** * 名前で指定されたデータを削除する。 * * @param name * 名前 * @return 削除した行数 */ public int delete(String name) { String whereClause = NAME + " = ?"; // 選択条件 String[] whereArgs = new String[] { name }; // パラメーター・マーカーの 値 return getWritableDatabase().delete(TABLE_NAME, whereClause, whereArgs); // (15) } /** * 名前で指定されたデータを削除する。 * * @param name * 名前 * @return 削除した行数 */ public int delete(Editable name) { return delete(name.toString()); } /** * 名前で指定されたデータを照会する。 * * @param name * 名前 * @return 照会したデータのリスト */ public List<Item> select(String name) { String selection = NAME + " = ?"; // 選択条件 String[] selectionArgs = { name }; // パラメーター・マーカーの値 String groupBy = null; // GROUP BY 句 String having = null; // HAVING 句 String orderBy = null; // ORDER BY 句 Cursor cursor = getReadableDatabase().query(TABLE_NAME, COLUMN_NAMES, selection, selectionArgs, groupBy, having, orderBy); // (16) List<Item> itemList = new ArrayList<Item>(); if (!cursor.moveToFirst()) { // 最初の行をさす // (17) cursor.close(); return itemList; } do { itemList.add(new Item(cursor.getLong(cursor.getColumnIndex(ID)), cursor.getString(cursor.getColumnIndex(NAME)), cursor .getString(cursor.getColumnIndex(COMMENT)))); // (18 ) } while (cursor.moveToNext()); // (19) cursor.close(); // (20) return itemList; } /** * 名前で指定されたデータを照会する。 * * @param name * 名前 * @return 照会したデータのリスト */ public List<Item> select(Editable name) { return select(name.toString()); } } --- (1) データベースにアクセスするクラス SQLiteOpenHelper クラスを継承する。 public class DatabaseHelper extends SQLiteOpenHelper { // (1) ・SQLiteOpenHelper クラス データベースと接続するためのクラス。 SQLite では、JDBC と違い、Connection オブジェクトを作るわけではなく、データベー ス自体の管理は、この SQLiteOpenHelper オブジェクトを通して、生成・バージョンアッ プ・接続などを行う。 java.lang.Object - android.database.sqlite.SQLiteOpenHelper ・コンストラクター --- SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) --- name はデータベース名。データベースは、「/data/data/パッケージ名/database/」に構 築される。 factory は、独自カーソルを定義した場合に使う。標準でよければ null。 version は、データベースのバージョン。既存のデータベースのバージョンと違う場合、 旧バージョンとの値の差によって、 onDowngrade() onUpgrade() メソッドが動く。なお、onUpgrade() メソッドは抽象メソッドなので、オーバーライドが 必要であるが、onDowngrade() メソッドは具象メソッドなので、必要なときにオーバーラ イドすればよい。 ・メソッド --- synchronized void close() String getDatabaseName() synchronized SQLiteDatabase getReadableDatabase() synchronized SQLiteDatabase getWritableDatabase() abstract void onCreate(SQLiteDatabase db) void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) void onOpen(SQLiteDatabase db) abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) --- データベースへの接続は、getReadableDatabase() メソッド、getWritableDatabase() メ ソッドで行う。 (2)(3) このデータベースのバージョン 今回は、バージョン 1 にしておく。データベースの構成が変わったときは、2 以上にし て、データベースを作り直す。 private static final int DATABASE_VERSION = 1; // (2) バージョンの指定は、スーパークラス SQLiteOpenHelper のコンストラクターの引数で指 定する。 super(context, DATABASE_NAME, null, DATABASE_VERSION); // (3) (4) データベースがなかったときの処理 データベースに接続するときに、データベースがなかったときにこのメソッドが呼ばれる。 これは、SQLiteOpenHelper クラスの抽象メソッド。 public void onCreate(SQLiteDatabase db) { // (4) (5)(6) データベースとテーブルを生成する CREATE TABLE 文を記している。文の形式はリソースとして定義している。 final String SQL = String.format(context .getString(R.string.createTableFormat), TABLE_NAME, ID, NAME, COMMENT); // (5) 実際の文は以下のとおり。 CREATE TABLE item ( _id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT , comment TEXT ) SQL 文を実行する。 db.execSQL(SQL); // (6) (7) データベースのバージョンがあがったときの処理 これは、SQLiteOpenHelper クラスの抽象メソッド。 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // (7) (8) テーブルがあれば削除して作り直す db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); // (8) onCreate(db); (9)(10) 挿入する列名と値を設定する テーブルに挿入や更新する場合、列名と値のペアで管理する。名前と値のペアというと、 Map オブジェクトがあるが、SQLite では、ContentValues オブジェクトを使う。使い方 は Map と同じで、put() メソッドを使って値を設定。get() メソッドで、値を取得する。 なお、値の型によって、getAsXxx() メソッドもある。 ContentValues values = new ContentValues(); // 挿入する列名と値 // (9) values.put(NAME, name); // (10) □ ContentValues クラス SQLite の DML を使いやすくするのに適した形のマップ(Map)。 ・android.content.ContentValues ・取得・設定関係のメソッド --- Object get(String key) Boolean getAsBoolean(String key) Byte getAsByte(String key) byte[] getAsByteArray(String key) Double getAsDouble(String key) Float getAsFloat(String key) Integer getAsInteger(String key) Long getAsLong(String key) Short getAsShort(String key) String getAsString(String key) void put(String key, Byte value) void put(String key, Integer value) void put(String key, Float value) void put(String key, Short value) void put(String key, byte[] value) void put(String key, String value) void put(String key, Double value) void put(String key, Long value) void put(String key, Boolean value) void putAll(ContentValues other) void putNull(String key) --- ・その他のメソッド --- void clear() boolean containsKey(String key) boolean equals(Object object) int hashCode() Set<String> keySet() void remove(String key) int size() String toString() Set<Entry<String, Object>> valueSet() --- (11) name, comment データを挿入する データを挿入するので、getWritableDatabase() メソッドを使って、書き込みができる モードで、データベースを開く。このメソッドの結果は、SQLiteDatabase オブジェクト。 SQLiteDatabase クラスには、CRUD 系のメソッドが用意されているので、それらを使って テーブルを操作する。 return getWritableDatabase().insert(TABLE_NAME, nullColumnHack, values); // (11) --- long insert(String table, String nullColumnHack, ContentValues values) --- 戻り値は、挿入したときの rowID。INTEGER 型の主キー制約列が定義されていればその値 (のはず)。挿入エラーのときは -1. String table テーブル名 String nullColumnHack NOT NULL 列に値が指定されていない場合のデフォルト値。 ContentValues values 列名と値がマッピングされたオブジェクト (12)(13)(14) name で指定されたデータを更新する 選択条件には、JDBC と同じように、パラメーター・マーカー「?」が使える。 パラメーター・マーカー「?」に対する値は、String 配列値として別に用意する。 String whereClause = NAME + " = ?"; // 選択条件 // (12) String[] whereArgs = new String[] { name }; // パラメーター・マーカーの値 // (13) テーブルの更新なので、getWritableDatabase() メソッドを使う。 return getWritableDatabase().update(TABLE_NAME, values, whereClause, whereArgs); // (14) --- int update(String table, ContentValues values, String whereClause, String[] whereArgs) --- 戻り値は、更新した行数 (15) name で指定されたデータを削除する update() メソッドと同じように、選択条件にはパラメーター・マーカー「?」が使える。 return getWritableDatabase().delete(TABLE_NAME, whereClause, whereArgs); // (15) --- int delete(String table, String whereClause, String[] whereArgs) --- 戻り値は、削除した行数 (16) name で指定されたデータを取得(照会)する ここでは、照会だけなので、読み取り専用で、getReadableDatabase() メソッドを使えば よい。戻り値は Cursor オブジェクト。 Cursor cursor = getReadableDatabase().query(TABLE_NAME, COLUMN_NAMES, selection, selectionArgs, groupBy, having, orderBy); // (16) --- Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) Cursor rawQuery(String sql, String[] selectionArgs) 引数 boolean distinct DISTINCT(true)かALL(false)か String table テーブル名 String[] columns 射影される列名(nullのとき、すべての列) String selection WHERE句(パラメーターマーカー(?)の指定も可能) String[] selectionArgs パラメーターマーカー(?)を置き換える文字列 String groupBy GROUP BY句 String having HAVING句 String orderBy ORDER BY句 String limit LIMIT句 String sql SQL文(パラメーターマーカー含む) --- (17) 取得したテーブルの最初の行をさす カーソルを使って取得したテーブルを処理する。 まずは、最初の行にカーソルを移動する。 if (!cursor.moveToFirst()) { // 最初の行をさす // (17) JDBC と違って、単純に next() メソッドを使うだけでできるわけではないので注意が必 要。moveToFirst() メソッドで、先頭行に移動し、moveToNext() メソッドで、つぎの行 に移動する、というパターン。全体としては、つぎのような感じでロジックを組む。 --- if (!cursor.moveToFirst()) { // 最初の行をさす cursor.close(); return ...; } do { // 行の処理 } while (cursor.moveToNext()); // つぎの行に移動する cursor.close(); --- ・行の移動関係のメソッド --- boolean move(int offset) boolean moveToFirst() boolean moveToLast() boolean moveToNext() boolean moveToPosition(int position) boolean moveToPrevious() --- (18) 行のデータから Item オブジェクトを生成する itemList.add(new Item(cursor.getLong(cursor.getColumnIndex(ID)), cursor.getString(cursor.getColumnIndex(NAME)), cursor .getString(cursor.getColumnIndex(COMMENT)))); // (18) ・ データ取得関係のメソッド --- byte[] getBlob(int columnIndex) double getDouble(int columnIndex) float getFloat(int columnIndex) int getInt(int columnIndex) long getLong(int columnIndex) short getShort(int columnIndex) String getString(int columnIndex) --- 引数としては列番号だけなので、列名から取得したいときは、 getColumnIndex(String columnName) と組み合わせる必要がある。 (19) つぎの行に移動する } while (cursor.moveToNext()); // (19) (20) カーソルを閉じる 使い終わったカーソルは閉じる。 cursor.close(); // (20) 閉じていない場合は、つぎのエラーが出る。 E/Cursor(14725): Finalizing a Cursor that has not been deactivated or closed. ▲エンティティ 単純に、id、name、comment を持っているだけのクラス。 JavaBeans の要件は満たすようにしている。 □ Item.java --- package jp.marunomaruno.android.database; import java.io.Serializable; /** * データベースの項目を管理するエンティティ・クラス。 * * @author marunomaruno */ public class Item implements Serializable { private static final long serialVersionUID = 1L; public static final int NONE_ID = -1; private long id; private String name; private String comment; public Item(long id, String name, String comment) { this.id = id; this.name = name; this.comment = comment; } public Item(String name, String comment) { this(NONE_ID, name, comment); } public Item() { assert true; // 何もしない } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } @Override public String toString() { return String.format("[%d, %s, %s]", id, name, comment); } } --- ▲レイアウト □ res/layout/main.xml --- <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="1" > <EditText android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/nameHint" > <requestFocus > </requestFocus> </EditText> <EditText android:id="@+id/comment" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/commentHint" android:inputType="textMultiLine" > </EditText> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/findButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onFindButtonClick" android:text="@string/findButton" > </Button> <Button android:id="@+id/saveButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onSaveButtonClick" android:text="@string/saveButton" > </Button> <Button android:id="@+id/updateButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onUpdateButtonClick" android:text="@string/updateButton" > </Button> <Button android:id="@+id/removeButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onRemoveButtonClick" android:text="@string/removeButton" > </Button> </LinearLayout> </LinearLayout> --- ▲ 文字列 --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Database01</string> <string name="nameHint">名前</string> <string name="commentHint">コメント</string> <string name="saveButton">保存</string> <string name="findButton">検索</string> <string name="removeButton">削除</string> <string name="updateButton">変更</string> <string name="saveMessage">ID %d で保存しました</string> <string name="findMessage">データがありました。</string> <string name="findMultipleMessage"> %d 件のデータがありました。最初の1件を表示します</string> <string name="removeMessage">%d 件のデータを削除しました</string> <string name="updateMessage">%d 件のデータを変更しました</string> <string name="notSaveMessage">データを保存できませんでした</string> <string name="notFoundMessage">データはありませんでした</string> <string name="notRemoveMessage">データを削除できませんでした</string> <string name="notUpdateMessage">データを変更できませんでした</string> <string name="createTableFormat"> CREATE TABLE %1$s ( %2$s INTEGER PRIMARY KEY AUTOINCREMENT , %3$s TEXT , %4$s TEXT ) </string> <!-- (1) --> </resources> --- (1) テーブルを生成する SQL 文のフォーマット <string name="createTableFormat"> CREATE TABLE %1$s ( %2$s INTEGER PRIMARY KEY AUTOINCREMENT , %3$s TEXT , %4$s TEXT ) </string> <!-- (1) --> ※ この部分は、国際化とは意味が違うので、別の XML ファイルにした方がよいかもしれ ない。 以上