しむしむてるるの日記&雑談 同人誌の進捗やら仕事のあれこれやら書いています。

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
[ --/--/-- --:-- ] スポンサー広告 | TB(-) | CM(-)

Androidでカードを配置する

以前、カードを回転させる処理をしましたが、今回はそのカードを並べます。
並べ方は色々あると思いますが、今回は二人対戦のトランプゲームを想定して、
相手に5枚、自分に5枚、山札1つの形で並べようと思います。

さて、どうやって並べるかですが、今回はLinearLayoutを使って並べてみます。
LinearLayoutはViewを追加していくだけで縦か横の一方向に並べる事が出来るので比較的簡単に奇麗な配置が可能です。
ですが、その前にカードを並べ易くする為にカードを1つのViewにしましょう。
ImageViewのままでも並べる事は出来ますが、のちにカードの1枚1枚を
異なる絵柄(数字とマーク)にする事が予測出来ますので、
早い段階で管理し易い形にまとめてしまいます。
実際にコードにするとこんな感じです。

CardView.java
package jp.sweetsblast.cardturn;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.ImageView;

public class CardView extends ImageView implements AnimationListener, View.OnClickListener{

private int imageNo; // カード番号
private boolean state; // 裏か表か false=裏、true=表

public CardView( Context context, int imageNo){
super(context);

this.imageNo = imageNo;
state = false;
setPadding( 0, 0, 0, 0);
setScaleType(ScaleType.CENTER);
setImage();
setLayoutParams( new LayoutParams( 96, 96));
setScaleType(ScaleType.FIT_XY);
setOnClickListener(this);
}

private void setImage(){
if( !state ){
if( imageNo==-1 ) setImageBitmap( createTalon());
else setImageResource( R.drawable.ura);
}else{
if( imageNo==-1 ) this.setImageBitmap( createTalon());
else setImageResource( R.drawable.omote);
}
}

// 山札のイメージ作成
private Bitmap createTalon(){
Bitmap orgBitmap = BitmapFactory.decodeResource( getContext().getResources(), R.drawable.ura);
int width = orgBitmap.getWidth();
int height = orgBitmap.getHeight();
// 元画像より30px大きなbitmapを作成(4枚を10pxずつずらして重ねるため)
Bitmap bm = Bitmap.createBitmap( width+30, height+30, Config.ARGB_8888);
BitmapDrawable db = new BitmapDrawable(orgBitmap);
// ここでdbに対して描画
Canvas canvas = new Canvas(bm);
// 4枚のカードが重なっているイメージを作成
canvas.drawBitmap( orgBitmap, 0, 0, null);
canvas.drawBitmap( orgBitmap, 10, 10, null);
canvas.drawBitmap( orgBitmap, 20, 20, null);
canvas.drawBitmap( orgBitmap, 30, 30, null);
db.draw(canvas);
return bm;
}

public void onClick( View v) {
// 90°回転
ScaleAnimation scale = new ScaleAnimation( 1.0f, 0.0f, 1.0f, 1.0f, 96f/2, 96f/2);
scale.setAnimationListener(this);
scale.setFillAfter(true);
scale.setFillEnabled(true);
scale.setDuration(500);
scale.setInterpolator( new LinearInterpolator());
startAnimation(scale);
}

public void onAnimationEnd(Animation animation) {
// X方向のサイズが0になって画像が見えない内に画像を変更
state = !state;
setImage();

// もう一度90°回転
ScaleAnimation scale = new ScaleAnimation( 0.0f, 1.0f, 1.0f, 1.0f, 96f/2, 96f/2);
scale.setFillAfter(true);
scale.setFillEnabled(true);
scale.setDuration(500);
scale.setInterpolator( new LinearInterpolator());
startAnimation(scale);
}

public void onAnimationRepeat(Animation animation) {
}

public void onAnimationStart(Animation animation) {
}
}

このViewの中で前回のタップされたら回転する動作も行っています。
あと、Viewを作る時にカード番号を受け取るようにしています。
これで、カード番号と絵柄を結びつければトランプゲームに1つ近づきますね。
今回は山札だけ別の絵にする必要があったので、カード番号が"-1"の時だけ
別の絵となるようなコードになっています。
さて、続いて実際にViewを並べるActivityクラスのコードです。

CardTurnActivity
package jp.sweetsblast.cardturn;

import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.LinearLayout;

public class CardTurnActivity extends Activity{

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
LinearLayout layoutT = new LinearLayout(this);
layoutT.setOrientation(LinearLayout.HORIZONTAL);
layout.addView( layoutT);
LinearLayout layoutM = new LinearLayout(this);
layoutM.setOrientation(LinearLayout.HORIZONTAL);
layoutM.setGravity( Gravity.RIGHT);
layout.addView( layoutM);
LinearLayout layoutB = new LinearLayout(this);
layoutB.setOrientation(LinearLayout.HORIZONTAL);
layout.addView( layoutB);

layoutT.addView( new CardView(this,0));
layoutT.addView( new CardView(this,1));
layoutT.addView( new CardView(this,2));
layoutT.addView( new CardView(this,3));
layoutT.addView( new CardView(this,4));
layoutB.addView( new CardView(this,5));
layoutB.addView( new CardView(this,6));
layoutB.addView( new CardView(this,7));
layoutB.addView( new CardView(this,8));
layoutB.addView( new CardView(this,9));
layoutM.addView( new CardView(this,-1));

setContentView(layout);
}
}

シンプルですね。
全体を包むLinearLayoutが1つと3列それぞれのLinearLayout。
そして、各列にカードのViewを作って追加。
それだけのコードです。
CardViewの2つ目の引数に適当な番号を入れていますが、今回は最後の"-1"以外は意味がありません。

そして、実行した結果はこんな感じです。
[広告] VPS

山札もクリックすると回転してしまうのはダメですね(^^;
その辺りは、クリック不可にすれば解決するでしょう。

次回は実際にランダムな絵柄を配置したりしてゲームに近づけようと思います。


スポンサーサイト
[ 2012/07/09 22:31 ] Androidアプリ開発 | TB(1) | CM(0)

Geocoderクラスを使って住所から緯度/経度を取得する

今回はAndroidで住所から緯度/経度を取得するプログラムについてです。
この手のプログラムコードについては色々なサイトに載っているのですが、
少々つまずくポイントがあったので記事にしておきます。

まずは、プログラムコードを掲載。

MainActivity.java
package jp.sweetsblast.geotest2;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

@Override
public void onCreate( Bundle bundle){
super.onCreate( bundle);

TextView textView = new TextView(this);
setContentView( textView);

Geocoder geocoder = new Geocoder( this, Locale.getDefault());
try{
List<Address> addrList = geocoder.getFromLocationName("京都府京都市南区",1);
if( addrList.isEmpty() ){
textView.setText( "list is empty");
}else{
Address address = addrList.get(0);
String str = address.getLatitude() + "," + address.getLongitude();
textView.setText(str);
}
}catch( IOException e){
textView.setText( "IOException 発生");
}
}
}

念のためにマニフェストも載せておきます。
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jp.sweetsblast.geotest2"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="7" />

<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme">
<activity android:name="MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>

</manifest>


さて、ここからが本番です。
まずは引っ掛けポイントその1:ビルドターゲット
Geocoderクラスを使う場合は、ビルドターゲットをgoogle APIsにします。
Geocoder ターゲットAPI


実はこの部分で長く引っかかってました。
Geocoder自体はAndroidの標準APIなので、標準APIをビルドターゲットにしていたのですが、そうするとgetFromLocationName()メソッドで必ず空リストが帰ってきます。
どうやらクラス内部でGoogleAPIに含まれるAPIを使っているようです。
一応リファレンスにも書いてあるのですが...
The Geocoder class requires a backend service that is not included in the core android framework. The Geocoder query methods will return an empty list if there no backend service in the platform. Use the isPresent() method to determine whether a Geocoder implementation exists.(一部を抜粋)

簡単に訳すと、
Geocoderクラスは標準のAndroid frameworkに含まれないサービスを必要とします。プラットフォームにそのサービスが無ければメソッドは空のリストを返します。Geocoderクラスが実装されているかはisPresent()メソッドを使って確認して下さい。

となります。(たぶん...)
つまり、標準のframeworkだけだと動かず、googleAPIが必要となります。
そんな訳でビルドターゲットをgoogleAPIsにする必要があるのです。
ちなみに、リファレンスに書かれている isPresent() メソッドですが、
APIレベルが9(Android2.3)以上じゃないと使えません。(^^ι
Android2.3以前でも対応させるには、上のリストのように空リストが帰って来た場合の処理をして対応させる必要があります。

続いて引っ掛けポイントその2:エミュレータのバグ
Android2.2のエミュレータで実行するとIOExceptionの例外が発生します。
これはネット上に情報が転がっていたので、簡単に解決しました。
どうやら、2.2や2.3のエミュレータではGeocoderが動かないみたいです。
2.1では動くので、ビルドターゲットを(Google)APIレベル7にしてAndroid(Google)2.1のエミュレータで実行しましょう。

これで、無事に動くようになりました。
GeoTest2 実行結果

[ 2012/07/02 02:46 ] Androidアプリ開発 | TB(0) | CM(1)

ImageView を使ったカードをめくるようなアニメーション

Androidアプリ開発訓練が自由制作の期間に入りましたが、
残り1ヶ月の時間を持て余しそうだったので、
ふと思い立って、Androidで簡単なカード(トランプ)ゲームを作りつつ、
作る過程のあれこれを勉強しつつ記事にしていこうと思いました。

今回は、その第1歩として、カードをめくる様なアニメーションを作ってみます。

アニメーションの考え方としては、
1. カードの横方向の幅を徐々に狭く(縮小)していく
2. 幅が0になった時に、カードの絵柄を変える
3. カードの幅を元に戻していく
の3つの手順となります。
実際に1や3を行うには、AndroidのSDKで実装されているアニメーション機能を使うと便利です。(※)
アニメーションには、移動させたり回転させたりといくつかの種類がありますが、
今回は拡大縮小を行うので、使用するのは ScaleAnimation となります。

※ アニメーション機能を使わない方法としては、サーフェイスビューを使うなどして一定時間毎に絵を書き直す方法が考えられます。

では、早速コードを見てみましょう。
ちなみに、リソースには適当に作成したomote.jpgとura.pngを使用しました。
カードの表の絵柄カードの裏の絵柄

package jp.sweetsblast.cardturn;

import android.app.Activity;
import android.os.Bundle;import android.view.Gravity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.LinearInterpolator;
import android.view.animation.ScaleAnimation;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;

public class CardTurnActivity extends Activity implements View.OnClickListener, AnimationListener {

ImageView imageview;
boolean animation_hf_flg;

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

LinearLayout layout = new LinearLayout(this);
layout.setGravity(Gravity.CENTER);
imageview = new ImageView(this);
imageview.setPadding( 0, 0, 0, 0);
imageview.setImageResource(R.drawable.ura);
imageview.setScaleType(ScaleType.CENTER);
imageview.setOnClickListener(this);
imageview.setTag(false);
layout.addView(imageview);
setContentView(layout);
}

// View.OnClickListenerインタフェースのメソッド
public void onClick(View v) {
// カードがクリックされたら、90°回転
AnimationSet set = new AnimationSet(true);
// ↓の第5・6引数の276はカードの絵柄の横幅、縦幅です。
//  実際にはimageのwidthやheightを得る方が賢いです。
ScaleAnimation scale = new ScaleAnimation( 1.0f, 0.0f, 1.0f, 1.0f, 276f/2, 276f/2);
scale.setAnimationListener(this);
set.setFillAfter(true);
set.setFillEnabled(true);
set.addAnimation(scale);
set.setDuration(500);
set.setInterpolator( new LinearInterpolator());
imageview.startAnimation(set);
animation_hf_flg = true;
}

// AnimationListenerインタフェースのメソッド
public void onAnimationEnd(Animation animation) {
// 後半の回転終了時の呼び出しだったら何もせずに終了
if( animation_hf_flg==false ) return;

// X方向のサイズが0になって画像が見えない内に画像を変更
Boolean flg = (Boolean)imageview.getTag();
if( flg==false ){
imageview.setImageResource(R.drawable.omote);
}else{
imageview.setImageResource(R.drawable.ura);
}
imageview.setTag(!flg);

// もう一度90°回転
AnimationSet set = new AnimationSet(true);
ScaleAnimation scale = new ScaleAnimation( 0.0f, 1.0f, 1.0f, 1.0f, 276f/2, 276f/2);
scale.setAnimationListener(this); // これは設定しなくても今回は問題ない
set.setFillAfter(true);
set.setFillEnabled(true);
set.addAnimation(scale);
set.setDuration(500);
set.setInterpolator( new LinearInterpolator());
imageview.startAnimation(set);
animation_hf_flg = false;
}

// AnimationListenerインタフェースのメソッド
public void onAnimationRepeat(Animation animation) { }

// AnimationListenerインタフェースのメソッド
public void onAnimationStart(Animation animation) { }
}

これを実行すると、カードをクリックすると1秒掛けてくるっと回転します。
[広告] VPS

ただ、リソースのサイズが 276 x 276 の正方形なので、微妙にカードっぽくありませんが(^^;
あと、欲を言えば、カードに奥行きをだしたりもしたいですね...
その辺はもう少し改良してみたいと思います。
詳しい解説とかも、後日と言う事で。(^^;

[ 2012/06/28 04:44 ] Androidアプリ開発 | TB(0) | CM(0)

求職者訓練75-77日目

Androidアプリ開発訓練75-77日目。

75日目:応用課題5( 上流行程とは)
76日目:応用課題5
77日目:応用課題5
※ 応用課題は、与えられた条件を盛り込んだ自作プログラムを作成・提出するものです。

今回、の応用課題の条件は、
・ 自作アクティビティを2つ以上作成して、画面を切り替えること
・ XMLを使用してレイアウトを作成すること
・ DBかプリファレンスを使用すること

の3つとなっています。
授業でやったレシーバーやサービス、プロバイダーは関係なし。
まぁ~これらは使わなくてもアプリは作れますからね。
レシーバーの自作なんて必要性が思いつかないし、
サービスはバックグラウンドで何かする時に使うものだし、
プロバイダーはアプリ内のデータを外部に公開する時に使うものだからね。

正直、自分でアプリを作るとしても使わなそうです。
レシーバーはバッテリー低下とかの受け取りくらいは使うかもしれませんけどね。
あと、アラーム機能でサービスを使うかも。
ネット通信とかをバックグラウンドでするならサービスの実装はありそうだけど…
どちらにしても、必須ではないですね。

ちなみに、私はタスク管理と言うか、簡易メモ的なアプリを作成中です。
完成したら、マーケットに無料でリリースするつもりです。
まぁ~もしかしたらリリースする時には、簡易メモから
プロジェクト管理的な物にジョブチェンジしちゃってるかもですけどね。(^^;

  

[ 2012/06/23 10:36 ] Androidアプリ開発 | TB(1) | CM(0)

求職者訓練57-60日目

Androidアプリ開発訓練57-60日目。

さて、今回も1週間分の訓練内容をさらします。
(月曜はキャリアコンサルティングで、授業はお休み)
57日目:XMLでのUIレイアウト
58日目:テキストビュー、イメージビュー
59日目:ボタンとダイアログ
    チェックボックス・ラジオボタン・スピナー
60日目:テキストエディタ、適当な課題
今週は、思っていた以上に授業の進みがゆっくりでした。
ゆっくり過ぎて1週間が非常に長かったです。
で、来週も同じ様な感じだろうなぁ~と思うと、少しうんざりします。
と言うか、参考書に乗ってるプログラムを打って、動かすだけの授業なのであまり有意義じゃないし、非効率的です。

そんな授業中に、OpenGLや授業でやらない部分のAndroidの勉強をしたりしている訳ですが。
なかなかに難しいです。
OpenGLはテクスチャのサイズが2の乗数じゃないと、画像が表示されないんですね。
しかも、エミュレータだと問題ないから、実機で試してみて始めて気付くとか...
とりあえず、読み込み時にbitmapのサイズを調整するようにして対応しましたけど、面倒ですね。
あと、Activityのライフサイクルも面倒です。
アプリの実行状況に応じて5段階に状態変化するとか、復帰時に呼ばれるメソッドが異なるとか...
何より、端末を回転させて縦横を変えた時に一度Activityを破棄してから作り直すってのが気持ち悪いです。
Destroyはアプリ終了時(Activityが不要になる時)に1度呼ばれるだけにして欲しいです。
Activityのこのあたりの挙動はもう少し掘り下げて調べてみる必要がありそうです。
そうじゃないと、不具合の無いアプリなんて作れませんから。

以上、今週の訓練についてでした。
来週も授業はちゃんと聞きつつ、個人的な勉強を突き進めようと思います。
[ 2012/05/27 01:12 ] Androidアプリ開発 | TB(0) | CM(0)
FC2カウンター
カレンダー
06 | 2017/07 | 08
- - - - - - 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 - - - - -
Twitter@sweetsblast
過去ログ

2017年 06月 【3件】
2017年 05月 【3件】
2017年 04月 【3件】
2017年 03月 【5件】
2017年 01月 【1件】
2016年 09月 【2件】
2016年 04月 【2件】
2016年 03月 【2件】
2016年 01月 【5件】
2015年 12月 【3件】
2014年 05月 【1件】
2014年 04月 【1件】
2013年 12月 【1件】
2013年 03月 【4件】
2013年 02月 【3件】
2013年 01月 【1件】
2012年 12月 【3件】
2012年 11月 【4件】
2012年 10月 【2件】
2012年 09月 【4件】
2012年 08月 【2件】
2012年 07月 【3件】
2012年 06月 【11件】
2012年 05月 【11件】
2012年 04月 【9件】
2012年 03月 【15件】
2012年 02月 【17件】
2012年 01月 【5件】
2011年 12月 【14件】
2011年 11月 【11件】
2011年 10月 【19件】
2011年 09月 【10件】
2011年 08月 【4件】
2011年 07月 【11件】
2011年 06月 【4件】
2011年 05月 【1件】
2011年 04月 【17件】
2011年 03月 【29件】
2011年 02月 【24件】
2011年 01月 【30件】
2010年 12月 【30件】
2010年 11月 【22件】
2010年 10月 【26件】
2010年 09月 【27件】
2010年 08月 【30件】
2010年 07月 【27件】
2010年 06月 【24件】
2010年 05月 【7件】
2010年 04月 【6件】
2010年 03月 【3件】
2010年 02月 【6件】
2010年 01月 【8件】
2009年 12月 【8件】
2009年 11月 【5件】
2009年 10月 【7件】
2009年 09月 【18件】
2009年 08月 【22件】
2009年 07月 【14件】
2009年 06月 【16件】
2009年 05月 【28件】
2009年 04月 【25件】
2009年 03月 【5件】
2009年 01月 【2件】
2008年 12月 【1件】
2008年 11月 【2件】
2008年 10月 【3件】
2008年 09月 【6件】
2008年 08月 【3件】
2008年 07月 【2件】
2008年 06月 【2件】
2008年 05月 【3件】
2008年 04月 【4件】
2008年 03月 【11件】
2008年 02月 【12件】
2008年 01月 【7件】
2007年 12月 【8件】
2007年 11月 【5件】
2007年 10月 【8件】
2007年 09月 【6件】
2007年 08月 【15件】
2007年 07月 【10件】
2007年 06月 【14件】
2007年 05月 【12件】
2007年 04月 【10件】
2007年 03月 【7件】
2007年 02月 【19件】
2007年 01月 【18件】
2006年 12月 【25件】
2006年 11月 【27件】
2006年 10月 【19件】
2006年 09月 【26件】
2006年 08月 【12件】
2006年 07月 【5件】



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。