2015年6月29日月曜日

OpenGLのサンプルをやってみたPart2

OpenGLのサンプルをやってみたPart2

もう少しOpenGLの理解を深めるためにネットに転がっているサンプルをやってみようと思います。
ということで今回は以下。
http://utage.headwaters.co.jp/blog/?p=1724

サンプルソースもすべて公開されており、ソースにコメントもあるので
大変勉強になったのですが、初心者にとっては理解ができないところがあったので、メモを残したいと思います。

renderMainでglMatrixModeを2回設定しているのはなぜ?

座標系としては透視投影(奥行きによって、大きさが変わる)ような表示をしたいので、
視体積を設定するglFrustumfの前にGL_PROJECTIONとして設定し、それ移行のオブジェクトはモデルビューで設定したいからっぽい。

テクスチャ画像ファイルは2の階乗になっていないといけない (128px*128pxなど)??

 と書いてあったが以下の解像度を試しましたがリードできてました。
 1600x1200
 278x204
 1333x1000
 1600x1600

使った画像は以下です。一応著作権フリーのもの。
enter image description here

キャラの周りが透明にならない。

上記のキャラの周りは透明(アルファ=0)にも関わらず以下のように周りが黒くなってしまいました。

enter image description here

renderMainに以下を追加することで解決しました。

gl.glEnable(GL10.GL_ALPHA_TEST);
gl.glAlphaFunc(GL10.GL_GEQUAL, 0.1f);

これはアルファ値が0.1f以上は描画するということなので、逆にいうとアルファ値が0の部分は描画されなくなったということです。ちなみに黒となっていたのはアルファ値が0の部分のRGB値がすべて0となっていたためです。

gl.glFrustumfって何?

 透視投影への視体積の設定。  引数は、以下の順。
  Nearの左側の座標
  Nearの右側の座標
  Nearの上側の座標
  Nearの下側の座標
  Nearの距離
  Farの距離

  gl.glFrustumfの引数を変えて見え方がどう変わるかを実験をしてみました。
     

実験 変数 画像 コメント
オリジナル -0.3f, 0.3f, -0.2f, 0.2f, 0.5f, 20.0f enter image description here
実験1 -0.5f, 0.5f, -0.2f, 0.2f, 0.5f, 20.0f enter image description here 透視投影だと遠くにいくほど大きくなるので、奥行き感がなくなると想定していたが、逆に奥行き感が増えた。よくわからない。
実験2 -0.3f, 0.3f, -0.5f, 0.5f, 0.5f, 20.0f enter image description here Nearの縦方向を大きくすることでFar方向の縦の距離の差が減るので縦方向が狭まった。
実験3 -0.3f, 0.3f, -0.2f, 0.2f, 1.0f, 20.0f enter image description here 見ている視点がZ=1.0fの為か手前側しか見えない
実験4 -0.3f, 0.3f, -0.2f, 0.2f, 0.2f, 20.0f enter image description here オリジナルよりNearとFarの距離が増えたので奥行きが広がった?
実験5 -0.3f, 0.3f, -0.2f, 0.2f, 0.5f, 10.0f enter image description here オリジナルと変わらない。10.0fも20.0fも同じ? 試しに5.0fにしても変わらなかった。
実験6 -0.3f, 0.3f, -0.2f, 0.2f, 0.5f, 1.0f enter image description here ねこより後ろが表示されていない
実験7 -0.3f, 0.3f, -0.2f, 0.2f, 0.5f, 2.0f enter image description here ねこより後ろが表示されるようになったが、空が表示されていない
実験8 -0.3f, 0.3f, -0.2f, 0.2f, 0.5f, 3.0f enter image description here オリジナルと同じになった

参考
http://seesaawiki.jp/w/mikk_ni3_92/d/%BC%C2%C1%A9%CA%D407
https://sites.google.com/a/gclue.jp/android-docs-2009/openglno-kiso
http://www.kameda-lab.org/lecture/2012-tsukuba-ic2/chapter08-j.html
http://ameblo.jp/xcc/entry-10276958074.html

gl.glTranslatefって何?

移動の設定。

実験 変数 画像 コメント
オリジナル 0.0f, 0.0f, -1.0f enter image description here
実験1 0.0f, 0.0f, 0.0f enter image description here
実験2 0.0f, 0.0f, -2.0f enter image description here
実験3 -1.0f, 0.0f, -1.0f enter image description here 左に移動したので右半分がでていない。
実験4 0.0f, -1.0f, -1.0f enter image description here 下に移動したので、上のほうがでていない

gl.glRotatefで-70.0fってなぜ-70.0f?

回転。X,Y,,Zどの軸を基準に回転させるか?
以下のように実験してみたが、-70.0fは結構いい感じで奥行き感がでている。

実験 変数 画像 コメント
オリジナル -70.0f,1.0f, 0.0f, -1.0f enter image description here
実験1 0.0f,1.0f, 0.0f, -1.0f enter image description here
実験2 -45.0f,1.0f, 0.0f, -1.0f enter image description here
実験3 -90.0f,1.0f, 0.0f, -1.0f enter image description here
実験4 90.0f,1.0f, 0.0f, -1.0f enter image description here
実験5 -80.0f,1.0f, 0.0f, -1.0f enter image description here
実験6 -60.0f,1.0f, 0.0f, -1.0f enter image description here

GraphicUtil.drawTextureって何?

ウインドウにテクスチャを貼り付ける方法の設定。

型 引数 説明
GL10 gl
float x テクスチャを貼り付けるウインドウの座標(x)左が0
float y テクスチャを貼り付けるウインドウの座標(y)上が0
float width 1倍なら1.0f?
float height 1倍なら1.0f?
int texture テクスチャのID。GraphicUtil.loadTextureで取得
float u テクスチャの横座標。左が0.0f
float v テクスチャの縦座標。上が0.0f
float tex_w テクスチャの横幅。最大1.0f
float tex_h テクスチャの縦幅。最大1.0f
float r 赤。 1.0fならテクスチャの赤をそのまま表示
float g 緑。 1.0fならテクスチャの緑をそのまま表示
float b 青。 1.0fならテクスチャの青をそのまま表示
float a アルファ 1.0fならテクスチャのアルファをそのまま表示
型 引数 説明
オリジナル enter image description here
実験1 width,hightを1.0f,1.0fに変更 enter image description here
実験2 width,hightを3.0f,1.0fに変更 enter image description here
実験3 width,hightを1.0f,3.0fに変更 enter image description here

gl.glPushMatrixって何?

行列スタックの一番上の行列をコピーして、その上に積む。
積まれた行列をスタックからとりだすときは、gl.PopMatrixで取り出す。

なぜ必要?

複数のオブジェクトを描画するときに、基準となる座標を1つ前に描画されたオブジェクト基準ではなく、常に同じ座標を基準に描画するようにする手段っぽい。

もう少し具体的にいうと
描画されるのは一番上のスタックにある行列で、
Translate, Rotateなどに描画に必要な操作はスタックの一番上の行列に対して計算されている。

この状態で次のオブジェクトを描画しようとすると、座標は1つ前の座標基準に考えなければならない。

Push,Popを使うことで
Push(コピー)されたものに対してTranslate, Rotateなどに描画するための演算をし、描画されたらその行列をPopで取り除くことで元の座標基準で描画できるというしくみ。
このサンプルでは地面を最初に描画しているが、地面は、座標をいじっていないのでPush/Popはしていない?

OpenGLでゲームを作る 図形の描画に非常にわかりやすく書いてあります。

使い方としては、以下のような形でPushとPopの間で描画する。

 gl.glPushMatrix();
{
            gl.glTranslatef(0.0f,1.5f,0.5f);  // y軸方向に1.5f,z軸方向に0.5f移動させる
            gl.glRotatef(90.0f, 1.0f,0.0f,0.0f);  // x軸を中心に90度回転
            // 奥背景の描画
            GraphicUtil.drawTexture(gl, 0.0f, 0.0f,
                    2.0f,1.0f,  // width, height
                    backTex,
                    0.0f,0.0f,
                    1.0f,1.0f,
                    1.0f,1.0f,1.0f,1.0f);
        }
        gl.glPopMatrix();

gl.glOrthofって何?

正射影の設定。
画面上の中央が(0, 0)、画面横の長さが2.0、画面縦の長さが3.0という座標系を指定している。奥行きに関しては手前が-1.0fで奥が1.0f。
だいたい画面縦横比は2:3なので、こうしているっぽい。

参考
http://news.mynavi.jp/column/iphone/019/

2015年6月23日火曜日

OpenGLでの描画

OpenGLでの描画

OpenGLを使って描画する。

三角形を例にします。
流れとしては頂点を設定して、描画って感じです。

頂点の設定

以下の手順で頂点を設定します。

Step1. 頂点の座標(X,Y,Z)を配列で定義する。

float[] vertices = {
  0.0f, 1.0f, 0.0f, //頂点0 (上)
  0.0f, 0.0f, 0.0f, //頂点1 (左下)
  1.0f, 1.0f, 0.0f, //頂点2 (右上)
};

Step2. バッファのメモリ確保

座標データ数x4倍のメモリを確保します。
※4倍しているのはfloatが4byte扱いの為。

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);

Step3. ネイティブのエンディアン指定

nativeのエンディアンを取得し、設定します。

vbb.order(ByteOrder.nativeOrder());

Step4. ByteBuffer型のオブジェクトをFloatBufferに変換

FloatBuffer mVertexBuffer = vbb.asFloatBuffer();

Step5. Step4で変換されたFloatBufferに最初の頂点座標(float配列)をセット

mVertexBuffer.put(vertices);

Step6. 書き込み位置の調整
書き込みが発生するたびに次書き込むための位置が1進んでしまうため、それを戻す処理を行っています。

mVertexBuffer.position(0);

[参考]
http://librastudio.hatenablog.com/entry/2013/08/19/010615

描画の設定

Step1. 頂点配列を有効にする。

   glEnableClientState(int array)を使って、どの配列を使って、描画するかを指定します。
   今回の場合は、頂点を設定しているので引数は、GL_VERTEX_ARRAYとする。
   

変数 意味 参照
GL_COLOR_ARRAY カラー配列 glColorPointer()
GL_EDGE_FLAG_ARRAY エッジフラグ配列 glEdgeFlagPointer()
GL_INDEX_ARRAY 指標配列 glIndexPointer()
GL_NORMAL_ARRAY 法線配列 glNormalPointer()
GL_TEXTURE_COORD_ARRAY テクスチャ座標配列 glTexCoordPointer()
GL_VERTEX_ARRAY 頂点配列 glVertexPointer()

glEnableClientState(GL10.GL_VERTEX_ARRAY);

Step2. 頂点配列を定義する。

glVertexPointer((int size, int type, int stride,java.nio.Buffer pointer)

変数 意味 備考
size 頂点データのサイズ 2次元なら2,3次元なら3,Wを含めるなら4
type GL_SHORT、GL_INT、GL_FLOAT、GL_DOUBLE
stride 連続する頂点間でのバイト・オフセット 0 を指定すれば、頂点の情報が配列ないに隙間なく入っている
pointer 座標情報を含む配列へのポインタ

X,Y,Z座標を指定しているのでsizeは3。

glVertexPointer(3,GL10.GL_FLOAT,0,mVertexBuffer);

Step3. 法線ベクトルの追加

ここでいう法線ベクトルとは・・・  面に垂直な長さが1のベクトル。

1)p0→p1という向きのベクトルv1(= p1 - p0)の算出
2)同様に、p0→p2という向きのベクトルv2(= p2 - p0)の算出。
3)v2からv1への外積v2×v1の算出
4)外積の長さの算出
5)外積をその長さで割り、正規化する。  

※glEnable(GL_NORMALIZE)とすれば法線ベクトルを単位ベクトルにする必要はないようです。

今回の場合は、以下なので
0.0f, 1.0f, 0.0f, //頂点0 (上)
0.0f, 0.0f, 0.0f, //頂点1 (左下)
1.0f, 1.0f, 0.0f, //頂点2 (右上)

1) p1-p0 = 0.0f, -1.0f, 0.0f
2) p2-p0 = 1.0f, 0.0f, 0.0f
3)外積は以下で求めると、
 -1*0-0*0,0*1-0*0,0*0-(-1*1)=0.0f, 0.0f,1.0f
 となる。




なので、

4) 外積の長さは以下のようにすでに1なので、単位ベクトルになっている。

ので、

glNormal3f(0.0f, 0.0f, 1.0f)

※四角形の場合は三角形2つに分割して、その三角形2つの面法線ベクトルを平均化するらしい
※三角形の場合はなくても描画できました。

Step4. 描画

glDrawArrays(int mode,int first,int count)を使って描画します。
描画する面に対してglNormal, glDrawArraysをペアで設定する必要があります。
三角形の場合は1つでよいが立方体の場合は6面あるので、6ペア必要です。

変数 意味
mode 描画方法
first はじめに描画する頂点番号
count 描画する頂点数

今回の場合は三角形を塗りつぶしたいので、以下でいいようです。

glDrawArrays(GL10.GL_GL_TRIANGLES, 0, 3);

参考
http://sky.geocities.jp/freakish_osprey/opengl/opengl_normalvecotr.htm
http://opengl.softwarecarpenter.biz/?eid=1075451
http://atelier-yoka.com/dev_android/p_main.php?file=apigl10gldrawarrays

2015年6月21日日曜日

stackeditでのflow図に関して

stackeditでのflow図に関して

StackEditでの図の書き方

StackEditはフローチャート描画用のflowchart.jsとシーケンス図用のjs-sequence-diagrams.jsが用意されているのでテキストで描画することができます。
描画関係でいろいろ調べるとmermaid.jsが良さそうですが、StackEditは対応していないので、残念です。

フローチャート

基本的には、以下の手順。

Step1. “エイリアス名=>図の種類: コメント”という塊をつくる。
コメントの後には:>httpとすることでリンクをつけることもできる。

部品 図の種類
始点端子 start
終了端子 end
処理部品 operation
判断部品 condition
定義済み処理部品 subroutline
入出力部品 inputoutput

Step2. 作成したエイリアスを接続する順番を記載
上記で動作を記載した後、1行開けてエイリアス名を”->”で接続していく。

[矢印の向き]
右から線を出したい場合: (right)、
左から線を出したい場合: (left)
をエイリアス名の後に記載。

[confitionの処理]
エイリアス名の後に(yes),(no)を記載し、その後の処理を->でつないでいく。矢印の向きも合わせて指定

以下に例を示しておきます。

例1.

 ```flow
 st=>start: 処理開始
 e=>end: 処理終了
 op1=>operation: テスト
 op2=>operation: 補習
 io1=>inputoutput: 点数入力
 cond1=>condition: 点数>80
 cond2=>condition: 点数>70
 cond3=>condition: 点数>60
 sub1=>subroutine: 合格
 (※2):>http://www.google.com
 sub2=>subroutine: 不合格

 st->op1->io1->cond1
 cond1(yes)->sub1
 cond1(no,right)->cond2(no,right)->cond3
 cond2(yes)->op2->sub1
 cond3(yes,right)->op1
 cond3(no)->sub2
 ```
Created with Raphaël 2.1.2処理開始テスト点数入力点数>80合格(※2)点数>70補習点数>60不合格yesnoyesnoyesno

例2.

 ```flow
 io1=>operation: A
 io2=>operation: B
 io3=>operation: C
 io4=>operation: D

 io1(right)->io2->io3(right)->io4
 ```
Created with Raphaël 2.1.2ABCD

シーケンス図

以下のコマンドを使って各項目を接続していきます。
コメントで改行したい場合は、\nを入れること。
また、接続は自分自身に接続することも可能です。

内容 コマンド
タイトル Title:
AからBへ実線三角矢印で接続 A -> B: 説明
AからBへ実線矢印で接続 A ->> B: 説明
AからBへ破線三角矢印で接続 A –> B: 説明
AからBへ破線矢印で接続 A –>> B: 説明
コメント(軸の右側) Note right of 軸名: コメント
コメント(軸の左側) Note left of 軸名: コメント
コメント(軸の上) Note over of 軸名: コメント
 ```sequence
 Title: フローチャート
 Note over Class A: function A1
 Class A->>Class B: アプリ起動
 Note over Class B: function B1
 Class B->Class C: テストA
 Class C-->Class B: OK
 Note over Class A: function A2
 Class A-->>Class D: 
 Class D->Class D:関数D1\nここで実験する。
 Class D->Class D:関数D2\nここで結果。
 ```
Created with Raphaël 2.1.2フローチャートClass AClass AClass BClass BClass CClass CClass DClass Dfunction A1アプリ起動function B1テストAOKfunction A2関数D1ここで実験する。関数D2ここで結果。

2015年6月15日月曜日

GoogleサンプルでAndroidアプリを学ぶ(MediaEffects)

GoogleサンプルでAndroidアプリを学ぶ(MediaEffects)

[開発環境]
 Android Studio
[使用したサンプル]
 MediaEffects
[機能]
画像の効果

※Logはなしとしました。
 よって、MainActivityのextendsはFragmentActivityとしました。

なんか1行ずつ分からないので調べていると時間がかかりますが、
意味を理解しながらでないと意味がないと思うので、少しずつ調べていきたいと思います。
Open GL関係は分からないことだらけなので次回にしたいと思います。


フォルダ構成をサンプルと合わせる

ソースが置いてあるフォルダをサンプルと同じApplicationにしたら
ビルドできなくなりました。以下の2つをすることでビルドできました。

  1. settings.gradleで
    include ‘app’ -> include ‘Application’
  2. Build -> clean Project
  3. RUN

savedInstanceState

今までonCreateにあるsavedInstanceStateをあまり気にせずにやっていました。
調べてみるとsavedInstanceStateは前回終了時の状態を保持する変数で最初は、nullが格納されているということ。
ということで以下のように最初の起動のときだけのような処理が必要っぽい。

if (savedInstanceState == null) {}

せっかくなので、もう少し調べてみるとsavedInstanceStateは、superのonCreateにも
渡している。ここでsuperはextendsした親のクラスで親のクラスのonCreateも同様に処理するというようにしている。
これがないとこのクラスのonCreateしか処理されなくなり、よくないらしい。
(具体的な理由は見つかりませんでした。)

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

onSaveInstanceState(Bundle outState)

自分のアプリに戻ったときに、前の状態には自動で戻れないので、その状態を意識的に保存する必要がある。STATE_CURRENT_EFFECTという文字列に
現在のEffectの値を入れておく。

その逆にSTATE_CURRENT_EFFECTという文字列から値を取り出すには、
getInt(STATE_CURRENT_EFFECT)。

private static final String STATE_CURRENT_EFFECT = "current_effect";
@Override
public void onSaveInstanceState(Bundle outState)
{
  outState.putInt(STATE_CURRENT_EFFECT, mCurrentEffect);
}

containsKey

特定のキーが含まれているかを確認するメソッド。
含まれていればTrue。

Fragmentのライフサイクル

何回かFragmentをやってきてましたが、少しふみこんで調べてみたところ最低でも以下3つは必要と
記載されてましたが、サンプルを見るとonCreate()とonCreateView()しかないのですが、動いてはいます。

onCreate()
onCreateView()
onPause()

参考
http://www.techdoctranslator.com/android/guide/activities/fragments

Open GLのエラー

AVD Managerのエミュレータで実行していたときに以下のようなエラーがでてハマりましたが、
実機を使うことで解決しました。
一旦、実機で試すことにします。

06-14 10:50:19.598    3848-3863/com.example.android.mediaeffects E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 167
    Process: com.example.android.mediaeffects, PID: 3848
    java.lang.IllegalArgumentException: No config chosen
            at android.opengl.GLSurfaceView$BaseConfigChooser.chooseConfig(GLSurfaceView.java:869)
            at android.opengl.GLSurfaceView$EglHelper.start(GLSurfaceView.java:1023)
            at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1400)
            at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)

メニューがでない

なぜかメニューがでないので調べたところ以下の2点の修正が必要でした。
1. MainActivityのextendsがFragmentになっていた。
 ActionBarActivityがdeprecatedだったのでFragmentActivityにしていたのが
 問題であり、以下にあるようにAppCompatActivityにする必要があった。

https://developer.android.com/intl/ja/reference/android/support/v7/app/ActionBarActivity.html
2. styles.xmlでThemeがAppCompatになっていなかったので以下のように修正。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
</style>
    <!-- Activity themes -->
<!--
    <style name="Theme.Base" parent="android:Theme.Light" />
    <style name="Theme.Sample" parent="Theme.Base" />
    <style name="AppTheme" parent="Theme.Sample" />   -->

その他

setHasOptionsMenu

Fragment でメニューを追加する場合は必ず setHasOptionsMenu(true)をつける必要があるらしい。おまじない。
onCreateで定義。

@Nullable

onCreateViewをオーバーライドしたら@Overrideに加えて@Nullableもついてきた。
意味としてはNullも許されるということらしい。
サンプルでは引数のViewGroup containerとBundle savedInstanceStateに@Nullableがついていたが、メソッド自身につけられるらしい。

inflate

レイアウトXMLファイルからViewを生成するときにはinflate()を使う。
attachRootをfalseとすることでR.layout.fragment_media_effectsがルートビューとなる。
trueの場合はcontainerがルートビューとなる。

inflater.inflate(R.layout.fragment_media_effects, container, false);

enter image description here

onViewCreated(View view, @Nullable Bundle savedInstanceState)

onCrearedViewが返された事をFragmentに知らせる。
viewを引数に持っているのでfindViewByIdに割り当てる。

参考
http://qiita.com/kkkaaakkku/items/97ef17ab6a7f7b4e365d

setEGLContextClientVersion

OpenGL ESのバージョンを指定する。
サンプルでは2だが、
Android 4.3からはOpenGL ES 3.0対応したらしい。

setRenderer(@Nullable GLSurfaceView.Renderer renderer)

レンダラーをセット。このサンプルでは自分自身なのでthis

setRenderMode(int rendermode)

レンダラーモードの設定。

変数 意味
RENDERMODE_CONTINUOUSLY 連続描画モード(毎フレーム)
RENDERMODE_WHEN_DIRTY 必要な時だけ描画

2015年6月13日土曜日

GoogleサンプルでAndroidアプリを学ぶ(SlidingTabsBasic)

GoogleサンプルでAndroidアプリを学ぶ(SlidingTabsBasic)

前回、ActionBarCompat-Styledを置き換えようとしたSlidingTabsBasicをやってみました。

[開発環境]
 Android Studio
[使用したサンプル]
 SlidingTabsBasic
[機能]
 デザインのみ。

※view/SlidingTabLayout、SlidingTabLayoutはpackage名を変えてそのまま使うことにしました。
※Logとかはとりあえずそのまま使いました。
※残念ながらメニューがうまくでない。。。


Packegeを作る

このサンプルでは、Common\activiesという階層にSampleActivityBase.javaというファイルを置いていたので、
javaが選択された状態でNew->Packegeでjavaを選択し、OK。
enter image description here

common.activitiesを作成する。
enter image description here

デフォルトコンストラクタ

LogWrapperクラスには、コンストラクタが定義されていないが、コンストラクタが1つも定義されていない場合は、
デフォルトコンストラクタと呼ばれる引数無しで中身が空のコンストラクタが自動で生成されるらしいので問題ないらしい。

参考
http://www.javadrive.jp/start/constructor/index4.html

Interface

インタフェース は、ある機能を実現するクラスが必ず実装するべきメソッドの名前や型といった作法のみを定義するもの。
インタフェースで定義されるメソッド(抽象メソッド)の実体は implements を用いた側のクラスで実装する必要がある。

public interface LogNode {
    public void println(int priority, String tag, String msg, Throwable tr);

}

public class MessageOnlyLogFilter implements LogNode {
}

実際にMessageOnlyLogFilterを作ってみると以下のようにinterfaceで定義したprintlnを宣言しなければいけない
とコメントがでる。 

enter image description here

drawable/tileでエラー

サンプルを真似してstyles.xmlにコーディングしていたが、以下のところでdrawable/tileがないと怒られた。

<item name="android:background">@drawable/tile</item>

テキストエディタでdrawableを検索するとオリジナルのSlidingTabsBasic/Application/build/intermediates/symbols/debug/R.txtに以下の記載がある。
int drawable tile 0x7f020001

R.txtにこれを記載する方法がわからないので、オリジナルをAndriod Studioで開いてみたところ以下のようにdrawableの下にtile.9.pngが置いてあった。

これを同じようにすればよいと思い、
SlidingTabsBasic/Application/src/main/res/drawable-hdpiに
tile.9.pngが置いてあったのでAndroid StudioでdrawableにコピーしようとDrag & Dropしたができない。。。
enter image description here

ツリービューを以下のようにProjectに変えればdrawableにDrag & Dropでコピーすることができました。そしてdrawable/tileのエラーも消えました。
enter image description here

enter image description here

FragmentTransaction

Fragmentを切り替えて画面遷移を表現する場合には、以下のように別で作成したものを置き換える。

 FragmentTransaction transaction = 
                getSupportFragmentManager().beginTransaction();
 SlidingTabsBasicFragment fragment = new SlidingTabsBasicFragment();
 transaction.replace(R.id.sample_content_fragment, fragment);
 transaction.commit();

イメージとしては以下のような感じが気がする。
enter image description here

その他

android:textSize

単位 略 例
px pixels 画面上のPixelがそのままの単位になる
dp(dpi) Density-independent Pixels ディスプレイ解像度の物理的な密度に応じた抽象単位
sp Scale-independent Pixels ユーザーのフォントサイズの設定により伸縮される。フォントサイズの指定では推奨される単位

9 patch

drawableにtile.9.pngを追加したがそもそも9.pngという拡張子を初めて見た。

9 patchというものらしく、画像が拡大される際に拡大される領域とそうでない領域を指定するものらしいです。

参考
http://d.hatena.ne.jp/tomorrowkey/20110501/1304245217

android:shadowColor

影の色

android:shadowDy

影をY方向にどれだけずらすか。負の値も指定可能。

android:shadowRadius

影の半径。大きいほどぼやける。

Widget.SampleMessage

????

android:lineSpacingMultiplier

改行時のテキストの行間の余白の高さの指定とのこと。

<item name="android:lineSpacingMultiplier">1.1</item>

transaction.replace

以下のようにしたが、Wrong 2nd argument type.というエラーがでている。
調べてみると、android.support.v4.app.Fragmentではなく、android.app.Fragmentがimportされていたので修正したら
エラーが消えました。
//import android.app.Fragment;
import android.support.v4.app.Fragment;

 SlidingTabsBasicFragment fragment = new SlidingTabsBasicFragment();
 //activity_main.xmlで定義したFrameLayoutをSlidingTabsBasicFragmentに取り替える。
transaction.replace(R.id.sample_content_fragment,fragment);

enter image description here

android:showAsAction=”always”

menu_main.xmlにandroid:showAsActionを記載したが以下のようにエラーになった。

enter image description here

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
    <item android:id="@+id/menu_toggle_log"
        app:showAsAction="always"
        android:title="@string/sample_show_log" />
</menu>

instanceof

logToggle.setVisible(findViewById(R.id.sample_output)instanceof ViewAnimator);

の意味が分からないので調べたところ、

findViewById(R.id.sample_output)がViewAnimatorだったら、
Trueということになります。

activity_main.xmlで以下のように宣言しているので当然Trueですが。

    <ViewAnimator
          android:id="@+id/sample_output"

setDisplayedChild

表示するためのChild viewを設定する。
以下のようになってるけど、どれが1?

if (mLogShown) {
    output.setDisplayedChild(1);
} else {
    output.setDisplayedChild(0);
}

2015年6月8日月曜日

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-Styled)

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-Styled)

[開発環境]
 Android Studio
[使用したサンプル]
 ActionBarCompat-Styled
[機能]
デザインのみ。


途中までやったが、以下理由によりこのサンプルは中断。

・deprecatedなクラスがあり、調べたがすんなりと置き換えがうまくいかない。
・SlidingTabLayoutに置き換えようとしたがそれ自身はSlidingTabsBasicのサンプルにあるので、
それをベースに考えたほうが無駄がない。


ActionBarActivityが取り消し線に

ActionBarActivityが以下のように取り消し線になってました。
enter image description here

調べてみるとAndroid Support Libraryの22.1から以下のようにdeprecatedなので、AppCompatActivityを代わりに使えとのこと。
enter image description here

AppCompatActivityに書き換えたら今度は赤くなっている。
enter image description here

Alt+Enterを押すことでimportにandroid.support.v7.app.AppCompatActivityが追加されて解決。

setNavigationModeが取り消し線に

setNavigationModeが取り消し線になっていたので、Google Developersで調べたところ以下のようにdeprecatedになってました。
enter image description here

置き換えの例がないのでどうしたらいいのか悩んでいたところ
SlidingTabsで置き換えるとが近いらしく、Android Developerのサンプルにもあるようなのでこれを参考にしてみました。

Step1. Google DeveloperのSlidengTabsBasicの
/SlidingTabsBasic/Application/src/main/java/com/example/android/common/viewにある以下の2つのファイルを新しいプロジェクトにコピー。

SlidingTabLayout.java
SlidingTabStrip.java

※packageはコピー先のMainActivityと同じpacakgeに修正する。
//package com.example.android.common.view;
package com.example.xxx.yyyyy;

以下を参考にしたがタブの画面がでてこないので中断。

参考:
http://qiita.com/nein37/items/b869193ee583a96f86a8

2015年6月7日日曜日

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-ShareActionProvider)

GoogleサンプルでAndroidアプリを学ぶ(ActionBarCompat-ShareActionProvider)

しばらくぶりにAndroidの勉強をしようと思い、Googleのサンプルから始めることにしました。
勉強の仕方としては、サンプルを参考に、1からプロジェクトを作ってサンプルを移植していきます。
いつまで続くかわかりませんが。。

[開発環境]
 Android Studio
[使用したサンプル]
 ActionBarCompat-ShareActionProvider
[機能]
 ・ページを切り替えるとテキストとassetsに格納された画像の表示を切り替える。
 ・表示されているコンテンツを他のアプリとShareする。

学んだことを記載します。

Assets

Assetsフォルダの追加

このサンプルではassetsフォルダにある画像を表示しておりますが、Android Studioにはassetsフォルダ自身が作成されてません。なので以下の手順でassetsフォルダを作成しました。

Step1. 表示を「Android」から「Project」へ変更
enter image description here

Step2. app\mainで右クリックし、「New」→「Directory」でassetsを作成
enter image description here

Step3. ファイルブラウザで作成したassetsフォルダに画像をコピー

Assetsフォルダのファイルへのアクセス

少しハマったので記載しておきます。
このサンプルはコンテンツを他のアプリとのShareすることを目的としているため、以下のようにContentProviderを拡張したクラスを作ってます。

public class AssetProvider extends ContentProvider

本来ならば以下のようにAssetManagerを使えば取得できるらしいのだが、できなかった。

AssetManager am = getContext().getAssets();

調べてみるとContentProviderを拡張したクラスを使っているため、AndroidManifest.xmlに
providerを追加する必要があった。

<application
  <activity
  </activity>
  <provider  
   android:authorities="com.example.android.actionbarcompat_shareactionprovider"
   android:name=".content.AssetProvider"/>
</application>

他のアプリとのShare(Intent)

enter image description here
のアイコンを出すために以下が必要。

Step1. menu_main.xmlに以下を追加する。

<menu 
    xmlns:support="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_share"
        android:title="@string/menu_share"
        support:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        support:showAsAction="always" />
</menu>

Step2. onCreateOptionsMenuの修正
ShareActionProviderはv7.widegetのほうをimportする必要があるので注意が必要。

イメージとしては以下のような感じな気がする。

enter image description here

//import android.widget.ShareActionProvider;
import android.support.v7.widget.ShareActionProvider;

private ShareActionProvider mShareActionProvider;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        MenuItem shareItem = menu.findItem(R.id.menu_share);
        mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem);

    // 今、Viewpagerに表示されているものをIntentする。
        int currentViewpagerItem = ((ViewPager)findViewById(R.id.viewpager)).getCurrentItem();
        setShareIntent(currentViewpagerItem);

        return super.onCreateOptionsMenu(menu);
    }

    private void setShareIntent(int position) {
        if (mShareActionProvider != null) {
            ContentItem item = mItems.get(position);
            Intent shareIntent = item.getShareIntent(MainActivity.this);

            mShareActionProvider.setShareIntent(shareIntent);
        }
    }
[ContentItem.java]
  public Intent getShareIntent(Context context) {
        Intent intent = new Intent(Intent.ACTION_SEND);

        switch (contentType) {
            case CONTENT_TYPE_IMAGE:
                intent.setType("image/jpg");
                intent.putExtra(Intent.EXTRA_STREAM,getContentUri());
                break;
        }

        return intent;
    }

PagerAdapter

ViewPagerに表示するための仕組みがよくわからなかったので、簡単な図にしてみました。
ViewPagerで表示する中身を生成するためのAdapter(PagerAdapter)を使ってます。

enter image description here

暗黙的Intent

今回使用したのは暗黙的Intentであり、他のアプリと連携するために使用する。
宛先となるオブジェクトを明示的に指定せずに所定の動作、データのみを指定する。
これによりAndroidシステムが該当するオブジェクトをシステム全体から検索し、起動するしくみ。

それと対象に明示的Intentは画面遷移などアクティビティーから他の指定したアクティビティーへ送るIntent。

今回の場合は以下。
・Intentのコンストラクタでアクション(Intent.ACTION_SEND)を
指定してインスタンスを生成。

・setTypeでインテントにカテゴリを付加し、
 putExtraでデータの種類とデータを渡している。
 

[参考]
http://www.sakc.jp/blog/archives/24833

その他

No files are open

Android Studioでプロジェクトを開いたら以下のようにNo files are openとでてファイルが開かなくなっていたが、左側の1: Projectを押せば復活しました。
enter image description here

getCurrentItem

Viewpagerで現在のページ位置を取得する場合には以下で取得可能。

int currentViewpagerItem = ((ViewPager)findViewById(R.id.viewpager)).getCurrentItem();

android:textAppearance

xmlでテキストのスタイル定義の設定を指定する。

要素 説明
?android:textAppearanceSmall 小さいサイズ
?android:textAppearanceMedium 普通のサイズ
?android:textAppearanceLarge 大きいサイズ

[参考]
http://androidguide.nomaki.jp/html/widget/textview/fontsize.html

setOnPageChangeListenerが取り消し線になっている

ViewPagerでsetOnPageChangeListenerを使おうとしたら以下のように取り消し線になってました。
enter image description here

Google Developerで調べてみると以下のように別のを使えということなので、addOnPageChangeListenerを使いました。

enter image description here

android:scaleType

画像サイズの設定を指定する。

ScaleType 画像サイズ 表示位置
CENTER サイズ変更なし 中央
CENTER_TOP ボタンの横幅いっぱいに拡大 中央
FIT_CENTER ボタンの縦幅いっぱいに拡大 中央
FIT_END ボタンの横幅いっぱいに拡大 右寄せ
FIT_START ボタンの縦幅いっぱいに拡大 左寄せ
FIT_XY ボタンの横幅いっぱいに拡大

android:lineSpacingMultiplier

改行時のテキストの行間の余白の高さを指定します。
android:lineSpacingMultiplier = “0.8”

ViewPagerのレイアウト

ViewPagerは全画面で設置することが想定されているのか、wrap_contentをサポートしておらず、 android:layout_height=”wrap_content”とすると、高さが0になってしまうとのこと。

高さが設定できないので、layout_weightを使う。

LayoutInflater

以下とのことです。

Androidのプログラミングでは、画面のViewを構成する場合、layout用xmlファイルを用いて、レイアウトを作成することが推奨されている。
しかし、xmlファイルを用いた場合、それは、静的にレイアウトが決定付けられてしまい、プログラムの実行時にレイアウトを変形することはできない。
この不都合を回避するため、LayoutInflater Classが用意されており、このクラスを活用することにより、実行時にお好みのレイアウトに変形できる。

[参考]
https://sites.google.com/site/androyerjapan/home/layoutinflater

Error:Execution failed for task ‘:app:compileDebugAidl’. > aidl is missing

Runしたら以下のようなエラーがでた。

#!

Information:Gradle tasks [:app:assembleDebug]
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72220Library UP-TO-DATE
:app:prepareComAndroidSupportSupportV42220Library UP-TO-DATE
:app:prepareDebugDependencies
:app:compileDebugAidl FAILED
Error:Execution failed for task ':app:compileDebugAidl'.
> aidl is missing
Information:BUILD FAILED

ビルドツールがあっていないのではということでapp\build.gradleを確認すると
以下のようにbuildToolsVersion “23.0.0 rc1”となっていた。

#!java

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "23.0.0 rc1"
    defaultConfig {
        applicationId "com.example.takashin10.actionbarcompat_shareactionprovider"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }

[対策]
1. [Tools] -> [Android] -> [SDK Manager]
2. Tools (Preview Channel)を見るとbuildToolsVersionで指定している23rc1がNot installed
 になっているので、チェックし、Install
範囲を選択_120.png
3. Android Studioを再起動

しかし、以下のようなエラーがまだでている。
Failed to find Build Tools revision 23.0.0 rc1

[SDK Manger]で確認するとAndroid SDK Build-toolsは23.0.0 rc2になっていた。
範囲を選択_122.png

app\build.gradleをbuildToolsVersion “23.0.0 rc2” に変えることでエラー回避できた。