ラベル GUI の投稿を表示しています。 すべての投稿を表示
ラベル GUI の投稿を表示しています。 すべての投稿を表示

2017年11月10日金曜日

XMLで作るアニメーションするメニュー

新作アプリオタマーズ(仮)作ってます タイトルメニューに階層があって、切り替えにアニメーションをつけてみたので紹介します
ほぼほぼXMLで済ませているので簡単です
画面レイアウトのXMLがこちら

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 <ImageView
 <FrameLayout
  <LinearLayout
  <ImageButton
   android:id="@+id/setting"
  <ImageButton
   android:id="@+id/mission"
・・・
  </LinearLayout>
 </FrameLayout>
</LinearLayout>
くっそ長いので全文は下のほうに追いやりました
メニュー部分はFrameLayoutで直下のLinearLayoutに1階層目のボタン3つ
id="@+id/stageの部分が2階層目になっててvisible=goneで隠してます
次にAnimation用のXMLがこちら
// 1階層目メニュースライドイン
// res/anim/menu_in.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/decelerate_interpolator"
 android:fromXDelta="-100%p"
 android:toXDelta="0%p"
 android:fillAfter="true"
 android:duration="800" />

// 1階層目メニュースライドアウト
// res/anim/menu_out.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/decelerate_interpolator"
 android:fromXDelta="0%p"
 android:toXDelta="120%p"
 android:fillAfter="true"
 android:duration="800" />

// 2階層目メニューズームイン
// res/anim/zoom_in.xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/decelerate_interpolator"
 android:fromXScale="0"
 android:toXScale="1.0"
 android:fromYScale="0.0"
 android:toYScale="1.0"
 android:pivotX="50%"
 android:pivotY="50%"
 android:fillAfter="true"
 android:duration="600" />
で、ボタンを押したときの処理がこちら
動かすViewに上記のstartAnimationをセットしてやるだけです
@Override public void onClick(View v) {
  switch (v.getId()) {
    case R.id.mission : //2階層目表示
      menu_off = true;
      findViewById(R.id.stage).startAnimation(AnimationUtils.loadAnimation(this, R.anim.zoom_in));
      findViewById(R.id.setting).startAnimation(AnimationUtils.loadAnimation(this, R.anim.menu_out));
      findViewById(R.id.mission).startAnimation(AnimationUtils.loadAnimation(this, R.anim.menu_out));
      findViewById(R.id.challenge).startAnimation(AnimationUtils.loadAnimation(this, R.anim.menu_out));
      break;
    case R.id.title1 : //1階層目に戻る
      menu_off = false;
      findViewById(R.id.stage).clearAnimation(); //これやらんとなぜか変に表示が残る
      findViewById(R.id.stage).setVisibility(View.GONE);
      findViewById(R.id.setting).startAnimation(AnimationUtils.loadAnimation(this, R.anim.menu_in));
      findViewById(R.id.setting).setVisibility(View.VISIBLE);
      findViewById(R.id.mission).startAnimation(AnimationUtils.loadAnimation(this, R.anim.menu_in));
      findViewById(R.id.mission).setVisibility(View.VISIBLE);
      findViewById(R.id.challenge).startAnimation(AnimationUtils.loadAnimation(this, R.anim.menu_in));
      findViewById(R.id.challenge).setVisibility(View.VISIBLE);
      break;
  }
}
メニューを消すときにstartAnimation直後に.setVisibility(View.GONE)をやってしまうと
アニメーションする前に消えてしまうので、AnimationListenerをimplementsして
onAnimationEndで消してます
public class Menu extends Activity implements View.OnClickListener, Animation.AnimationListener {

@Override public void onAnimationStart(Animation animation) { }
@Override public void onAnimationRepeat(Animation animation) { }
@Override public void onAnimationEnd(Animation animation) {
  if (menu_off) {
    findViewById(R.id.setting).setVisibility(View.GONE);
    findViewById(R.id.mission).setVisibility(View.GONE);
    findViewById(R.id.challenge).setVisibility(View.GONE);
  }
}
以上

res/layout/menu.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:background="@drawable/title_back"
 android:gravity="center_horizontal"
 android:orientation="vertical" >
 <ImageView
  android:scaleType="fitStart"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_margin="32dp"
  android:src="@drawable/title" />
 <FrameLayout
  android:layout_width="fill_parent"
  android:layout_height="0dp"
  android:layout_weight="1"
  android:gravity="center">
  <LinearLayout
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:layout_gravity="center">
  <ImageButton
   android:id="@+id/setting"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginBottom="36dp"
   android:background="@null"
   android:onClick="onClick"
   android:src= "@drawable/menu_sg"/>
  <ImageButton
   android:id="@+id/mission"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginBottom="36dp"
   android:background="@null"
   android:onClick="onClick"
   android:src= "@drawable/menu_mi"/>
  <ImageButton
   android:id="@+id/challenge"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginBottom="36dp"
   android:background="@null"
   android:onClick="onClick"
   android:src= "@drawable/menu_ch"/>
  </LinearLayout>
  <LinearLayout
   android:id="@+id/stage"
   android:orientation="vertical"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:visibility="gone">
   <LinearLayout
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal">
    <LinearLayout
     android:id="@+id/stage1"
     android:tag="1"
     android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_margin="12dp"
     android:onClick="onClick"
     android:gravity="center_horizontal">
     <ImageView
      android:scaleType="matrix"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/mission_u"/>
     <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Stage1"
      android:gravity="center"
      android:textColor="#000"
      android:textSize="12sp"
      android:ellipsize="end"/>
    </LinearLayout>
    <LinearLayout
     android:id="@+id/stage2"
     android:tag="2"
     android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_margin="12dp"
     android:onClick="onClick"
     android:gravity="center_horizontal">
     <ImageView
      android:scaleType="matrix"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/mission_l"/>
     <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Stage2"
      android:gravity="center"
      android:textColor="#000"
      android:textSize="12sp"
      android:ellipsize="end"/>
    </LinearLayout>
    <LinearLayout
     android:id="@+id/stage3"
     android:tag="3"
     android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_margin="12dp"
     android:onClick="onClick"
     android:gravity="center_horizontal">
     <ImageView
      android:scaleType="matrix"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/mission_u"/>
     <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Stage3"
      android:gravity="center"
      android:textColor="#000"
      android:textSize="12sp"
      android:ellipsize="end"/>
    </LinearLayout>
   </LinearLayout>
   <LinearLayout
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal">
    <LinearLayout
     android:id="@+id/stage4"
     android:tag="4"
     android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_margin="12dp"
     android:onClick="onClick"
     android:gravity="center_horizontal">
     <ImageView
      android:scaleType="matrix"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/mission_u"/>
     <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Stage4"
      android:gravity="center"
      android:textColor="#000"
      android:textSize="12sp"
      android:ellipsize="end"/>
    </LinearLayout>
    <LinearLayout
     android:id="@+id/stage5"
     android:tag="5"
     android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_margin="12dp"
     android:onClick="onClick"
     android:gravity="center_horizontal">
     <ImageView
      android:scaleType="matrix"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/mission_u"/>
     <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Stage5"
      android:gravity="center"
      android:textColor="#000"
      android:textSize="12sp"
      android:ellipsize="end"/>
    </LinearLayout>
    <LinearLayout
     android:id="@+id/stage6"
     android:tag="6"
     android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_margin="12dp"
     android:onClick="onClick"
     android:gravity="center_horizontal">
     <ImageView
      android:scaleType="matrix"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/mission_u"/>
     <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Stage6"
      android:gravity="center"
      android:textColor="#000"
      android:textSize="12sp"
      android:ellipsize="end"/>
    </LinearLayout>
   </LinearLayout>
   <ImageButton
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="36dp"
    android:background="@null"
    android:onClick="onClick"
    android:src= "@drawable/menu_tt"/>
  </LinearLayout>
 </FrameLayout>
</LinearLayout>

2014年3月25日火曜日

新作Androidアプリ開発 GUIを盛る編 ダッシュボード的なパネル

今回はStats(統計)機能の画面のGUIを盛っていきたいと思います
現状の画面だと操作と情報表示部分の区切りがはっきりせず、どこが何なのかをもう少しわかりやすくしたいので表示切替操作部をダッシュボード調にしてみます
こんな感じ、少しはわかりやすくなったかな?
こうなるとアイコンがちょっとしょぼい気がしますね、要改良です
静的なコンテンツなのであまり難しいことはしてません
layout.xmlはこんな構造です
ちょっと入れ子が多くなってしまいますね
ポイントというほどのあれはありませんが、強いて言えばダッシュボードパネル部(オレンジ)の円弧分のPaddingを取ることと、右側にドロップシャドウを落としてやることで立体感を出してます
あと緑のLinearLayoutは、3等分でアイコンを配置したいがためだけに入れています

2014年3月23日日曜日

新作Androidアプリ開発 GUIを盛る編 スタートシグナル

さて今日もGUIを盛っていきたいと思います
ゲームのスタート時いきなり始まるとユーザーがとまどうということで、3秒のカウントダウン時間を設けることにしました
ここでスタートシグナルのようなものを出したいということでとりあえず作ってみたのがこれ
んー確かにスタートシグナルなんだけど・・・
ちょっと普通っぽいし、いまいちかなぁ
一ひねりしてみようと作ったのがこれ
色調と形をもうちょっとどうにかしなきゃですが、なんとなく・・・こんな感じでいい?かな?
実装は横着して簡単にベースの黒いところと左赤、右赤、真ん中青を順番に重ねて描画するだけです

デザインは正解がないのでセンスがないと試行錯誤が増えてしまいますね・・・

2014年3月21日金曜日

新作Androidアプリ開発 GUIを盛る編 ゲージのような表示

さて新作アプリの開発ですが、 4回にわたるテコ入れ編でクリティカルな問題に対しての対策が出来ました
あとは完成に向けてひた走るだけ!?
というわけで今回から見た目部分の改良でGUIを盛る編といきたいと思います

まずは右上に表示していた残り時間の表示がスコアの表示と同じじゃわかりにくいし、なんかしょぼいのでもう少し視覚的に残り時間がわかりやすいようにしたいと思います

完成イメージはこう
これをどうやって描画したらいいかなぁと考えました
やり方はいろいろでしょうが今回は丸いゲージの部分の画像をフルで用意して、それを扇形のclipPathでマスクして必要部分だけを描く方法を取りました
パーツを一個用意して回転させながら60個描く方法もありますが、clipPathの方法なら切れ目がないようなアナログ的なゲージにも対応できる思います
コード的には以下のような感じ
    int time; //残り時間
    int rect; //ゲージの大きさのRect
    Bitmap gauge; //フルゲージ画像
    Path clip = new Path();
    clip.moveTo(rect.centerX(), rect.centerY());
    clip.addArc(rect, 267 + ((60 - time) * 6), 360 - ((60 - time) * 6));
    clip.lineTo(rect.centerX(), rect.centerY());
    canvas.save();
    canvas.clipPath(clip);
    gauge.draw(canvas);
    canvas.restore();
このブログで以前、SurfaceViewで描画範囲を限定するでやった方法と同じですね
clipPathは描画したい部分の指定になるので、addArc()の開始角と終了角をずらしながらセットしてやります

わりといい感じにできました

2013年6月21日金曜日

自作ライブラリ-SurfaceViewで画像の数字を表示

Androidアプリ・ゲームを作るときに、スコアやパラメータなど数字を表示したい場合が結構あります。
こんなときCanvas#drawText()で済めばいいんですが、見た目にこだわりたいときは画像を使う他ありません。 
やることは数字の画像を0から9まで用意して各桁の数字に合わせて位置を決めて描画するというだけですが、何回もでてくるので汎用的なクラスにしてしまったほうがいいかなということで作ってみました。 
まず0から9までの画像を用意。


表示用のクラスはこんな感じ

public class CvsNumber {
    public Rect res;
    public Bitmap[] images = null;
    public int number = 0;
    public int digit = 3;
    public boolean zerofill = false;
    public int top;
    public int left;
    public int width;
    public int height;
    public Paint paint = new Paint();
    private Rect src;

    public CvsNumber(int id, Context context, int[] resources) {
        images = new Bitmap[10];
        //0から9の画像をセット
        for (int i = 0; i < 10; i++) {
            images[i] = BitmapFactory.decodeResource(context.getResources(), resources[i]);
        }
        //1つ目の画像の大きさを取っておく
        src = new Rect(0, 0, images[0].getWidth(), images[0].getHeight());
    }

    public void draw(Canvas canvas) {
        int r = left + width; //描画範囲の右端
        int w = width / digit; //1桁当たりの描画幅
        int h = (w * images[0].getHeight()) / images[0].getWidth(); //1桁当たりの数字の描画高さ
        int t = top + ((height - h) / 2); //描画開始高さ
        int s = number % 10; //1の位の数字
        //1の位を描画
        canvas.drawBitmap(images[s], src, new Rect(r - (w * 1), t, r, t + h), paint);
        //digitで指定した位まで描画
        for (int i = 1; i < digit; i++) {
            if (zerofill || String.valueOf(number).length() > i) {
                s = (number / (int)(Math.pow(10, i))) % 10;
                canvas.drawBitmap(images[s], src, new Rect(r - (w * (i + 1)), t, r - (w * i), t + h), paint);
            }
        }
    }
}

表示結果はこんな感じ。
与えるパラメータは描画位置のtop,left,width,heightとnumber(値),digit(桁数),zerofill(0埋め)です。
 
四角い枠は指定した描画範囲をわかりやすいように表示してます。

一度作っておけば画像を差し替えれば、いろんなパターンで利用できて捗ること間違いなしです。
SurfaceViewに限らず自作Viewでも利用可能ですね。