レイアウトやテキストを配置した時、単色では面白くない。 Background に画像を指定する方法が最も簡単ですが、たとえば画面全体に854x480ドットの画像を読み込むとかなり重くなります。
こんな時は、HTML の Background のようにグラデーションやタイルを使いたい。

グラデーション
bmp22.bmp  
startColor から endColor へ 角度指定でグラデーションをする。
  1. 下記のコードを xxxx.xml としてフォルダ drawable に保存する。(Ctrl+S)で保管を忘れないように!
  2. LinearLayout、TextView、Button などの Background に先ほどの xxxx.xml を指定する。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#FFFFFFFF"
android:endColor="#FF000000"
android:angle="270" />
</shape>


●色の指定は、start と end を指定できます。上2桁は透明度、下6桁は色(16進数)

android:startColor="#FFFFFFFF"
android:endColor="#FF000000"

●角度は、45°単位で指定可能。※45°以外にすると描画がされない。

android:angle="270"

タイル

やり方は上記のグラデーションと同じ、指定の画像を上下、左右に同じ画像をタイル状に描画する。

  1. まず、1枚の画像を drawable に用意する。(下記では tile.png)
  2. 下記のコードを yyyy.xml  としてフォルダ drawable  に保存する。
  3. LinearLayout、TextView、Button などの Background に先ほどの yyyy.xml を指定する。

<?xml version="1.0" encoding="utf-8"?> 
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/tile"
android:antialias="true"
android:dither="false"
android:filter="false"
android:gravity="fill_horizontal|top"
android:tileMode="mirror" />


繰り返しの設定

android:tileMode

  • disabled  ビットマップをタイル化しません。これがデフォルトの値です。
  • clamp     オリジナルの境界を超えて描画された場合に端の色で反復します。
  • repeat    イメージを水平と垂直に繰り返します。
  • mirror    イメージを水平と垂直に繰り返し、隣り合うイメージが常に繋ぎ合うように鏡像に替えます。
●配置の設定 (全ての説明は無理なので、実際に色々試してみてください)

android:gravity

  • top                      オブジェクトをコンテナの上端に置き、そのサイズは変更しません。
  • bottom               オブジェクトをコンテナの下端に置き、そのサイズは変更しません。
  • left                      オブジェクトをコンテナの左端に置き、そのサイズは変更しません。
  • right                   オブジェクトをコンテナの右端に置き、そのサイズは変更しません。
  • center_vertical オブジェクトをコンテナの垂直方向の中心に配置し、そのサイズは変更しません。
  • fill_vertical         オブジェクトのサイズが必要に応じ垂直方向に増えることで、そのコンテナを埋め尽くします。
  • center_horizontal オブジェクトをコンテナの水平方向の中心に配置し、そのサイズは変更しません。
  • fill_horizontal    オブジェクトのサイズが必要に応じ水平方向に増えることで、そのコンテナを埋め尽くします。
  • center                オブジェクトをコンテナの垂直軸と方向軸両方の中心に配置し、そのサイズは変更しません。
  • fill                       オブジェクトのサイズが必要に応じ水平方向と垂直方向に増えることで、コンテナを埋め尽くします。これがデフォルトです。
  • clip_vertical      追加のオプションで、子の要素の上端かつ ( または ) 下端がそのコンテナの境界で切り抜かれるように設定することができます。切り抜きは垂直方向の gravity に基づいて行われます。つまり、gravity が top では下端が切り抜かれ、gravity が bottom では上端が切り抜かれ、どちらでもなければ上下両端が切り抜かれます。
  • clip_horizontal  追加のオプションで、子の要素の左端かつ ( または ) 左端がそのコンテナの境界で切り抜かれるように設定することができます。切り抜きは水平方向の gravity に基づいて行われます。つまり、gravity が left では右端が切り抜かれ、gravity が right であれば左端が切り抜かれ、どちらでもなければ左右両端が切り抜かれます。
 
サンプルはこちらで。Test.lzh 



onTouchによる画像の移動

| コメント(0)
画面をタッチして画像を移動するには、Bitmap や SurfaceView を使って少しややこしいのですが、 MotionEvent を使った簡単な方法を教えてもらったので、公開します。

main.xml に view1 を1個用意してください。 test20.bmp
package net.test;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
 
 
public class FrameMoveActivity extends Activity
          implements OnTouchListener {
    private View move_view1;
     int currentX;   //Viewの左辺座標:X軸
 
    int currentY;   //Viewの上辺座標:Y軸
    int offsetX;    //画面タッチ位置の座標:X軸
    int offsetY;    //画面タッチ位置の座標:Y軸
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        move_view1 = findViewById(R.id.view1);        
        //リスナーの設定
        move_view1.setOnTouchListener(this);
     }
 
    @Override
    public boolean onTouch(View view, MotionEvent event) {
 
        int x = (int) event.getRawX();
        int y = (int) event.getRawY();
 
        switch(event.getAction()) {
 
        case MotionEvent.ACTION_MOVE:
            int diffX = offsetX - x;
            int diffY = offsetY - y;
 
            currentX -= diffX;
            currentY -= diffY;
            //画像の移動
            view.layout(currentX, currentY, currentX + view.getWidth(),
                                       currentY + view.getHeight());
            offsetX = x;
            offsetY = y;
            break;
           
        case MotionEvent.ACTION_DOWN:
            //x,yセット
            currentX = view.getLeft();
            currentY = view.getTop();
            offsetX = x;
            offsetY = y;
            break;
           
        case MotionEvent.ACTION_UP:
            break;
        }
        return true;
    }
}

とても簡単に移動が行えた。ちょっとしたトランプゲームなら応用できそうだ。
で、少し変形してサンプルを作ってみた。

詳しくは続きで。。。
 

時間の表示

| コメント(1)

アンドロイドで時間を計測するために時間の取得を作ってみた。test15.bmp

以外にあっさり、時間の計算ができました。

1.現在時間を得る方法。(ミリ単位で可能)

time =System.currentTimeMillis();

2.フォーマットして表示する方法

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS");
textView.setText(sdf.format(time));

3.時間の計算(時間の型はLong型です)

time = endTime - startTime

※timeの値は、1/1000秒が単位となる。(最大24h)
 3時間2分5秒なら time=( (3*60*60)+(2*60+5) )*1000 = (10 925 000)となる。

※表示は、ミリ秒単位ですが、onClick  がスレッドで動いているので1/1000まで完全に正確ではありません。
 onClick  がハードウェア の割り込み発生ではなくソフトウェアで動いているので。

 

簡単なプログラムを作ってみた。Start から Stop ボタンの時間差を表示します。

button(button) / TextView(textView) 各1個をmain.xml に用意

 

public class TestTime extends Activity implements OnClickListener{
    
    private SimpleDateFormat sdf;
    private Button sButton;
    private long time;
    private long startTime;
    private TextView timeDisp;
    private Boolean sFlag = true;
    private String list="";
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        sdf = new SimpleDateFormat("HH:mm:ss SSS");
        sButton = (Button)findViewById(R.id.button);
        timeDisp= (TextView)findViewById(R.id.textView);
        sButton.setOnClickListener(this);
        sButton.setText("START");
    }
 
    @Override
    public void onClick(View v) {
        time = System.currentTimeMillis();
        if (v.getId() == R.id.button) {
            if (sFlag) {
                list=list + "Start=" + sdf.format(time);
                timeDisp.setText(list);
                startTime = time;
                sFlag = !sFlag;
                sButton.setText("STOP");
            }else {
                list=list + "  Stop= " + sdf.format(time) + "\n";
                list=list + "  (Lap= " + sdf.format(time - startTime) + ")\n";
                timeDisp.setText(list);
                sFlag = !sFlag;
                sButton.setText("START");
            }
        }
    }
}

 

日付を得るには? 下記の方法があります。
 

SimpleDateFormat  sdf = new SimpleDateFormat("yyyy'年'MM'月'dd'日 'hh'時'mm'分'ss'秒'"); 
Date  date = new Date();
Log.d("date : ", sdf.format(date));

 

これでは、つまらないのでストップウォッチを作ってみた。「続き」にUPしました。

XMLとAndroidの連携

| コメント(0)

 前回、main.xmlでレイアウトを作成した。簡単なプログラムを作って、androidへのレイアウト取り込みを考えてみた。

 基本的には、下記の順になる。(main.xmlにはボタンを2個配置してある)

public class MainActivity extends Activity implements OnClickListener {
    private Button btn1;
    private Button btn2;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //オブジェクト取得   
        btn1 = (Button) findViewById(R.id.btn1);
        btn2 = (Button) findViewById(R.id.btn2);
        //リスナーセット
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
    }

    public void onClick(View v) {
        //押されたボタンによって分岐する
        switch(v.getId()) {
            case R.id.btn1:
                //処理1
                break;
            case R.id.btn2:
                //処理2
                break;
        }      
     }
}

上記の場合、ボタンは2個ですが、ボタンがもっと多くあればどうするか?

id を  for 文で割り当てれば間単になります。

①まず、フィールドにボタンの数だけIDを記述。
    int[] contentR={R.id.btn1,R.id.btn2,R.id.btn3,R.id.btn4,R.id.btn5,R.id.btn6,R.id.btn7};
② onCreate にfor文でidの設定をする。
      for (int i=0;i<contentR.length;i++) {  
           button = (Button) findViewById(contentR[i]);
     button.setId(i);
           button.setOnClickListener(this);
      }

さらに多くのボタンがあればどうする?詳しくは 下の 続きを読む で。

XMLを使う

| コメント(0)

 android 画面でボタンやテキストを配置するならプログラム本体で記述するよりも、main.xml に記述したほうがすっきりする。

無題.pngと、言うことで早速 main.xml をクリックしてみた。あれやこれや使っているうちに最も作業しやすいEclipseの表示にたどり着いた。

右記では画面が小さいので見にくいが、下側にプロパティー、右側にアウトラインを配置するとベストだと思う。

 配置するには、ウィンドウコマンドの「ビューの表示」または部品を右クリックして「表示」から。場所が違ったっ場合は右や下にドラッグしよう。非表示にする場合はXではなく、縮小で表示を消しましょう。 

作業のコツ。

1- 青の三角部分のバージョンは「android3.0」にしておくとプロパティで日本語が使える。他はなぜか使えない。

2- 複雑な配置の場合、パーツを中央の擬似画面ではなく、アウトラインにドラッグすると思い通りの場所に配置ができます。

3- レイアウト部品を選択状態にする場合、アウトラインのパーツをクリックすると簡単に選択できる。

4- まとめてプロパティを変更する場合は、Shiftキーを押しながら複数の選択後、プロパティを変えると一気に変更できます。

 

button.bmp

実際にプログラムでXMLを取り込むには、

フィールドに

   private Button btn1;

Classに

   setContentView(R.layout.main);

   btn1=(Button)findViewById(R.id.button1);

を記入するだけ。

この時、注意点はXMlを変更後は必ず、Ctrl+Sの 「保管」を実行すること。忘れるとつまらぬエラーに引っかかりますよ! 



問題 main.xml に右上のようなボタン配置を作ってみよう。

Draw 9-patch の注意点

| コメント(0)
こちらが実行時の画像   9-patchの設定
test13.bmp
 Draw 9-patch を使ってボタンを描画しているとボタンに貼り付けたText文字が欠けているのに気付いた。(Test1のボタン参照)

 パディング(内側の余白)を設定したわけでもないのに、上に余白が設けられている。

 で、上下の9-patchの設定は同じにして、左右で各種パターンを実験してみた。(Test1~4)
 
 2は左右に大きく取っているので期待通りだが、3と4は大きな違いが出た。見ての通り、1のような設定は間違いで、4のように右側に9-patchの設定を長くしないとダメなようだ。

 上下(Test5&6)も調べると、下側の設定は長くしないとダメなようだ。

バグのような気がするが、いつも右と下のラインは大きく引く必要がある。(やっぱりバグだろう!)




<<神戸でHP作成&個人レッスンなら http://petafield.com まで>>

Draw 9-patchを使う

| コメント(0)
android には9-patch という画像フォーマットが用意されている。これは、パーツを9つの部位に分け、拡大してもきれいに表示されるというものらしい。解像度が色々あるandroidの機種で、機種別画像を用意せず、一つの画像で使いまわしでき、便利そうだ。ただ、ボタンなどのように背景画像が無いものにしか使えない。その仕組みを理解してから使うべきだ。

まずは使ってみよう。button.gif

anndroid をインストールしたフォルダandroid-sdk-windows の tools の中に draw9patch.bat がある。これをクリックして起動。コマンドは File というだけのシンプルなプログラムだ。
1- まずは、適当なボタン画像(右の画像をコピー保存して使ってください)を中央の ↓ にドラッグする。 
2- 上下左右の端の1ラインにクリックした状態でラインを引く。修正は右クリックでラインが消える。
   
test7.bmp




3- コマンド File のSave9-patch で xx.9.png (ドット 9 ドット png) というファイルネームでandroid の res フォルダの drawble に保存する。 



test10.bmp
※ここで重要なのが、このラインの中だけが拡大されるということだ。
※Show patches にチェックを入れると右のように色分けされる

番号の説明。。。。
①②③④の部分は拡大されない。
⑤⑥は横方向のみ拡大れる
⑦⑧は縦方向のみ拡大される
⑨は縦、横に拡大される

つまり、上下左右の端部分は見た目で1:1の比率なのできれいということである。逆に言えば、⑨の部分のみ拡大される。つまり、⑨に模様入ったボタンは無理だということだ。

しかし、ラインの取り方の工夫次第で、模様の入ったものでもきれいに表示できる。
下記の場合、模様の無い2か所の部分を設定して拡大するようにすれば、中央に光のシルバーラインが入った画像がきれいに表示できる。
最初に「ボタンなどのように背景がないものしか使えない」と言ったが、⑨の部分をどこに取るかでかなり応用ができそうだ。


test11.bmptest12.bmp



ちなみに、最初のボタン画像はhttp://box.aflat.com/buttonmaker/で簡単に作ることができる。お勧めサイトだ。

<<神戸でHP作成&個人レッスンなら http://petafield.com まで>>

TableLayout で電卓を作ろう

| コメント(0)
参考書ではLinearLayoutでのボタン説明であった。ボタンが一直線に並ぶだけなので、
TableLayout に挑戦してみた。
test4.bmp
使い方は、layout の中に row を作り、その中にbutton を一列分配置し、
続いて 作りたい行列分だけ繰り返す。サンプルはforの2重ループを使った
4x4のボタン配置です。

//テーブルレイアウト
public class Test extends Activity {
    private final static int WC=TableLayout.LayoutParams.WRAP_CONTENT;
    private final static int FP=TableLayout.LayoutParams.FILL_PARENT;

    //アプリの初期化
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        //レイアウトの生成
        TableLayout layout=new TableLayout(this);
        layout.setBackgroundColor(Color.WHITE);
        layout.setGravity(Gravity.CENTER);//中央寄せ
        setContentView(layout);
        
        for (int j=0;j<4;j++) {
            //行の生成
            TableRow row=new TableRow(this);
            row.setLayoutParams(new TableLayout.LayoutParams(FP,WC));
            row.setGravity(Gravity.CENTER);//中央寄せ
            layout.addView(row);
            
            //要素の追加
            for (int i=0;i<4;i++) {
                Button button=new Button(this);
                button.setText("("+i+","+j+")");
                row.addView(button);
            }
        }
    } 
}

しかし、これだとボタンのテキストを自由に入れられない。そこでテキストを配列で
用意し、配列の要素数だけボタンを作れるように改造した。

//テーブルレイアウト
public class Test extends Activity {
    private final static int WC=TableLayout.LayoutParams.WRAP_CONTENT;
    private final static int FP=TableLayout.LayoutParams.FILL_PARENT;

    //アプリの初期化
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        
        String[] content={"A","N","D","R","O","I","D","!","test","Button","!"};
        
test5.bmp
        //レイアウトの生成
        TableLayout layout=new TableLayout(this);
        layout.setBackgroundColor(Color.WHITE);
        layout.setGravity(Gravity.CENTER);//中央寄せ
        setContentView(layout);
        TableRow row = null;
        
        for (int j=0;j<content.length;j++) {
            //行の生成
         if(j==0 || j%4==0) {
        row=new TableRow(this);
           row.setLayoutParams(new TableLayout.LayoutParams(FP,WC));
           row.setGravity(Gravity.CENTER);//中央寄せ
           layout.addView(row);
       }
            //要素の追加
            Button button=new Button(this);
            button.setText(content[j]);
            row.addView(button,new TableRow.LayoutParams(50, 50));
        }
   } 
}
 
%4 の4を変えると1行のボタン数が変わる。また、配列contentの要素を書きたすだけで
ボタンが簡単に変更出来る。

最後に電卓に挑戦だ! プログラムはこの下の「続きを読む」をクリック

SDカードの動画を再生する

| コメント(0)
まず、SDカードをエミュレータに増設する必要があります。test1.bmp
手順
1 - Elipseの[ウィンドウ]コマンドから[Android SDK and AVD Manager]を起動。
2 - [新規]をクリック。
3 - 右記のように設定。[名前]は適当に、[ターゲット]は自分の環境に合わす。
4 - カードサイズを入れて下の[新規]をクリック。SD Card support=yesを確認
5 - [Create AVD] をクリック。

Snapshot は良く分かりませんが、エミュレータの起動が早くなるらしいです。

SDカードにファイルをUPしましょう。
手順
1 - エミュレータを起動。起動した状態でないとSDカードは見えません。
2 - Elipseの[ウィンドウ]コマンドから[パースペクティブを開く][DDMS]を起動。
3 - [ファイルエクスプローラ]をクリック。
4 - sdcard フォルダにファイルをドラッグ&ドロップにてコピー。

アクセスの仕方
videoView.setVideoPath(Environment.getExternalStorageDirectory().getPath() 
                   + "/" + "ファイル名");

サンプル
     (sample.mp4をSDカードに用意してください)
test3.bmp
public class SdCard extends Activity {
    @Override
    public void onCreate( Bundle icicle ) {
        super.onCreate( icicle );
        requestWindowFeature(Window.FEATURE_NO_TITLE);
 
        LinearLayout layout=new LinearLayout(this);
        layout.setBackgroundColor(Color.rgb(255,187,255));
        layout.setGravity(Gravity.CENTER);//中央寄せ
        setContentView(layout);
 
        TextView textView=new TextView(this);
        
        VideoView videoView=new VideoView(this);
videoView.requestFocus();
    //下のコメントを外すとじゃまなコントローラが表示される
    //videoView.setMediaController(new MediaController(this));
layout.addView(videoView);
String file="/sample.mp4";
   
   //動画の再生(メモリカードから再生)    
            try {
         String status = Environment.getExternalStorageState();
     //SDカードがあるかチェック
         if (status.equals(Environment.MEDIA_MOUNTED)) {
     videoView.setVideoPath(Environment.getExternalStorageDirectory().getPath() + file); 
     //自動で再生スタート
     videoView.start();
     }
     else {
     textView.setText("SD CARD がありません");
     }
           }catch (Exception e){
           }
     }
}


<<神戸でHP作成&個人レッスンなら http://petafield.com まで>>
画像ファイルや動画ファイルの保存する場所は、決められているようだ。test.bmp

        保存フォルダ   使用できる拡張子 
画像    drawble - PNG GIF JPEG
動画   raw        - MP4 3GPP
音楽   raw        - MP3

 (尚、 raw フォルダ は初めは無いのでresの下に新規フォルダを作る必要あり)

それぞれの形式に保存。または変換してから各フォルダに保存。
 
また、これらのファイルはR.javaで管理されており、(それぞれの実アドレスが格納されている)
プログラムの中ではファイル名を接記述すのではなく、genフォルダ下のRクラスのフィールドを
呼び出す形を取ってる。
具体的には icon.png を描きたい場合、R.drawable.iconという変数を記述する。尚、変数は、
実アドレスが格納されているので int型となる。
例)
Bitmap bitmap=BitmapFactory.decodeResource(
               getResources(),R.drawable.icon)
imageView.setImageBitmap(bitmap);
今までの失敗。。。。。。(^_^;)
1 - icon.png を削除すると実行しても立ち上がらないよ。
 
2 - ファイル名は、小文字とアンダーバーのみ使用可。大文字はエラーだよ。
 
3 - 動画をコンバート(MPEG2→MPEG4など)する場合は、アンドロイド用のフォーマット出力
   があればそれを選ぶ。なければフリーソフトを探そう。h264のコーディックがお勧め。

4 - また、最近のアンドロイド画面は約800ドットのハイビジョン対応できれいですが、
      ファイルサイズが大きくなりすぎます。ビットレートをいろいろ試して妥協できる最小レート
  で変換ましょう。ビットレートの違いによるサンプルをUPしました。
  動きある物なら600~300kb/s。アニメなどなら300~100kb/s 位でしょう。

<<神戸でHP作成&個人レッスンなら http://petafield.com まで>>

android Market

calc.jpg
  マーケットに出品中!!
電卓が完成しました。メモリー計算、定数計算、レート計算など通常の計算だけでなく、 AC(オールクリア)が押されるまで、計算結果がリストとして表示されます。
そして、色を6色用意いたしましたので、あなたの好みの色を設定してください。
詳しくは こちらをクリック下さい

2012年1月14日

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31