Could not find class 'com.google.ads.AdView'
標題のエラーについては下記のサイトで解決策が掲示されています。
Libraries in SDK 17 - android
How to fix the “NoClassDefFoundError” with ADT 17
Dealing with dependencies in Android projects
この問題は、revision 17 of the Android SDK Tools and of the Eclipse ADT plug-inにおけるものであるとされています。
解決方法は次のとおりです。
プロジェクト名のフォルダー(プロジェクトルートのフォルダー)の直下に"libs"という名前のフォルダーを設けて、そのフォルダーにjarファイルをコピーしてください。そうすれば、jarファイルは自動的に"Android Dependencies"のフォルダーに組み込まれ、問題は解決します。
"libs"という名前のフォルダーは、「Package Explorer」欄で手入力で作成できます。
教科書で示されているような、EclipseにおけるProject > Properties > Java Build Path > Libralies > Add External JARs....といった操作は必要ではありません。
教科書:Google AdMob Ads Android Fundamentals
むしろ、(Project > Properties > Java Build Path > Libralies の)「JARS and class folders on the build path:」欄には、"Android 4.0.3"及び"Android Dependencies"の2個だけにしておかねばなりません。
そして、"libs"という名前のフォルダーにGoogleAdMobAdsSdk-4.3.1.jarファイルをコピーします。jarファイルをコピーする作業は、「Package Explorer」欄で行えます。
この場合の留意点として、"libs"フォルダーの直下にjarファイルを置かねばならないということです。"libs"フォルダーとjarファイルの中間に何らかのフォルダーが有ってはダメです。
正しいjarファイルの配置:
JPVoicer(プロジェクトルートのフォルダー)
|- libs(フォルダー)
|- GoogleAdMobAdsSdk-4.3.1.jar
ダメなファイルの配置
JPVoicer(プロジェクトルートのフォルダー)
|- libs(フォルダー)
|- GoogleAdMobAdsSdkAndroid-4.3.1(フォルダー)
|- GoogleAdMobAdsSdk-4.3.1.jar
2012年3月25日日曜日
2012年3月18日日曜日
onTouch sample code
onTouch sample code
利用者がViewを操作した場合、その操作は当該Viewのみに限定されるのであって、他のView、例えば、親のViewに自動的に処理が移るというのではない。
もし、他のViewに処理を移し替えたい場合には、そのようにcodeを書かなければならない。
public class OnTouchActivity extends Activity
implements
OnTouchListener,
OnClickListener
{
TextView tvValue, tvResult;
Button buMain, buSub;
boolean bReturnTrue;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvValue = (TextView)findViewById(R.id.TextReturnValue);
tvResult = (TextView)findViewById(R.id.TextResult);
buMain = (Button)findViewById(R.id.ButtonMain);
buMain.setOnClickListener(this);
buSub = (Button)findViewById(R.id.ButtonSub);
buSub.setOnTouchListener(this);
buSub.setOnClickListener(this);
DisplayValue(false);
}
void DisplayValue(boolean b){
String s;
bReturnTrue = b;
if(b==true) s= "Return Value onTouch : true";
else s = "Return Value onTouch : false";
tvValue.setText(s);
}
/*
* onClickメソッドの実行の前に、onTouchメソッドが実行される。
* onTouchメソッドにおいてfalseを返した場合、そのViewを引数とするonClickメソッドが呼ばれる。
* trueを返した場合、onClickメソッドは呼ばれない。
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
tvResult.setText("");
if(v==buSub){
if(bReturnTrue==true){
//trueを返すことによりbuSubのonClickメソッドは呼ばれなくなる。
return true;
}
}
return false;
}
//onTouchメソッドにおける戻値がfalseの場合に、onClickメソッドが呼ばれる。
@Override
public void onClick(View v) {
if(v==buMain){
if(bReturnTrue==true) DisplayValue(false);
else DisplayValue(true);
return;
}
//buSubのonTouchメソッドの戻値がtrueの場合、onClickメソッドは呼ばれない。
if(v==buSub){
tvResult.setText("onClick : ButtonSub");
return;
}
}
}
利用者がViewを操作した場合、その操作は当該Viewのみに限定されるのであって、他のView、例えば、親のViewに自動的に処理が移るというのではない。
もし、他のViewに処理を移し替えたい場合には、そのようにcodeを書かなければならない。
public class OnTouchActivity extends Activity
implements
OnTouchListener,
OnClickListener
{
TextView tvValue, tvResult;
Button buMain, buSub;
boolean bReturnTrue;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvValue = (TextView)findViewById(R.id.TextReturnValue);
tvResult = (TextView)findViewById(R.id.TextResult);
buMain = (Button)findViewById(R.id.ButtonMain);
buMain.setOnClickListener(this);
buSub = (Button)findViewById(R.id.ButtonSub);
buSub.setOnTouchListener(this);
buSub.setOnClickListener(this);
DisplayValue(false);
}
void DisplayValue(boolean b){
String s;
bReturnTrue = b;
if(b==true) s= "Return Value onTouch : true";
else s = "Return Value onTouch : false";
tvValue.setText(s);
}
/*
* onClickメソッドの実行の前に、onTouchメソッドが実行される。
* onTouchメソッドにおいてfalseを返した場合、そのViewを引数とするonClickメソッドが呼ばれる。
* trueを返した場合、onClickメソッドは呼ばれない。
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
tvResult.setText("");
if(v==buSub){
if(bReturnTrue==true){
//trueを返すことによりbuSubのonClickメソッドは呼ばれなくなる。
return true;
}
}
return false;
}
//onTouchメソッドにおける戻値がfalseの場合に、onClickメソッドが呼ばれる。
@Override
public void onClick(View v) {
if(v==buMain){
if(bReturnTrue==true) DisplayValue(false);
else DisplayValue(true);
return;
}
//buSubのonTouchメソッドの戻値がtrueの場合、onClickメソッドは呼ばれない。
if(v==buSub){
tvResult.setText("onClick : ButtonSub");
return;
}
}
}
<?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"
>
<Button
android:id="@+id/ButtonMain"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/ButtonMain"
>
</Button>
<TextView
android:id="@+id/TextReturnValue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</TextView>
<Button
android:id="@+id/ButtonSub"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/ButtonSub"
>
</Button>
<TextView
android:id="@+id/TextResult"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</TextView>
</LinearLayout>
2012年3月14日水曜日
TextViewの任意の位置にスクロールさせる
TextViewの任意の位置にスクロールさせる
参考
AndroidのScrollViewで一番下までスクロールさせるには
ScrollViewを一番下まで自動でスクロールする方法
Scroll TextView to text position
TextView#getLineCountメソッドの戻値がゼロ
ScrollViewを使って、TextViewの任意の位置までスクロールさせるプログラムです。
このプログラムでは、TextViewに設定する大量の文字列群内の中央の文字列に赤色を付けて、その赤色の文字列が存在する中央の位置まで画面をスクロールさせます。
Javaのsample codeは次のとおりです。
public class ScrollTextActivity extends Activity
implements
OnClickListener
{
Button bu;
TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SpannableStringBuilder sb;
int i, j;
BackgroundColorSpan spanBC;
final String sData = "あいうえお";
bu = (Button)findViewById(R.id.Button);
bu.setOnClickListener(this);
//適当に文字列データを作成する。
spanBC = new BackgroundColorSpan(0xff880000);
sb = new SpannableStringBuilder();
for(i=0, j=0; i<300; i++, j++) sb.append(sData);
j *= sData.length();
for(i=0; i<300; i++) sb.append(sData);
sb.setSpan(spanBC, j, j+sData.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv = (TextView)findViewById(R.id.TextView);
tv.setText(sb);
//onCreateメソッドが実行される時点ではスクロールはできない。
//ScrollView sv;
//sv = (ScrollView)findViewById(R.id.ScrollView);
//sv.smoothScrollTo(0, 500);//効果の無いコマンド
}
@Override
public void onClick(View v) {
if(v==bu){
//Viewが作成された後で、スクロールが可能になる。
ScrollView sv;
int iLine, iPixel, iHeight, i;
sv = (ScrollView)findViewById(R.id.ScrollView);
iLine = tv.getLineCount ();
iLine /= 2;
iPixel = tv.getLineHeight ();
iHeight = sv.getHeight ();
i = iLine * iPixel;
i -= iHeight / 2;
sv.smoothScrollTo(0, i);//実行可能
}
}
}
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"
>
<Button
android:id="@+id/Button"
android:text="@string/Button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</Button>
<ScrollView
android:id="@+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/TextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</TextView>
</ScrollView>
</LinearLayout>
参考
AndroidのScrollViewで一番下までスクロールさせるには
ScrollViewを一番下まで自動でスクロールする方法
Scroll TextView to text position
TextView#getLineCountメソッドの戻値がゼロ
ScrollViewを使って、TextViewの任意の位置までスクロールさせるプログラムです。
このプログラムでは、TextViewに設定する大量の文字列群内の中央の文字列に赤色を付けて、その赤色の文字列が存在する中央の位置まで画面をスクロールさせます。
Javaのsample codeは次のとおりです。
public class ScrollTextActivity extends Activity
implements
OnClickListener
{
Button bu;
TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SpannableStringBuilder sb;
int i, j;
BackgroundColorSpan spanBC;
final String sData = "あいうえお";
bu = (Button)findViewById(R.id.Button);
bu.setOnClickListener(this);
//適当に文字列データを作成する。
spanBC = new BackgroundColorSpan(0xff880000);
sb = new SpannableStringBuilder();
for(i=0, j=0; i<300; i++, j++) sb.append(sData);
j *= sData.length();
for(i=0; i<300; i++) sb.append(sData);
sb.setSpan(spanBC, j, j+sData.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv = (TextView)findViewById(R.id.TextView);
tv.setText(sb);
//onCreateメソッドが実行される時点ではスクロールはできない。
//ScrollView sv;
//sv = (ScrollView)findViewById(R.id.ScrollView);
//sv.smoothScrollTo(0, 500);//効果の無いコマンド
}
@Override
public void onClick(View v) {
if(v==bu){
//Viewが作成された後で、スクロールが可能になる。
ScrollView sv;
int iLine, iPixel, iHeight, i;
sv = (ScrollView)findViewById(R.id.ScrollView);
iLine = tv.getLineCount ();
iLine /= 2;
iPixel = tv.getLineHeight ();
iHeight = sv.getHeight ();
i = iLine * iPixel;
i -= iHeight / 2;
sv.smoothScrollTo(0, i);//実行可能
}
}
}
<?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"
>
<Button
android:id="@+id/Button"
android:text="@string/Button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</Button>
<ScrollView
android:id="@+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/TextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</TextView>
</ScrollView>
</LinearLayout>
SimpleAdapterのsample code
SimpleAdapterのsample code
文字列を代入し、色を付けたTextViewを一覧にして表示するSimpleAdapterのsample codeです。
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="wrap_content"
>
<TextView
android:id="@+id/TextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</TextView>
</LinearLayout>
文字列を代入し、色を付けたTextViewを一覧にして表示するSimpleAdapterのsample codeです。
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="wrap_content"
>
<TextView
android:id="@+id/TextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</TextView>
</LinearLayout>
Javaのcodeは次のとおりです。
public class SimpleAdapterActivity extends ListActivity{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
String sFrom[] = {"String", "Color"};
int iTo[] = new int[]{R.id.TextView, R.id.TextView};
ArrayList<Map<String, Object>> data =new ArrayList<Map<String, Object>>();
SimpleAdapter sa;
SimpleAdapter.ViewBinder savb;
savb = new SimpleAdapter.ViewBinder(){
@Override
public boolean setViewValue(View view, Object data, String s){
if(view.getId()==R.id.TextView){
TextView tv;
tv = (TextView)view;
if(data.getClass().equals(String.class)==true){
String sData;
sData = (String)data;
tv.setText(sData);
return true;
}
if(data.getClass().equals(Integer.class)==true){
Integer iData;
iData = (Integer)data;
tv.setBackgroundColor(iData.intValue());
return true;
}
}
return false;
}
};
//適当にデータを作成する。
Map<String, Object> m;
m = new HashMap<String, Object>();
m.put("String", "Red");
m.put("Color", 0xffff0000);
data.add(m);
m = new HashMap<String, Object>();
m.put("String", "Green");
m.put("Color", 0xff00ff00);
data.add(m);
m = new HashMap<String, Object>();
m.put("String", "Blue");
m.put("Color", 0xff0000ff);
data.add(m);
sa = new SimpleAdapter(this, data, R.layout.main, sFrom, iTo);
sa.setViewBinder(savb);
setListAdapter(sa);
}
}
2012年3月13日火曜日
Spannable.SPAN_PARAGRAPH
Spannable.SPAN_PARAGRAPH
Spannable.SPAN_PARAGRAPHを使ったsample codeは次のとおりです。
public class TextViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SpannableString ss;
SpannableStringBuilder ssb;
BackgroundColorSpan spanRed, spanGreen, spanBlue;
TextView tv;
ss = new SpannableString("aaa\nbbb\nccc\nddd\n");
ssb = new SpannableStringBuilder();
spanRed = new BackgroundColorSpan(0xff880000);
spanGreen = new BackgroundColorSpan(0xff008800);
spanBlue = new BackgroundColorSpan(0xff000088);
ss.setSpan(spanRed, 4, 8, Spannable.SPAN_PARAGRAPH);
ss.setSpan(spanGreen, 8, 12, Spannable.SPAN_PARAGRAPH);
ss.setSpan(spanBlue, 12, 16, Spannable.SPAN_PARAGRAPH);
ssb.append(ss);
spanRed = new BackgroundColorSpan(0xff880000);
ssb.append("eee\n");
ssb.setSpan(spanRed, 16, 20, Spannable.SPAN_PARAGRAPH);
ssb.append("fff\n");
tv = (TextView)findViewById(R.id.TextView);
tv.setText(ssb);
}
}
bbb
ccc
ddd
eee
fff
Spannable.SPAN_PARAGRAPHを使ったsample codeは次のとおりです。
public class TextViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SpannableString ss;
SpannableStringBuilder ssb;
BackgroundColorSpan spanRed, spanGreen, spanBlue;
TextView tv;
ss = new SpannableString("aaa\nbbb\nccc\nddd\n");
ssb = new SpannableStringBuilder();
spanRed = new BackgroundColorSpan(0xff880000);
spanGreen = new BackgroundColorSpan(0xff008800);
spanBlue = new BackgroundColorSpan(0xff000088);
ss.setSpan(spanRed, 4, 8, Spannable.SPAN_PARAGRAPH);
ss.setSpan(spanGreen, 8, 12, Spannable.SPAN_PARAGRAPH);
ss.setSpan(spanBlue, 12, 16, Spannable.SPAN_PARAGRAPH);
ssb.append(ss);
spanRed = new BackgroundColorSpan(0xff880000);
ssb.append("eee\n");
ssb.setSpan(spanRed, 16, 20, Spannable.SPAN_PARAGRAPH);
ssb.append("fff\n");
tv = (TextView)findViewById(R.id.TextView);
tv.setText(ssb);
}
}
このプログラムを実行すると次のように画面に表示されます。
aaabbb
ccc
ddd
eee
fff
SPAN_EXCLUSIVE_EXCLUSIVE
SPAN_EXCLUSIVE_EXCLUSIVE
SpannableStringBuilder#setSpanメソッドの第四番目の引数の意味が不明だったため、調べました。
Corgiさんのspanの適用範囲の設定に解答がありました。
そこに書かれている内容を検証するプログラムを作りました。
public class TextViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String s;
SpannableStringBuilder ssb;
BackgroundColorSpan spanBCEE, spanBCEI, spanBCIE, spanBCII, spanBCNothing;
TextView tv;
s = getString(R.string.hello);
ssb = new SpannableStringBuilder();
ssb.append(s);
spanBCEE = new BackgroundColorSpan(0xff880000);
spanBCEI = new BackgroundColorSpan(0xff880000);
spanBCIE = new BackgroundColorSpan(0xff880000);
spanBCII = new BackgroundColorSpan(0xff880000);
spanBCNothing = new BackgroundColorSpan(0xff880000);
ssb.setSpan(spanBCEE, 2, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(spanBCEI, 7, 9, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
ssb.setSpan(spanBCIE, 12, 14, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
ssb.setSpan(spanBCII, 17, 19, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
ssb.setSpan(spanBCNothing, 17, 19, 0);
ssb.insert(24, "*");
ssb.insert(22, "*");
ssb.insert(19, "*");
ssb.insert(17, "*");
ssb.insert(14, "*");
ssb.insert(12, "*");
ssb.insert(9, "*");
ssb.insert(7, "*");
ssb.insert(4, "*");
ssb.insert(2, "*");
tv = (TextView)findViewById(R.id.TextView);
tv.setText(ssb);
}
}
上記プログラムによって、画面には次のように表示されます。
He*ll*o W*or*ld,* T*ext*Vi*ewA*ct*ivity!
次に、挿入を、範囲の内側に実施した場合の実験をしてみました。挿入部分のcodeは次のとおりです。
ssb.insert(23, "*");
ssb.insert(18, "*");
ssb.insert(13, "*");
ssb.insert(8, "*");
ssb.insert(3, "*");
この結果は次のとおりです。
Hel*lo Wo*rld, *TextV*iewAc*tivity!
以上のことから、Corgiさんが説明するように、「spanの適用範囲の直前直後に関する設定」ということが言えます。
挿入をすることによって意味を成すオプションであるため、SpannableStringBuilder#setSpanでは使えますが、SpannableString#setSpanでは意味の無いオプションであるように思えます。
第四番目の引数にゼロを代入した場合、装飾が表示されないため、何か値を代入しておかなければならないということです。
Spannable.SPAN_MARK_MARKは、Spannable.SPAN_INCLUSIVE_EXCLUSIVEと同じConstant Value 17 (0x00000011)です。
Spannable.SPAN_POINT_POINTは、Spannable.SPAN_EXCLUSIVE_INCLUSIVEと同じConstant Value 34 (0x00000022)です。
SpannableStringBuilder#setSpanメソッドの第四番目の引数の意味が不明だったため、調べました。
Corgiさんのspanの適用範囲の設定に解答がありました。
そこに書かれている内容を検証するプログラムを作りました。
public class TextViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String s;
SpannableStringBuilder ssb;
BackgroundColorSpan spanBCEE, spanBCEI, spanBCIE, spanBCII, spanBCNothing;
TextView tv;
s = getString(R.string.hello);
ssb = new SpannableStringBuilder();
ssb.append(s);
spanBCEE = new BackgroundColorSpan(0xff880000);
spanBCEI = new BackgroundColorSpan(0xff880000);
spanBCIE = new BackgroundColorSpan(0xff880000);
spanBCII = new BackgroundColorSpan(0xff880000);
spanBCNothing = new BackgroundColorSpan(0xff880000);
ssb.setSpan(spanBCEE, 2, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(spanBCEI, 7, 9, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
ssb.setSpan(spanBCIE, 12, 14, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
ssb.setSpan(spanBCII, 17, 19, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
ssb.setSpan(spanBCNothing, 17, 19, 0);
ssb.insert(24, "*");
ssb.insert(22, "*");
ssb.insert(19, "*");
ssb.insert(17, "*");
ssb.insert(14, "*");
ssb.insert(12, "*");
ssb.insert(9, "*");
ssb.insert(7, "*");
ssb.insert(4, "*");
ssb.insert(2, "*");
tv = (TextView)findViewById(R.id.TextView);
tv.setText(ssb);
}
}
He*ll*o W*or*ld,* T*ext*Vi*ewA*ct*ivity!
次に、挿入を、範囲の内側に実施した場合の実験をしてみました。挿入部分のcodeは次のとおりです。
ssb.insert(23, "*");
ssb.insert(18, "*");
ssb.insert(13, "*");
ssb.insert(8, "*");
ssb.insert(3, "*");
この結果は次のとおりです。
Hel*lo Wo*rld, *TextV*iewAc*tivity!
以上のことから、Corgiさんが説明するように、「spanの適用範囲の直前直後に関する設定」ということが言えます。
挿入をすることによって意味を成すオプションであるため、SpannableStringBuilder#setSpanでは使えますが、SpannableString#setSpanでは意味の無いオプションであるように思えます。
第四番目の引数にゼロを代入した場合、装飾が表示されないため、何か値を代入しておかなければならないということです。
Spannable.SPAN_MARK_MARKは、Spannable.SPAN_INCLUSIVE_EXCLUSIVEと同じConstant Value 17 (0x00000011)です。
Spannable.SPAN_POINT_POINTは、Spannable.SPAN_EXCLUSIVE_INCLUSIVEと同じConstant Value 34 (0x00000022)です。
2012年3月12日月曜日
複雑な形状のViewの一覧を作成する
複雑な形状のViewの一覧を作成する
ListViewを使えば複雑な形状のViewの一覧を作成できる。
参考:SimpleAdapterのsample code
しかし、この技法の欠点は、書き込み可能なView、例えば、EditTextを配置しても、そのEditTextに対して利用者が書き込みを行うことはできない、ということである。
ListViewのような作り込まれたものは、プログラミングが終わった後で、予期しない不都合が判明する。
素直に、ScrollView & LayoutInflaterを使って、地道に作成する。
ただし、この場合、EditTextにはIDを与えてはいけない、という点に留意しなければならない。
例えば、次のxmlのように、android:id="@+id/EditText"を設けてはいけない。削除しよう。
<EditText
android:id="@+id/EditText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</EditText>
仮に、IDを設けたとしても、初回起動時には、上手く表示される。しかし、configuration changeに伴う再起動が発生した後で表示されるEditTextには、全て同一の文字列が代入されてしまう。
この問題を避けるために、ID指定を書いてはいけないのである。
TextViewの場合はID指定をしても問題は発生しない。
main.xmlは次のとおりである。IDがParentListのLinearLayoutに、複数の子Viewを動的に追加する。
<?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"
>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:id="@+id/ParentList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
</LinearLayout>
</ScrollView>>
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:background="#555"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#000"
>
<CheckBox
android:text="@string/Apply"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</CheckBox>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:text="@string/Before"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</TextView>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</EditText>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:text="@string/After"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</TextView>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</EditText>
</LinearLayout>
</LinearLayout>
</LinearLayout>
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
setContentView(R.layout.main);
int i;
ArrayList<String> al;
BackupData bd;
bd = (BackupData)getLastNonConfigurationInstance();
if(bd==null){
//サンプルプログラムなので適当にデータを代入する。
al = new ArrayList<String>();
al.add("true");
al.add("Green");
al.add("Blue");
al.add("false");
al.add("Green");
al.add("Blue");
al.add("true");
al.add("Green");
al.add("Blue");
al.add("false");
al.add("Red");
al.add("Blue");
al.add("true");
al.add("Yellow");
al.add("Red");
}
else{//configuration changeに伴う再起動
al = bd.getBackupData();
}
for(i=0; i<al.size()/3; i++){
LayoutInflater inf;
LinearLayout llParent, ll, ll2, llChild;
CheckBox cb;
EditText et;
String s;
//親Viewを取得する。
llParent = (LinearLayout)findViewById(R.id.ParentList);
//挿入する子Viewを作成する。
inf = getLayoutInflater();
ll = (LinearLayout)inf.inflate(R.layout.listitem, null);
ll2 = (LinearLayout)ll.getChildAt(0);
//子Viewにデータを入れる。
cb = (CheckBox)ll2.getChildAt(0);
s = al.get(i*3);
if(s.equals("true")==true) cb.setChecked(true);
else cb.setChecked(false);
llChild = (LinearLayout)ll2.getChildAt(1);
et = (EditText)llChild.getChildAt(1);
et.setText(al.get(i*3+1));
llChild = (LinearLayout)ll2.getChildAt(2);
et = (EditText)llChild.getChildAt(1);
et.setText(al.get(i*3+2));
//親Viewに子Viewを入れる。
llParent.addView(ll);
}
}
//configuration changeに伴う再起動への対応
@Override
public Object onRetainNonConfigurationInstance(){
ArrayList<String> al;
BackupData bd;
LinearLayout llParent;
int i, iSize;
al = new ArrayList<String>();
llParent = (LinearLayout)findViewById(R.id.ParentList);
iSize = llParent.getChildCount();
for(i=0; i<iSize; i++){
LinearLayout ll, ll2, llChild;
CheckBox cb;
EditText et;
String s;
ll = (LinearLayout)llParent.getChildAt(i);
ll2 = (LinearLayout)ll.getChildAt(0);
cb = (CheckBox)ll2.getChildAt(0);
if(cb.isChecked()==true) s = "true";
else s = "false";
al.add(s);
llChild = (LinearLayout)ll2.getChildAt(1);
et = (EditText)llChild.getChildAt(1);
s = et.getText().toString();
al.add(s);
llChild = (LinearLayout)ll2.getChildAt(2);
et = (EditText)llChild.getChildAt(1);
s = et.getText().toString();
al.add(s);
}
bd = new BackupData();
bd.setBackupData(al);
return bd;
}
private class BackupData{
private ArrayList<String> dataBackup;
void setBackupData(ArrayList<String> al){
dataBackup = al;
}
ArrayList<String> getBackupData(){
return dataBackup;
}
}
}
ListViewを使えば複雑な形状のViewの一覧を作成できる。
参考:SimpleAdapterのsample code
しかし、この技法の欠点は、書き込み可能なView、例えば、EditTextを配置しても、そのEditTextに対して利用者が書き込みを行うことはできない、ということである。
ListViewのような作り込まれたものは、プログラミングが終わった後で、予期しない不都合が判明する。
素直に、ScrollView & LayoutInflaterを使って、地道に作成する。
ただし、この場合、EditTextにはIDを与えてはいけない、という点に留意しなければならない。
例えば、次のxmlのように、android:id="@+id/EditText"を設けてはいけない。削除しよう。
<EditText
android:id="@+id/EditText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</EditText>
この問題を避けるために、ID指定を書いてはいけないのである。
TextViewの場合はID指定をしても問題は発生しない。
main.xmlは次のとおりである。IDがParentListのLinearLayoutに、複数の子Viewを動的に追加する。
<?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"
>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:id="@+id/ParentList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
</LinearLayout>
</ScrollView>>
</LinearLayout>
上記のxmlの中に、次のlistitem.xmlを動的に挿入する。各ViewにはIDを付けていない。
<?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"
android:padding="2dp"
android:background="#555"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#000"
>
<CheckBox
android:text="@string/Apply"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</CheckBox>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:text="@string/Before"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</TextView>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</EditText>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:text="@string/After"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</TextView>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
</EditText>
</LinearLayout>
</LinearLayout>
</LinearLayout>
上記2個のxmlを使って、複数のViewを動的に生成し、一覧を作成するJavaのcodeは次のとおりである。ViewのIDが存在しないため、個々のViewの識別はアドレス(相対位置と表現して良いかもしれない)で行う。
public class InflateListActivity extends Activity {@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
setContentView(R.layout.main);
int i;
ArrayList<String> al;
BackupData bd;
bd = (BackupData)getLastNonConfigurationInstance();
if(bd==null){
//サンプルプログラムなので適当にデータを代入する。
al = new ArrayList<String>();
al.add("true");
al.add("Green");
al.add("Blue");
al.add("false");
al.add("Green");
al.add("Blue");
al.add("true");
al.add("Green");
al.add("Blue");
al.add("false");
al.add("Red");
al.add("Blue");
al.add("true");
al.add("Yellow");
al.add("Red");
}
else{//configuration changeに伴う再起動
al = bd.getBackupData();
}
for(i=0; i<al.size()/3; i++){
LayoutInflater inf;
LinearLayout llParent, ll, ll2, llChild;
CheckBox cb;
EditText et;
String s;
//親Viewを取得する。
llParent = (LinearLayout)findViewById(R.id.ParentList);
//挿入する子Viewを作成する。
inf = getLayoutInflater();
ll = (LinearLayout)inf.inflate(R.layout.listitem, null);
ll2 = (LinearLayout)ll.getChildAt(0);
//子Viewにデータを入れる。
cb = (CheckBox)ll2.getChildAt(0);
s = al.get(i*3);
if(s.equals("true")==true) cb.setChecked(true);
else cb.setChecked(false);
llChild = (LinearLayout)ll2.getChildAt(1);
et = (EditText)llChild.getChildAt(1);
et.setText(al.get(i*3+1));
llChild = (LinearLayout)ll2.getChildAt(2);
et = (EditText)llChild.getChildAt(1);
et.setText(al.get(i*3+2));
//親Viewに子Viewを入れる。
llParent.addView(ll);
}
}
//configuration changeに伴う再起動への対応
@Override
public Object onRetainNonConfigurationInstance(){
ArrayList<String> al;
BackupData bd;
LinearLayout llParent;
int i, iSize;
al = new ArrayList<String>();
llParent = (LinearLayout)findViewById(R.id.ParentList);
iSize = llParent.getChildCount();
for(i=0; i<iSize; i++){
LinearLayout ll, ll2, llChild;
CheckBox cb;
EditText et;
String s;
ll = (LinearLayout)llParent.getChildAt(i);
ll2 = (LinearLayout)ll.getChildAt(0);
cb = (CheckBox)ll2.getChildAt(0);
if(cb.isChecked()==true) s = "true";
else s = "false";
al.add(s);
llChild = (LinearLayout)ll2.getChildAt(1);
et = (EditText)llChild.getChildAt(1);
s = et.getText().toString();
al.add(s);
llChild = (LinearLayout)ll2.getChildAt(2);
et = (EditText)llChild.getChildAt(1);
s = et.getText().toString();
al.add(s);
}
bd = new BackupData();
bd.setBackupData(al);
return bd;
}
private class BackupData{
private ArrayList<String> dataBackup;
void setBackupData(ArrayList<String> al){
dataBackup = al;
}
ArrayList<String> getBackupData(){
return dataBackup;
}
}
}
登録:
投稿 (Atom)