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

2012年11月28日水曜日

ViewFlipperでページめくり ~おまけ編

ここからはおまけ.

前回の続きでフリックでページをめくる処理を実装する.
要するにフリックイベントを取りに行くわけでもはやViewFlipperほとんど関係ない気がする('A`)

OnGestureListenerをもちいたフリックイベントの取得

ついにタイトルすらViewFlipperから遠のいたけど気にしない.
実装するのはActivity. ここに

implements OnGestureListener

してやる. 当然 eclipse「メソッドのオーバーライド足りてねぇぞゴルァ(゚Д゚#)」と怒られるので言われるままに作成.
ただし今回使うメソッドは2つのみ.

① onFling
② dispatchTouchEvent

特に②が忘れられがちなので注意

① onFling

実際に受け取ったフリックイベントから処理を行なうクラス. 

@Override
public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY) {
    float dx = Math.abs(e1.getX() - e2.getX());
    float dy = Math.abs(e1.getY() - e2.getY());
    if (dx > dy) {
      if (velocityX > 0) {
        flipper.setInAnimation(slideInFromLeft);
        flipper.setOutAnimation(slideOutToRight);
        flipper.showPrevious();
      } else {
        flipper.setInAnimation(slideInFromRight);
        flipper.setOutAnimation(slideOutToLeft);
        flipper.showNext();
      }
      return true;
    }
    return false;
}

たまにはsyntaxhighlighterの色を変えてみたかった(言い訳)ので参考サイトをほぼコピペを更にコピペというだめっぷりorz
3行目, 4行目でフリックのX方向, Y方向の移動距離をそれぞれ取得,
5行目で比較してX方向のほうが大きい=横にフリックする気でフリックした 時のみ処理を行なう.
6行目でフリックのベクトルが右方向か左方向かを判定, 右なら1ページ戻る, 左なら1ページ進む, を処理させる. 処理の内容は前回参照.
それだけ. これでイベントが飛んでくれば処理してくれる.

②dispatchTouchEvent

一度ここを設定し忘れて「あっれーうごかないぞー(゜д゜;三;゜д゜)」とか言ってたことがあるのでorz
まずonCreateあたりで

GestureDetector gestureDetector = new GestureDetector(this, this);

を取得.
そして問題のdispatchTouchEvent
@Override
public boolean dispatchTouchEvent(final MotionEvent event) {
  return gestureDetector.onTouchEvent(event) || super.dispatchTouchEvent(event);
}

eclipseの自動生成に出てこない引っ掛けっぷり. ひどすぎる('A`)
コイツを作っておかないとそもそもイベントを取ってくれませんorz


これらを設定してやると, おめでとう!ボタンで動いていた画面がフリックで移動するようになったぞ!
となる.

onFlingの3行目, 4行目でとったように, e1.getX()でとった座標で条件分岐してやれば, 特定の範囲でフリックしたときのみイベントを取るなんてのもできそう. やってないけど(・ω・`)





長かった…('A`)

ViewFlipperでページめくり ~動作編


前回からの続き. ようやくページめくりのお話.

B. コード上で動きを指定

とりあえず

ViewFlipper flipper = (ViewFlipper) findViewById(R.id.flipper)

で ViewFlipperを取得.
ページを送る/戻す処理は

flipper.showNext()/flipper.showPrevious()

これだけ.
これをボタンのクリックイベントだったり画面のフリックイベントだったりに呼ぶようにしてやれば, それだけで次の/前の子ビューを表示してくれる.便利!

ただこれだけだと一瞬でページが切り替わる非常に味気ないページめくりに…
なので折角だしアニメーションを仕込んでみる.

手順は
① アニメーションの情報を仕込んだxmlを作成
② ①を基にflipperにアニメーションをセット
の2本立てでお送りします

①xmlを作成

まずはres/animを作成. 基本自動生成はされていないので自作のはず.
ここにAndroid XML File を作成します. RootElementは「translate」.
内容は,

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXDelta="-100%p"
    android:toXDelta="0%p"
    android:fromYDelta="0%p"
    android:toYDelta="0%p">
</translate>

ためしに左からページが画面に入ってくるアニメーション.

android:durationがアニメーションに書ける時間(ミリ秒)
XDelta, YDeltaはそれぞれViewの左上の座標の位置を指定. 0%pで今写っている画面の左上を指す.
fromがアニメーション開始時の位置, toがアニメーション終了時の位置を指す.
のでこのアニメーションは,
画面外ちょうど画面1枚分左から, 500ミリ秒かけて画面ぴったりに収まるように入ってくる
アニメーションとなる.
ちょっと指定を変えれば出ていく, 逆方向の動きはもちろん, 斜めからスライドイン/アウトだって指定できちゃう(゚∀゚)ラクチン!

これを,
1. 左から入ってくる
2. 右へ出て行く
3. 左へ出て行く
4. 右から入ってくる
の4タイプ分用意します.

②flipperにアニメーションをセット

xmlを用意できたらいざセット

Animation slideInFromLeft = AnimationUtils.loadAnimation(this, R.anim.slide_in_from_left);
Animation slideOutToRight = AnimationUtils.loadAnimation(this, R.anim.slide_out_to_right);
flipper.setInAnimation(slideInFromLeft);
flipper.setOutAnimation(slideOutToRight);

slide_in_from_leftがちょうど①に挙げたxml. 同様にAnimation を作成し, InとOutそれぞれflipperにセットしてやる.
新しいページの入り方と古いページの出方…のはず(・ω・`)
これでOK.
ただしIn, Outそれぞれアニメーションは1個ずつしか登録できないため, 上記のコード全部で右にページを送る処理ひとつ.
左にページを送る逆向きの処理を同じ flipperにセットしたい場合, 処理を呼び出すごとにセットしてやらないと, 最後にセットしたアニメーションのみ実行することになります.
なので1ページ戻るアニメーションを実現するなら,

 flipper.setInAnimation(slideInFromLeft);
 flipper.setOutAnimation(slideOutToRight);
 flipper.showPrevious();

これ全部を「戻る」ボタンあたりのonClickで呼んでやる必要がある.逆もまた然り.


これで一応アニメーションしながらページめくりはできる. できるけど…なんか違う.
やっぱりフリックでページをめくりたい!


なのでさらに続けてみます.







あともうちょっとだけ続くんじゃ('A`)

ViewFlipperでページめくり ~ページ作成編

ホーム画面やらiPhoneやらでおなじみ横フリックでページめくり.
これを利用して, 数ページに分割したランキングを作りたい! と調べてみたら, ViewFlipperなんて便利そうなViewを見つけたヽ(・ω・)/.

ViewFlipperで簡単ページめくり


必要なものは
A. <ViewFlipper>タグを用意
B. コード上で動きを指定

まずはxml

A. <ViewFlipper>タグを用意

使いたいActivityのレイアウトに

<ViewFlipper
       android:id="@+id/flipper"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >
</ViewFlipper>

これだけ. 実に簡単. ちなみにこの外にボタンやらなにやら置いてもOK. Layout内で<ViewFlipper>タグが陣取ったエリアだけでページめくりしてくれます.

ただしこのままだとめくる「ページ」が無いので, 中に子ビューを入れる.
入れる方法は2通り.

①. このままxmlに突っ込むぜ!
② いやコード上で動的に作りたいんで

①はまた楽. <ListView>なんかと同じようにタグの間に宣言するだけ.
例えば…

<ViewFlipper
       android:id="@+id/flipper"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >
       <include android:id="@+id/flipper_child" layout="@layout/flipper_child"/>
</ViewFlipper>

<include>を使うと見やすくまとまってよろしいかと.flipper_child.xmlはまた別にLayoutを作って用意しておけばOK. ただ<include>は2個以上入れないとページめくりになりません. まぁ当たり前だけど('A`)
ページ数が決まっているならばこっちがオススメ.

②はちょっとめんどい. 追加自体は

ViewFlipper flipper = (ViewFlipper) findViewById(R.id.flipper);
flipper.addView(childLayout)

問題はこのchildLayout.すでにLayout自体ができているならひたすらViewを作成→addViewで良いのだが, それなら<include>使ったほうが誤爆は少ない.
また今回は順位表のように決まったLayoutを使いまわして作りたかったうえに, 何ページになるかが決まっていない始末.仕方が無いので子ビューのLayout.xmlを一枚テンプレート的に用意して動的に内容を作って addしていく.


View childLayout = this.getLayoutInflater().inflate(FLIPPER_CHILD_LAYOUT_ID, null);
ListView list = (ListView) childLayout.findViewById(R.id.list);
list.setAdapter(listAdapter);
list.setScrollingCacheEnabled(false);
list.setOnItemClickListener(itemListener);


完璧今回使ったもののコピペ. 手抜きではありません. ええ決して.
1行目で子ビューを新規生成. FLIPPER_CHILD_LAYOUT_IDは子ビューのLayout.xmlのid. 第二引数は今回は特に親のViewGroupをとらないのでnull…で良いのかな(・ω・`)
2行目は子ビューのLayout.xml内に自分で設置したListViewを取得. childLayoutからfindViewByIdしている点には注意.
3行目はそのListに値をぶち込む処理. Adapterに関しては今回はノータッチ. ただ何ページも作る際はAdapterを毎回新しく作るなどちゃんとしておかないと同じ内容のデータが延々と並ぶ苦行のFlipperが完成するので注意.
4行目は完全にListViewの設定. これをしておくとListViewスクロール時, 背景の色が変わるアレを無くすことができます. 背景色を指定しているときなんかに合わせてどうぞ. Flipper関係ねー.
5行目もListの OnItemClickListener のセット. ここで毎回ちゃんとしておくとどのページのListViewもイベントが取れるようになります. ただListenerの中でgetitemする際は,

ListView list = (ListView) parent;
Object item = (Object) list.getItemAtPosition(position);


しておかないとうまく取れないかも…
ともあれこれでFlipperにページを収められたはず.

…長くなっちゃったのでページを動かす処理は次回


AWS CDKで立てたEC2インスタンスのTimeZoneとかいじりたかった話

EC2を立てることはできたけど、立てたインスタンスは UTCのままだし設定ファイルとかいちいちscpしてくるのはダルい。 当初UserDataでなんとかしようとしたものの、「書く量がヤバいしメンテしにくい」と悩んでいたところ見かけたのが  AWS::CloudFormation:...