setVisibility & getVisibility

Posted by muchag | Android |
初回投稿:2011-04-17 (日) 22:29:19 | 最終更新:2011-04-17 (日) 22:32:11

UI の表示・非表示を切り替えるメソッド。

Android Developers:View setVisibility & getVisibility

スクリプト
  1. Button button = (Button) findViewById(R.id.button);
  2.  
  3. // 表示する場合
  4. button.setVisibility(View.VISIBLE);
  5.  
  6. // 非表示にする場合(見えないけど、ボタン分のスペース空き)
  7. button.setVisibility(View.INVISIBLE);
  8.  
  9. // 非表示にする場合(ボタン分のスペース詰め)
  10. button.setVisibility(View.GONE);
  11.  
  12. // 値を取得する場合
  13. if (button.getVisibility == View.VISIBLE) {
  14. }
  15. else if (button.getVisibility == View.INVISIBLE) {
  16. }
  17. else if (button.getVisibility == View.GONE) {
  18. }

 

XML
  1. <!-- 表示 -->
  2. <Button android:visibility="visible" />
  3.  
  4. <!-- 非表示(ボタン分のスペース空き) -->
  5. <Button android:visibility="invisible" />
  6.  
  7. <!-- 非表示(ボタン分のスペース詰め) -->
  8. <Button android:visibility="gone" />

Android Developers:View android:visibility

Posted by muchag | Android |
初回投稿:2011-04-17 (日) 22:29:19 | 最終更新:2011-04-17 (日) 22:32:11

ディレクトリ構成

Posted by muchag | Android |
初回投稿:2011-04-17 (日) 0:50:31 | 最終更新:2011-07-06 (水) 16:40:15

まだまだ理解できない
Android プロジェクトのディレクトリ構成。

デフォルト

[ファイル]-[新規]-[プロジェクト] から新しくプロジェクトを作成すると
左のようなフォルダ構成になっている。
新規プロジェクトの立ち上げ

 

src/

.java ファイルの格納場所。
パッケージ名が上位にあるところを見ると
Flex のときのようにパッケージを複数配置できるのかしら。
 

gen/

R.java の格納場所。

R.java には、リソースファイル群に付加した ID の一覧が書かれている。
コンパイル時?に自動的に書き加えられていく。
 

assets/

テキストファイルなどの自作ファイルの置き場所・・・らしい。

現時点ではまだまだ不明。
res/raw ディレクトリとの差異も不明。
 

res/

リソース格納場所。
Android Developers:Application Resources
Android Developers:Resource Types
 

res/drawable/

Android Developers:Providing Resources Grouping Resource Types
Android Developers:Drawable Resources
 
.png, .jpg, .gif などのビットマップファイルまたは XML ファイル置き場。

  • Bitmap files
  • Nine-Patches (re-sizable bitmaps)
  • State lists
  • Shapes
  • Animation drawables (Frame Animation)
  • Other drawables

drawable フォルダは、端末の Density ( dpi ) の判別してくれる。

しかし、Android OS のヴァージョン( API Level )によって異なる。
Android Developers:Supporting Multiple Screens

Android 1.5 (API Level 3)以前

drawable (160dpi 端末)
 

Android 1.6 (API Level 4)以降

drawable-ldpi (120dpi 端末)
drawable-mdpi (160dpi 端末)
drawable-hdpi (240dpi 端末)
drawable-nodpi (端末に対応するためにリサイズして欲しくないファイルの置き場)
 

Android 2.2 (API Level 8)以降

rawable-xhdpi (320dpi 端末)
 

Android 2.3 (API Level 9)以降

xlargeScreen に対応
 

<supports-screens>

AndroidManifest.xml に設定を行うことで
マーケットに端末でアクセスした場合に
当該端末が対応しているか否かを判別し
表示されるかどうか決まるらしい。

Android 1.6 以降ではデフォルトで全部 true だそうな。

  1. <supports-screens
  2.     android:resizeable=["true" | "false"]
  3.     android:smallScreens=["true" | "false"]
  4.     android:normalScreens=["true" | "false"]
  5.     android:largeScreens=["true" | "false"]
  6.     android:xlargeScreens=["true" | "false"]
  7.     android:anyDensity=["true" | "false"] />

Android Developers:<supports-screens>

単位 も参考にせよ。
 

識別子

また、res/drawable/ を res/drawable-ja/ とすることで、
端末に日本語設定がされているときに優先的にこちらを読ませることもできる。
詳しくは、アプリの多言語対応リソースファイルのネーミング
 

res/layout/

アクティビティのレイアウト XML ファイル置き場。
 

res/values/

Android Developers:Providing Resources Grouping Resource Types

以上のような、各種設定 XML ファイル置き場。
 

その他の決められたディレクトリ

Android Developers:Providing Resources Grouping Resource Types
 

res/anim/

トゥウィーンアニメーションを定義した XML ファイル置き場。
Android Developers:Animation Resources
 

res/color/

カラーステートリストを定義した XML ファイル置き場。
Android Developers:Color State List Resource
 

res/menu/

オプションメニュー、コンテキストメニュー、サブメニューなどの
アプリケーションメニューを定義した XML ファイル置き場。
Android Developers:Menu Resource
 

res/raw/

音楽データや画像データなどの自由なファイルの置き場。
コンパイルせずにアプリケーションに組み込みたい場合に利用。
 

res/xml/

独自の XML ファイル置き場。
あれこれサイトを見て回るとウィジェットなどを含む
アプリ設定画面に用いられることが多いようだ。
 

assets/ と res/raw/ の差異

参考サイト元にまとめてみると
 

assets/
  • アプリからの保存可
  • ファイル名制限なし
  • リソース ID なし
  • ディレクトリ管理あり(配下にフォルダを設置できる)
  • URL【file:///android_asset/】でアクセスできる
    (コロンの後ろの / スラッシュは3本である)

 

assets/hoge.txt
  1. AssetManager as = getResources().getAssets();
  2. InputStream stream_in = as.open("hoge.txt");

 

assets/hoge.png
  1. WebView webView = (WebView) findViewById(R.id.web);
  2. String strHtml = "<html><head><title>Test</title></head><body><img src='hoge.png' /></body></html>";
  3. webView.loadDataWithBaseURL("file:///android_asset/", strHtml, "text/html", "utf-8", null);

 

res/raw/
  • アプリからの保存不可
  • ファイル名制限あり([a-z] 英小文字、 _ アンダースコア、. ピリオドのみ)
  • リソース ID あり(R.raw.hoge)
  • ディレクトリ管理なし(配下にフォルダを設置でない)
  • drawable 同様に raw-ja, raw-mdpi などとネーミングすることで
    自動判別機能を利用できる

 

res/raw/hoge.png
  1. Resources resources = this.getResources();  
  2. InputStream inputStream = res.openRawResource(R.raw.hoge);

 
<参考元サイト>
Y05_net’s blog:Androidアプリにおけるassetsフォルダとres/rawの使い分け
整理できない底辺プログラマのメモブログ:任意データの置き場所は、/assets or /res/raw?
tappli blog:[Android] assetsのファイルを使う

Posted by muchag | Android |
初回投稿:2011-04-17 (日) 0:50:31 | 最終更新:2011-07-06 (水) 16:40:15

アクティビティに画像を配置

Posted by muchag | Android |
初回投稿:2011-04-17 (日) 0:02:09 | 最終更新:2011-04-17 (日) 22:50:01

SD カードにある画像を
アクティビティに配置しようとして苦労した・・・。

普段 ImageView に画像をセットする場合

res/drawable-hdpi/hoge.png
  1. ImageView imageView = new ImageView();
  2. imageView.setImageResource(R.drawable.hoge);

これでいける。

※ drawable-xxx というフォルダ名称は、
Android OS のヴァージョン(API Level)によってルールがある。
詳しくは、ディレクトリ構成

元々、画像の配置方法は以下の2種類らしい。

  1. リソースファイルを ID にて指定
  2. ビットマップを指定

上の例は1番目の手法なわけだが
これすら画像の保存場所によっては
他にも方法がある。
詳しくは、ディレクトリ構成
 

SD カードの画像を配置

ところが、SD カードの画像を配置しようとすると2番目の方法しかないようで
それには FileInputStream というクラスを利用する。
FileInputStream & FileOutputStream

色々試した結果、以下のスクリプトで成功した。

  1. // ImageView のインスタンスを生成
  2. ImageView imgView = (ImageView) findViewById(R.id.imgView);
  3.  
  4. // File のインスタンスを生成
  5. final File fileImage = new File(Environment.getExternalStorageDirectory().getPath(), "hoge.jpg");
  6.  
  7. // FileInputStream のインスタンスを生成
  8. FileInputStream fisImage = new FileInputStream(fileImage);
  9.  
  10. // Bitmap のインスタンスを生成
  11. Bitmap bmpImage = BitmapFactory.decodeStream(fisImage);
  12.  
  13. // ImageView に画像を設定
  14. imgView.setImageBitmap(bmpImage);

尚、5行目について

  1. // getPath メソッドがあってもなくてもOK
  2. final File fileImage = new File(Environment.getExternalStorageDirectory().getPath(), "hoge.jpg");
  3. final File fileImage = new File(Environment.getExternalStorageDirectory(), "hoge.jpg");
  4.  
  5. // sdcard/ フォルダに勝手なフォルダを配置し
  6. // その中に画像ファイルを置いてもOK
  7. // フォルダ名に大文字を用いてもOK
  8. final File fileImage = new File(Environment.getExternalStorageDirectory().getPath(), "hoge.jpg");
  9. final File fileImage = new File(Environment.getExternalStorageDirectory().getPath(), "folderSample/hoge.jpg");

 
参考元サイト:yamaTum 画像の保存→表示 – TAKのAndroid開発日記

Posted by muchag | Android |
初回投稿:2011-04-17 (日) 0:02:09 | 最終更新:2011-04-17 (日) 22:50:01

Resources

Posted by muchag | Android |
初回投稿:2011-04-15 (金) 23:31:20 | 最終更新:2011-07-06 (水) 17:11:05

スクリプトを記述していると、リソースに指定したものを使いたくなるときがある。
Resources は、そんなときに利用できるクラス。

Android Developers:Context Resources

頻度の高い例として

  1. TextView textView = new TextView();
  2. textView.setText(R.string.hoge);

なんていうのがあるが、R.string.hoge というのは実は数値でしかないので
setText メソッドに直接使うと変換してくれるが

  1. TextView textView = new TextView();
  2. textView.setText(R.string.hoge + R.string.hoi);

なんてしてみると楽しいことが起きる。

文字列のつもりで連結させようとしても無理なのだ。
(私が実際にやってしまったのはバレバレ) 🙄

世の中そんなに甘いわけはなく
こういう場合に利用できるのが Resources クラス。

  1. Resources resources = getResources();
  2. String myHoge = resources.getString(R.string.hoge);

Android Developers:Context getResources

このようにすることで、実際の文字列を取得できるので
後はいつものように処理できる。

Resources クラスのメソッドは、もちろん getString だけではない。
型に合わせて色々あるので、上記ページを参考に。
 

getIdentifier

getIdentifier メソッドはリソース名を動的に設定したい場合に有効。

public int getIdentifier (String name, String defType, String defPackage)

Android Developers:Resources getIdentifier

第1引数:リソース名文字列
第2引数:リソースタイプ文字列
第3引数:パッケージ名文字列
 

静的取得

リソースを取得したい場合、私は以下のようにしている。

  1. Resources resources = getResources();
  2. String myHoge = resources.getString(R.string.hoge);
  3.  
  4. または
  5.  
  6. String myHoge = getResources().getString(R.string.hoge);

 
ところが、hoge の部分を入れ替えたいときがあり
手動(入れ替え分コードを記述するの)では困ることがある。

そんなときは、getIdentifier メソッドの出番。
 

動的取得

R.string.hoge
という記述は int 型のオブジェクト。

だから
R.string.hoge0
R.string.hoge1
R.string.hoge2

これらを
R.string.hoge + i
とか
R.string.”hoge” + i
のように記述したくなるがこれはできない。

そこで
for (int i = 0; i < 3; i++) { // リソース ID を取得 int myInt = getResources().getIdentifier("hoge" + i, "string", getPackageName() ); // 取得したリソース ID を利用して文字列を取得 String myHoge = getResources().getString(myInt); // 取得した文字列をログへ書き出し Log.i("Test", myHoge ); }[/android] このようにしてやることで、動的にリソース名を設定できる。

Posted by muchag | Android |
初回投稿:2011-04-15 (金) 23:31:20 | 最終更新:2011-07-06 (水) 17:11:05

ListActivity

Posted by muchag | Android |
初回投稿:2011-04-15 (金) 17:51:19 | 最終更新:2011-07-07 (木) 19:52:20

ListActivityActivity クラスのサブクラスである。

その名の通り、ListView を配置したいアクティビティに利用する。

Android Developers:ListActivity

概要

ListActivity クラスは、ListView 表示用のため
ListView を利用する際に様々な特典がある。
 

レイアウト XML
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3.     xmlns:android="http://schemas.android.com/apk/res/android">
  4.  
  5.     <ListView android:id="@+id/android:list" />
  6.     <TextView android:id="@+id/android:empty"
  7.             android:text="@string/nodata" />
  8. </RelativeLayout>

ListActivity で ListView を利用するには
5,6行目のように、ListView と TextView をセットで配置し
ID を上記のように設定することで
データがあるときは ListView を、データがないときは TextView を
自動的に配置してくれる。
 

ListView の取得

普段スクリプトにてビューを取得する場合は

  1. ListView listview = (ListView) findViewById(R.id.list);

のように記述するが、ListActivity では

  1. ListView listview = getListView();

とするだけでよい。

もっとも ID を前述のように記述しているので
ID から取得するのは不可能だが。
 

イベント

ListActivity には、デフォルトで onListItemClick メソッドが用意されているので
インターフェイスを実装しなくても、そのまま利用できる。

  1. public class ListActivityTest extends ListActivity {
  2.  
  3.     /* 省略 */
  4.  
  5.     @Override
  6.     protected void onListItemClick(ListView listView, View view, int position, long id) {
  7.         super.onListItemClick(listView, view, position, id);
  8.  
  9.         /* 処理 */
  10.     }
  11. }

Android Developers:ListActivity onListItemClick

しかし残念ながら onListItemLongClick や onListItemSelected というメソッドは存在しないようだ。

もしこれらを利用したいのであれば、いつも通り
実装してリスナーの登録をしてやればよい。

  1. public class ListActivityTest extends ListActivity implements AdapterView.OnItemLongClickListener {
  2.  
  3.      @Override
  4.     public void onCreate(Bundle savedInstanceState) {
  5.             super.onCreate(savedInstanceState);
  6.  
  7.         ListView listview = getListView();
  8.         listview.setOnItemLongClickListener(this);
  9.     }
  10.  
  11.     @Override
  12.     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
  13.  
  14.         /* 処理 */
  15.     }
  16. }

ちなみに、OnItemClickListener を登録すると onListItemClick メソッドは無視される
 

ListView のカスタマイズ

mucchinのAndroid戦記:ListViewのカスタマイズ方法
こちらを参考に、というか丸ごとパクらせていただいて実現。
 

データの取得&設定
Sample.java
  1. @Override
  2. public void onCreate(Bundle savedInstanceState) {
  3.  
  4.     super.onCreate(savedInstanceState);
  5.  
  6.     List<ItemBean> myProfile = new ArrayList<ItemBean>();
  7.  
  8.     /* DB 部分省略 cursor に取得済みとする */
  9.     if (cursor.getCount() != 0) {
  10.  
  11.         boolean isEof = cursor.moveToFirst();
  12.         while (isEof) {
  13.  
  14.             ItemBean ibProfile = new ItemBean();
  15.             ibProfile.setId( cursor.getInt( cursor.getColumnIndex("_id") ) );
  16.             ibProfile.setName( cursor.getString( cursor.getColumnIndex("name") ) );
  17.             ibProfile.setBirth( cursor.getString( cursor.getColumnIndex("birth") ) );
  18.             myProfile.add(ibProfile);
  19.  
  20.             isEof = cursor.moveToNext();
  21.         }
  22.  
  23.         ListAdapter adapter = new ListAdapter(getApplicationContext(), myProfile);
  24.         setListAdapter(adapter);
  25.  
  26.         ListView list = getListView(); // ListActivity なので、これでレイアウト上の ListView を取得できる
  27.         list.setOnItemClickListener(this); //リスト項目をタップしたときのリスナー
  28.     }
  29. }

 

ListAdapter クラス
Sample.java
  1. class ListAdapter extends ArrayAdapter<ItemBean>
  2. {
  3.     private LayoutInflater mInflater;
  4.     private TextView txtName;
  5.     private TextView txtBirth;
  6.  
  7.     public ListAdapter(Context context, List<ItemBean> objects) {
  8.  
  9.         super(context, 0, objects);
  10.         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  11.     }
  12.  
  13.     public View getView(final int position, View convertView, ViewGroup parent) {
  14.  
  15.         if (convertView == null) {
  16.  
  17.             convertView = mInflater.inflate(R.layout.list_profile, null);
  18.         }
  19.  
  20.         final ItemBean item = this.getItem(position);
  21.  
  22.         if(item != null){
  23.  
  24.             txtName = (TextView)convertView.findViewById(R.id.txtName);
  25.             txtName.setText(item.getName());
  26.  
  27.             txtBirth = (TextView)convertView.findViewById(R.id.txtBirth);
  28.             txtBirth.setText(item.getBirth());
  29.         }
  30.  
  31.         return convertView;
  32.     }
  33. }

 

イベント処理
Sample.java
  1. @Override
  2. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  3.  
  4.     ListView listView = (ListView) parent;
  5.     ListAdapter adapter = (ListAdapter) listView.getAdapter();
  6.  
  7.     final ItemBean item = adapter.getItem(position);
  8.     int id = item.getId();
  9.     String name = item.getName();
  10.     String birth = item.getBirth();
  11. }

 

ItemBean クラス

これが一番嬉しかった!

Java には連想配列というものがないそうで
連想配列に慣れてきた私には
このクラスはとっても理解しやすかった。

ItemBean.java
  1. public class ItemBean {
  2.  
  3.     private int intId = 0;
  4.     private String strName = "";
  5.     private String strBirth = "";
  6.  
  7.     public void setId(int intId) {
  8.         this.intId = intId;
  9.     }
  10.     public int getId() {
  11.         return intId;
  12.     }
  13.  
  14.     public void setName(String strName) {
  15.         this.strName = strName;
  16.     }
  17.     public String getName() {
  18.         return strName;
  19.     }
  20.  
  21.     public void setBirth(String strBirth) {
  22.         this.strBirth = strBirth;
  23.     }
  24.     public String getBirth() {
  25.         return strBirth;
  26.     }
  27. }

 

XML

ListView の各行用の XML ファイル。

list_profile.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3.     xmlns:android="http://schemas.android.com/apk/res/android"
  4.     >
  5.    
  6.     <TextView
  7.         android:id="@+id/txtName"
  8.     />
  9.    
  10.     <TextView
  11.         android:id="@+id/txtBirth"
  12.         android:layout_toRightOf="@+id/txtName"
  13.     />
  14.  
  15. </RelativeLayout>

 
ひとまず無事に取得できたけど
これから少しずつ研究。

Posted by muchag | Android |
初回投稿:2011-04-15 (金) 17:51:19 | 最終更新:2011-07-07 (木) 19:52:20

言語設定を取得

Posted by muchag | Android |
初回投稿:2011-04-14 (木) 2:39:43 | 最終更新:2011-06-03 (金) 12:56:45

Android 端末では
言語設定を行うことができる。
日本語表記

更に、Android アプリケーションでは多言語対応も可能。
アプリの多言語対応

ということは、端末の言語設定を取得する必要も出てくる。

手法が2つあるようだ。
 

手法1

Locale クラスの getDefault メソッドを利用する手法。

Locale.CANADA en_CA
Locale.CANADA_FRENCH fr_CA
Locale.CHINA zh_CN
Locale.CHINESE zh
Locale.ENGLISH en
Locale.FRANCE fr_FR
Locale.FRENCH fr
Locale.GERMAN de
Locale.GERMANY de_DE
Locale.ITALIAN it
Locale.ITALY it_IT
Locale.JAPAN ja_JP
Locale.JAPANESE ja
Locale.KOREA ko_KR
Locale.KOREAN ko
Locale.PRC zh_CN
Locale.ROOT the root locale
Locale.SIMPLIFIED_CHINESE zh_CN
Locale.TAIWAN zh_TW
Locale.TRADITIONAL_CHINESE zh_TW
Locale.UK en_GB
Locale.US en_US

以下のように toString メソッドを用いて文字列として取得できる。

  1. String myLocale = Locale.getDefault().toString();
  2.  
  3. if (myLocale == "ja_JP") {
  4.     // ゴニョゴニョ
  5. }

ところが! この if 文はスルーされる・・・なぜ? 🙄
いつの日か解決する日を夢見て・・・zzz

※2011-06-03 いただいたコメントにより解決。詳細は次の項にて。
 
参考サイトで紹介されていた以下の手法はちゃんと機能した。

  1. if ( Locale.JAPAN.equals(Locale.getDefault() ) {
  2.     // 日本語の処理
  3. } else {
  4.     // 日本語以外の処理
  5. }

 

手法2

getResources().getConfiguration().locale.getLanguage() を利用する手法。

  1. String myLocale = getResources().getConfiguration().locale.getLanguage();
  2.  
  3. if (myLocale == "ja") {
  4.     // ゴニョゴニョ
  5. }

これは toString なしでも文字列変数に代入できるし
デバッグの変数内容を見ると ja になっているのに
やっぱり上記 if 文が機能しない。 🙄

な~ぜ~だろ~なぜだろ~。

2011-06-03 いただいたコメントにより解決。

Java では、比較演算子 ==

  • プリミティブ型 – 値を比較してくれる
  • オブジェクト型 – 型を比較する(同じ型か否か)

ので、オブジェクト型で値を比較したいときは equals を利用すべし。
 
 
参考サイト:日本アンドロイドの会 設定言語の取得について

Posted by muchag | Android |
初回投稿:2011-04-14 (木) 2:39:43 | 最終更新:2011-06-03 (金) 12:56:45

setTag & getTag

Posted by muchag | Android |
初回投稿:2011-04-10 (日) 21:15:17 | 最終更新:2011-04-10 (日) 21:19:49

Button の onClick イベントでは、Button ビューそのものしか渡せないため
その次の処理に必要な引数を渡すことができない。

そこで Flex のときに用いた data プロパティ のようなものがないか
リファレンスをジロジロ見てみた。

あったあった♪ setTag & getTag

リファレンスの英語は今一理解できなかったけど

Tags can also be used to store data within a view ・・・

この部分でピンときてグーグル先生に聞いてみたら、
やっぱり期待した機能のようだった。

void | setTag (Object tag)

とのことなので、まずはオブジェクト作り。

MyObject.java
  1. package com.example.sample;
  2.  
  3. public class MyObject {
  4.    
  5.     public int myInt;
  6. }

 
次にボタンを配置したアクティビティクラスにて

  1. //フィールドにて宣言
  2. private Button myButton;
  3.  
  4. /* 省略 */
  5.  
  6. //情報格納インスタンスを生成
  7. MyObject myObject = new MyObject();
  8. myObject.myInt = 24; //値を格納
  9.  
  10. //ボタンインスタンスの生成
  11. myButton = new Button(this);
  12. //インスタンスの Tag へ情報を格納
  13. myButton.setTag(myObject);
  14. //ボタンインスタンスへリスナーを登録
  15. myButton.setOnClickListener(this);
  16.  
  17. /* 省略 */
  18.  
  19. //ボタンクリックイベントの処理
  20. public void onClick(View view) {
  21.     if (view == myButton) {
  22.             //Button に埋め込んだ情報オブジェクトを取得
  23.             MyObject myObject = (MyObject) myButton.getTag();
  24.             //情報オブジェクトから当該情報を取得
  25.             int myInt = myObject.myInt;
  26.     }
  27. }

見事に情報の受け渡しに成功!

この setTag & getTag メソッドは、Button クラス固有のものではなく
View クラスのものなので、そのサブクラスではどれでも利用可ってことよね?

めでたしめでたし。

Posted by muchag | Android |
初回投稿:2011-04-10 (日) 21:15:17 | 最終更新:2011-04-10 (日) 21:19:49

LogCat にログが表示されない

Posted by muchag | Android |
初回投稿:2011-04-10 (日) 20:16:09 | 最終更新:2011-04-10 (日) 20:16:09

あるとき突然 LogCat の表示が消えた。
困った・・・。

グーグル先生にお伺いを立ててみると
素晴らしい回答を発見。
Kazzzの日記:Logcat Viewにログが表示されない時に試すこと

  1. DDMS パースペクティブを開く
  2. Device ビューにある当該エミュレータをクリック

直った・・・ウソみたい!
クリックした途端に LogCat にログがズラズラと。

Posted by muchag | Android |
初回投稿:2011-04-10 (日) 20:16:09 | 最終更新:2011-04-10 (日) 20:16:09

画面下部に固定配置

Posted by muchag | Android |
初回投稿:2011-04-09 (土) 22:37:19 | 最終更新:2012-01-09 (月) 15:28:35

スマートフォンを片手で操作する人が多い現状
画面下部にナビゲータなりメニューなりを配置することが多いと思う。

実際、各端末メーカーが提供するホーム画面も
画面下部にメニューを移動させた。(とどこかで読んだ)

【環境】
android-sdk_r08-windows
Android DDMS 8.0.1.v201012062107-82219
Android 開発ツール 8.0.1.v201012062107-82219
Android Hierarchy Viewer 8.0.1.v201012062107-82219
ターゲット:Android 1.6

画面上部にもタイトルなり情報なりを表すとすると
画面の基本レイアウトは

  • ヘッダ
  • 本文
  • フッタ

となってくる。

ところが、まんまレイアウトしても
このようになってしまう。

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     >
  7.     <Button
  8.         android:text="Header"
  9.         android:layout_width="fill_parent"
  10.         android:layout_height="wrap_content"
  11.         />
  12.     <TextView
  13.         android:text="Content"
  14.         android:layout_width="wrap_content"
  15.         android:layout_height="wrap_content"
  16.         />
  17.     <Button
  18.         android:text="Footer"
  19.         android:layout_width="fill_parent"
  20.         android:layout_height="wrap_content"
  21.         />
  22. </LinearLayout>

 

手法1:Gravity の利用

そこで私が最初に考えた手法は、
フッタに LinearLayout を採用し
Gravity を設定する手法。
もちろん、LinearLayout である必要はない。何でもOK。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     >
  7.     <Button
  8.         android:text="Header"
  9.         android:layout_width="fill_parent"
  10.         android:layout_height="wrap_content"
  11.         />
  12.     <TextView
  13.         android:text="Content"
  14.         android:layout_width="wrap_content"
  15.         android:layout_height="wrap_content"
  16.         />
  17.  
  18.     <LinearLayout
  19.         android:gravity="bottom"
  20.         android:layout_width="fill_parent"
  21.         android:layout_height="fill_parent"
  22.         >
  23.         <Button
  24.             android:text="Footer"
  25.             android:layout_width="fill_parent"
  26.             android:layout_height="wrap_content"
  27.             />
  28.     </LinearLayout>
  29.  
  30. </LinearLayout>

 
ひゃっほい!
上手くできた♪

と思うも束の間。
本文が長くなると、フッタが画面から追い出されてしまう。

 

手法2:ScrollView の利用

仕方がないので、本文部分を ScrollView で囲んでみた。
が、何故か最下部にフッタがない。

どうやら仕様のようで
以下のサイトに解決策が載っていた。

public static void main:AndroidでScrollViewの下部にボタンなどを配置する方法
 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     >
  7.     <Button
  8.         android:text="Header"
  9.         android:layout_width="fill_parent"
  10.         android:layout_height="wrap_content"
  11.         />
  12.    
  13.     <ScrollView
  14.         android:layout_width="fill_parent"
  15.         android:layout_height="fill_parent"
  16.         android:layout_weight="1"
  17.         >
  18.         <TextView
  19.             android:text="Content"
  20.             android:layout_width="wrap_content"
  21.             android:layout_height="wrap_content"
  22.             />
  23.     </ScrollView>
  24.    
  25.     <Button
  26.         android:text="Footer"
  27.         android:layout_width="fill_parent"
  28.         android:layout_height="wrap_content"
  29.         />
  30.  
  31. </LinearLayout>

16行目 android:layout_weight=”1″ がポイント。
この属性は パーツの均等割り付け でも出てきたけど、今一つかめない。

ちなみに15行目の android:layout_height=”fill_parent” は wrap_content でも同じ結果になった。

同じく ScrollView を用いた手法で別のパターンもあった。
adakoda:[Android] ScrollViewのfillViewportの解説

本文が短いときでも思い通りのレイアウトになった。
wrap_content でもOK。

と書いてはいるが、このシンプルなサンプルでは上手くいったけど
本物の方では上手くいかなかった。

本物では Style を用いて XML ファイルを作成している。
あれこれゴチャゴチャしてミスの見落としがあるのかもしれないが
上手くいかないので、他も当たってみた。
 

手法3:RelativeLayout の利用

日本Androidの会:RelativeLayoutの中にScrollViewを入れる方法
上記ディスカッションに素敵な情報が♪
 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="fill_parent"
  5.     >
  6.     <Button
  7.         android:text="Header"
  8.         android:id="@+id/header"
  9.         android:layout_alignParentTop="true"
  10.         android:layout_width="fill_parent"
  11.         android:layout_height="wrap_content"
  12.         />
  13.    
  14.     <Button
  15.         android:text="Footer"
  16.         android:id="@+id/footer"
  17.         android:layout_alignParentBottom="true"
  18.         android:layout_width="fill_parent"
  19.         android:layout_height="wrap_content"
  20.         />
  21.    
  22.     <ScrollView
  23.         android:layout_below="@id/header"
  24.         android:layout_above="@id/footer"
  25.         android:layout_width="fill_parent"
  26.         android:layout_height="fill_parent"
  27.         >
  28.         <TextView
  29.             android:text="Content"
  30.             android:layout_width="wrap_content"
  31.             android:layout_height="wrap_content"
  32.             />
  33.     </ScrollView>
  34.  
  35. </RelativeLayout>

2行目、ラッパーを RelativeLayout にして
9行目、ヘッダに android:layout_alignParentTop=”true”
17行目、フッタに android:layout_alignParentBottom=”true”
本文 ScrollView に
23行目、android:layout_below=”@id/ヘッダ”
24行目、android:layout_above=”@id/フッタ”

これでバッチリOK!

上記ディスカッションでは

  • ヘッダ、フッタ、本文の順で記述すること(もしかすると取り違えているかも)
  • 23, 24行目の “@id/ヘッダ” は “@+id/ヘッダ” とする必要がないこと
  • 26行目、ScrollView の android:layout_height を fill_parent とすること

の3点が書いてあったが、

  • “@+id/ヘッダ” と記述してもOK
  • “@+id/ヘッダ” と記述すると、ヘッダ、本文、フッタの順で記述してもOK
  • 26行目、ScrollView の android:layout_height が wrap_content でもOK

という実験結果が出た。

Posted by muchag | Android |
初回投稿:2011-04-09 (土) 22:37:19 | 最終更新:2012-01-09 (月) 15:28:35

単位

Posted by muchag | Android |
初回投稿:2011-04-08 (金) 14:25:48 | 最終更新:2011-04-19 (火) 14:01:44

あれこれサイトを見回って
色々なサンプルを見ていると、何か単位があれこれある・・・。

Android Developers:More Resource Types Dimension

種類
dp (=dip, Density-independent Pixels)

160 dpi の画面だと 1 dp = 1 px になる。
画面解像度が上がれば、それに応じて変化するが、必ずしも正比例するわけではない。
 

sp (Scale-independent Pixels)

dp に似た単位だが、ユーザーが設定したフォントサイズによって自動でスケールされる。
(=ユーザーが端末でフォントサイズを変更しているとその影響を受ける、という意味かしら)

フォントサイズを指定する場合には、この単位を使うことを推奨している。
よって、sp で指定したサイズは、画面密度(解像度)とユーザーが設定したフォントサイズに依存する。
 

pt (Points)

スクリーンの物理的サイズに基づいた 1/72 インチ。
 

px (Pixels)

ピクセル。
この単位で測ることは推奨しない。
 

mm (Millimeters)

ミリメートル。
 

in (Inches)

インチ。
 
ザックリ表現すれば
dp (= dip ), sp相対設定
pt, px, mm, in絶対設定

参考元サイト:Y.A.M の 雑記帳 Android Dimension 単位
 

具体的な利用法

 
この先は、下記リンク先ディスカッションを読みながら
公式リファレンスを見ながら個人的にまとめたものであり、
本人も確認はおろか理解もままならない状態です。
もし読み進める場合は、十分注意してください。
また、アドバイスがあればぜひお願いします。

(まぁ、元々私の覚書の精度は怪しいのですが、ここは特によくわかりません)
 
【教えてください】TextView等のテキストサイズについて
こちらで大変参考になるやり取りが行われていた。
上記参考元サイトの管理人さんも参加しておられる。
 

基本方針

レイアウトdpフォントサイズsp
これが基本らしい。

いずれも相対的な設定方法で
要は、例えば 20dp とか 20sp とかすれば
もし 160dpi (mdpi) の画面だったら 20px 分のサイズ(領域)になりますよ~。
画面サイズが異なる場合は、それに合わせて私(OS)が変更してあげますよ~。
ってこと。

ただし、AndroidManifest.xml ファイルにて

  1. <supports-screens android:anyDensity="true" />

としていなければ効力がない。
(Android 1.6 (API Level 4) 以降はデフォルトで true 設定なので特に必要はない・・・?)

android:anyDensity は、端末毎の画面解像度の差異を

  • true ・・・ OS に調整を任せる
  • false ・・・ 自分で調整する(端末毎の設定を作る)

ということだと思うんだけど、
上記参考サイトディスカッションを読んでみると
もしかしたら違うかも・・・。
 

各設定値の単位

私の参考書にもあった
setTextSize(20.0f)
という指定方法。
f ってなんじゃろ・・・と思いながらやってきたけど
f は float だった。

というわけで、参考書などの例では float 値で設定しているが
基本的には

setTextSize メソッドの引数の単位は sp

public void setTextSize (float size)

Android Developers:TextView setTextSize

でも、

setPadding メソッドの引数の単位は px

public void setPadding (int left, int top, int right, int bottom)

Android Developers:View setPadding

 

LayoutParams クラスのコンストラクタ引数も単位は px

public ViewGroup.LayoutParams (int width, int height)

Android Developers:ViewGroup.LayoutParams

 

絶対設定の場所で相対設定を行う

setPadding メソッドのように、引数に絶対設定を要求される場所で
相対設定を利用するには、

res/values/dimens.xml (ファイル名は自由)

にて

  1. <resources>
  2.     <dimen name="padding_left">20dp</dimen>
  3.     <dimen name="padding_top">15dp</dimen>
  4.     <dimen name="padding_right">10dp</dimen>
  5.     <dimen name="padding_bottom">5dp</dimen>
  6. </resources>

のような相対設定を定義するリソースを作成し

  1. Resources res = getResources();
  2. float paddingLeft = res.getDimensionPixelSize(R.dimen.padding_left);
  3. float paddingTop = res.getDimension(R.dimen.padding_top);
  4. float paddingRight = res.getDimension(R.dimen.padding_right);
  5. float paddingBottom = res.getDimension(R.dimen.padding_bottom);
  6. View.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);

というようにして、値を設定してやる。

こうすれば、
getDimension (戻り値 float)メソッド

getDimensionPixelSize (戻り値 int) メソッド
がリソースから値を取得するに当たり
それぞれの相対設定値(例えば 20dp)を絶対設定値に変換する途中で
画像サイズの差異を保管する比例定数を乗算した上で取得してくれる。

public float getDimension (int id)

Android Developers:Resources getDimension

public int getDimensionPixelSize (int id)

Android Developers:Resources getDimensionPixelSize

比例定数は、以下の通り。

  • 120dpi ・・・ 0.75
  • 160dpi ・・・ 1
  • 240dpi ・・・ 1.5

Android Developers:android:anyDensity

getDimension は、float を戻してくれるので
setTextSize などに有効。

getDimensionPixelSize は、int を戻してくれるので
setPadding などに有効。

と、上記ディスカッションを読みながら公式リファレンスを見て
このようにまとめてみたが、
ディスカッションを読み続けると、どうも間違っている気がする・・・。

正解は何なのか、今後のお楽しみということで。 😎
 
各端末の画面解像度およびサイズとどのように対応しているかは
以下の表を見ればわかる。

Low
density
(120),
ldpi
Medium
density
(160),
mdpi
High
density
(240),
hdpi
Extra
high
density
(320),
xhdpi
Small
screen
QVGA
(240×320)
Normal
screen
WQVGA400
(240×400)
WQVGA432
(240×432)
HVGA
(320×480)
WVGA800
(480×800)
WVGA854
(480×854)
Large
screen
WVGA800*
(480×800)
WVGA854*
(480×854)
Extra
Large
screen

* To emulate this configuration, specify a custom density of 160 when creating an AVD that uses a WVGA800 or WVGA854 skin.
Android Developers:Supporting Multiple Screens

Posted by muchag | Android |
初回投稿:2011-04-08 (金) 14:25:48 | 最終更新:2011-04-19 (火) 14:01:44
« 前ページへ次ページへ »