ダイアログを表示する

FloatingActionButtonをタップして、ダイアログを表示させます。

今回は左図の右下のボタンを押すと、右図のようにダイアログが表示されるアプリを作りました。
f:id:imoto-yuya-1234:20170823003940p:plain f:id:imoto-yuya-1234:20170823225747p:plain

ソースコードgithubにあげました。
github.com
33a2a47c5afeed6aede84a0b790afa529f5f858d


まずはダイアログのクラスを作ります。ネットで探すとAlertDialogを使って〜という記事が多いですが、この記事ではDialogFragmentを継承して、下記のようにカスタムダイアログクラスを作成しました。

class AddListDialog: DialogFragment() {

    companion object {
        fun newInstance(): AddListDialog {
            val instance = AddListDialog()
            return instance
        }
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState)
        return dialog
    }

    override fun onCreateView(i: LayoutInflater, c: ViewGroup?, b: Bundle?): View? {
        val content: View = i.inflate(R.layout.add_list_dialog, c)
        return content
    }
}

FloatingActionButtonから以下のメソッドを呼び出すことで、ダイアログを表示します。

private fun displayDialog() {
    val newFlagment = AddListDialog.newInstance()
    newFlagment.show(fragmentManager, "dialog")
}

ダイアログ関連

ダイアログクラスのコンストラクタはnewInstanceメソッドを使う必要がありました。
ダイアログの動作はonCreateDialogメソッドとonCreateViewメソッドで定義します。
onCreateDialogメソッドでダイアログコンテナを作成して、onCreateViewメソッドでコンテンツを生成するとかっこいいみたいです。ただ今調べている感じだと、onCreateDialogメソッドで全部やった方が簡単そうです。

kotlin関連で学んだこと

・staticメソッドを実装するにはcompanion objectを使用すること
・nullが入る場合は?で明示すること
 onCreateViewメソッドのViewGroupとBundleにはnullが入るらしく、?をつけないとエラーになりました。

FloatingActionButtonのアイコンを変更する

今回はAndroid Studioに用意されたアイコン(addアイコン)に変更します。

まずは左端のプロジェクトウィンドウ選択して、app配下のresを右クリックして、[New]->[Vector Asset]をクリックします。

f:id:imoto-yuya-1234:20170819002123p:plain

すると、アイコンの選択画面に遷移するので、Iconのドロイドくんをクリックして、違うアイコンを選択します。

f:id:imoto-yuya-1234:20170819002211p:plain

色々なアイコンがあります。検索でaddを入力して、候補を絞ります。目当てのアイコンがあったので、選択します。

f:id:imoto-yuya-1234:20170819002512p:plain

このようにプラスのアイコンを選択できました。

f:id:imoto-yuya-1234:20170819002642p:plain

あとは[Next]->[Finish]でres/drawableに保存されるので、xmlファイルでこのアイコンファイル(ic_add_black_24dp)を指定すればよいです。

アイコンの色を黒から白に変更します。ic_add_black_24dp.xmlのfillColorの値を変えることで色を変更できます。

android:fillColor="#FF000000"

android:fillColor="#FFFFFFFF"

FloatingActionButtonを実装する

表題の通り、FloatingActionButtonを実装します。
Empty projectを起点にしました。

まずはMainActivityのonCreate()で

var AddListButton: FloatingActionButton? = findViewById(R.id.addbutton)
AddListButton?.setOnClickListener {view ->
    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
            .setAction("Action", null).show()
}

次にactivity_main.xmlファイルにaddbuttonを追加します。

<android.support.design.widget.FloatingActionButton
        android:id="@+id/addbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:srcCompat="@android:drawable/ic_dialog_email" />

ここでaddbuttonは画面の右端に設置したいので、layout_constraintBottom_toBottomOfとlayout_constraintRight_toRightOfを指定しました。ConstraintLayoutではこのように設定するようです。はじめはlayout_gravityで設定しようとして、うまくいきませんでした。

この変更で画面右下にFloatingActionButtonを実装できます。
Buttonを押すと下から"Replace with your own action"という表示が出ます。

githubにソースをアップしましたので、参考にしてください。
アップしたソースはFloatingActionButtonにマージンを設けて、またアイコンもメールのアイコンからプラスのアイコンに変更しています。

github.com
SHA: 50eabf64cda98bd3e99c951a5b20987b2e3a82f0

FloatingActionButtonがunresolved

KotlinでFloatingActionButtonを実装しようとしたら、unresolvedになりました。
結局、Kotlinは関係なかったのですが、少し困ったので、記録を残したいと思います。

Android StudioでEmpty Projectを作成して、FloatingActionButtonを実装しようとしました。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        var AddListButton: FloatingActionButton? = findViewById(R.id.addbutton)
    }
}

ところが、FloatingActionButtonなんてないよ!と怒られます。
色々頭を悩ませた結果、android.support.designライブラリを追加していないことに気づきました...
初めてのときはここでつまずかなかったので、ライブラリを追加する必要があることをすっかり忘れていました。

以下の対応で解決します。
kimagureneet.hatenablog.com

ことりん

いまさらですが、Androidアプリの開発言語にKotlinが正式採用されましたね。
検索するとすごくいいらしいので、これからの開発はKotlinでやっていこうと思います。
なので、最近ぼちぼち勉強中です。

試しに以下の記事を参考に(ほぼコピペ)、ストップウォッチアプリを作りました。
employment.en-japan.com

私の環境ではこのままでは動かず、以下のように修正しました。

修正前

// View要素を変数に代入
val timeText = findViewById(R.id.timeText) as TextView
val startButton = findViewById(R.id.start) as Button
val stopButton = findViewById(R.id.stop) as Button
val resetButton = findViewById(R.id.reset) as Button

修正後

// View要素を変数に代入
val timeText = findViewById<TextView>(R.id.timeText)
val startButton = findViewById<Button>(R.id.start)
val stopButton = findViewById<Button>(R.id.stop)
val resetButton = findViewById<Button>(R.id.reset)

修正後は記事の通りに動いています。
一応、githubにupしました。これを元に何か作っても面白そう。

github.com

BounceBall#05 ボールを反射させる

ボールが四角に衝突したときの反射について考えます。

f:id:imoto-yuya-1234:20170720220739p:plain:w350

上の図のよう各々のベクトルが決められたとき、ボールの進行ベクトル{\bf v}と反射ベクトル{\bf v'}、平行ベクトル{\bf p}でなされる大きな三角に着目すると求めたい{\bf v'}は下記の通りです。

{
{\bf v'} = 2{\bf p} - {\bf v} \tag{1} \label{1}
}

ここで{\bf v}は既知ですので、{\bf p}を求めればよいです。
{\bf v}{\bf p}、法線ベクトルの定数倍である{a{\bf n}}でなされる小さな三角に着目すれば、

{
{\bf p} = a{\bf n} + {\bf v} \tag{2} \label{2}
}

となるので、式\eqref{1}に代入して、

\begin{eqnarray}{\bf v'}&=&2( a{\bf n} + {\bf v}  ) - {\bf v}\\
&=&{\bf v} + 2a{\bf n} \tag{3} \label{3}\end{eqnarray}

が得られます。既知である反射面のベクトルからその法線ベクトル{\bf n}を求められるので、定数aがわかれば反射ベクトル{\bf v'}を求めることができます。

定数aを求めるために、再び{\bf v}{\bf p}{a{\bf n}}でなされる小さな三角に着目します。この三角形の内積三角関数の公式を用いれば、下記の2式が成立します。

\begin{eqnarray}-{\bf v} \cdot {\bf n}&=&|{\bf v}||{\bf n}|\cos\theta \tag{4} \label{4}\\
\cos\theta &=& \frac{a |{\bf n}|}{|{\bf v}|} \tag{5} \label{5}\end{eqnarray}

この2式から定数aが

\begin{eqnarray}a = - \frac{{\bf v} \cdot {\bf n}}{|{\bf n}|^2} \tag{6} \label{6}\end{eqnarray}

と求まるので、定数aを式\eqref{3}に代入して、反射ベクトル{\bf v}を導くことができました。

\begin{eqnarray}{\bf v'}&=&{\bf v} - 2 \frac{{\bf v} \cdot {\bf n}}{|{\bf n}|^2} {\bf n} \tag{7} \label{7}\end{eqnarray}

BounceBallではこの式を実装してボールの反射を制御しています。
ベクトル計算をしたのは高校以来で、懐かしい気持ちになりました。大分前ですが、案外覚えているものだと感心?しています。

あと、本筋とは違いますが、前回からの数式はTexコマンドで数式を書いています。大学の時にレボート、論文で使っていたので苦労せず記述できました。(はてなブログへのTexコマンド導入方法でかなり手こずりましたが...)当時は今時Texとかwordでいいじゃん、等々言われましたが、どこかで役に立つものですね。

BounceBall#04 ボールが四角に接触したことを検知する

前回までで四角を検出することとボールを動かすことができました。
次はボールが四角に接触するときを考えます。

ここでボールが四角に接触するとは、ボールと辺または角の最短距離がボールの半径以下であれば接触したと言えます。

そこで四角には4本の線分の内の1本について、線分ABとボールの中心点Cの最短距離dを考えます。この最短距離dがボールの半径以下であるかどうかを調べ、この試行を4本の線分に行えば、ボールと四角との当たり判定を行えます。

最短距離dについては三つのパターンがあります。

i)点Cから点Aの距離が最短距離dとなる場合

{
d = |C - A|
}
f:id:imoto-yuya-1234:20170704234757p:plain:w250

ii)点Cから点Bの距離が最短距離dとなる場合

{
d = |C - B|
}
f:id:imoto-yuya-1234:20170704234853p:plain:w250

iii)点Cから線分ABに対する垂線が最短距離dとなる場合

{
d = \frac{|(C - A) \times (B - A)|}{|(B - A)|}
}
f:id:imoto-yuya-1234:20170704234902p:plain:w220

導出は下記のサイトを参考にしました。
平面幾何におけるベクトル演算 » 直線と線分