Little Strange Software

スマホアプリの開発を行う LittleStrangeSoftware のブログです。

Androidアプリ開発初心者がkotlinでカラーピッカーを作ってみるよ! その4

 

 どうも!LSSです!

 前回の「その3」でいったん完成を見たカラーピッカーですが、その4からは機能追加を検討していきたいと思います!

 

まず、アイデアを出します

 いくつか、考えてる事はあります。

 列挙すると…

  • 気に入った色が出来た時に、ボタンを押すと「お気に入りの色」としてSQLiteデータベースに登録され、アプリを閉じて再度起動した後からでも「お気に入りの色」が一覧で確認、また再度シークバー・EditText・背景色に取り出せる。
  • 現状、色の設定はシークバーからのみですが、EditTextに直接打ち込んでも、シークバー・背景がそれに追従して変化する。
  • 赤緑青の比率を保ったまま、「暗くする」または「明るくする」事ができるようにする。
  • 一つめの「お気に入りの色」とは別に、数秒以上変更を加えなかった色は自動的に、それ用の履歴として記録する。
  • ランダムな色を提案してくれる機能。
  • 現在の設定色に近い色を提案してくれる機能。
  • 現在の色から遠く離れた、つまり目立ちやすい色を教えてくれる機能。

 

 こんなところでしょうか。

 全て実装・そしてその記事を書くかどうかは未定ですが、「お気に入りの色」や「履歴」機能のためにはまず、SQLiteデータベースを取り扱う必要がある事。
 また、「履歴」の実装が上記のような条件であれば、タイマーを使う必要が出てきますね。

 

 ですが、機能追加の前に、現在の仕様について、見直し・コード修正を行う必要がある事に気づきました。

 

予想できる問題点

 現在の仕様は「シークバーのツマミが変更された時」に、EditTextを変更し、背景色を変更する、という処理の流れになっています。

 ここで、「EditTextが変更された」場合のイベントリスナーを定義し、それによってシークバーを変更し、背景色を変更する、という処理を組んだ場合…その処理によってシークバーのイベントリスナーが発動し、その処理としてEditTextに変更が生じ、またそのイベントリスナーによってシークバーが…という無限ループになっちゃわないか?という点。

 これについては、イベントリスナーの中に「ユーザーによる変更か否か」っていう判定が組み込めるようですので、それで対処できそうです。

 

~閑話休題~裏作業で苦労した話

 いやぁ…記事を書く前に、別に同様のプロジェクトを作って、そっちで実験したりしている際にドハマリした事があったので、一応、ここに記録として残しておきます。

>赤緑青の比率を保ったまま、「暗くする」または「明るくする」事が
>できるようにする。

の部分を実現しようとしてた時に発生したのですが、xmlにボタンを配置して、そのonClickイベントに、onCreateの外に置いたfunを呼び出すようにして、

sbR.progress=(sbR.progress * 0.9).toInt()
sbG.progress=(sbG.progress * 0.9).toInt()
sbB.progress=(sbB.progress * 0.9).toInt()

のようにしていたんですね。(これは比率を保ったまま色を暗くするコード例)

 で、それは問題なく動いたんですが、ふと、
「これもsb.forEachのループで処理できるんじゃないかな?」と思い、

 sb.forEach() {
it.progress = (it.progress * 0.9).toInt()
}

のように書いたところ、sbを認識してくれなかったんです。

「…ああ、そっか!
 sbを定義してるのがonCreate内だから、onCreateの外からでは使えないんだ!」

と気づき、

val sb=listOf(sbR,sbG,sbB)

をonCreateの外に置いてビルドすると…今度はビルドは問題なくできたのに、エミュレータ上で画面が出る前にアプリが強制停止する、という問題が発生し、小一時間悩みました(^^;;;。

 で、たどり着いた結論は、

  • onCreateの外側にまず、「lateinit var sb:List<SeekBar>」と書く。
    sbはSeekBarを入れるListとして使いますよ、って宣言だけ、onCreateの外側で
    行う事によって、onCreateの外でもsbが扱えるようにするんですね。
    valをvarにしないといけなくなってしまいましたが、そこは特に困らないからいいや。
  • onCreate内で「val sb=listOf(sbR,sbG,sbB)」と書いていた部分を、
    「sb =listOf(sbR,sbG,sbB)」に書き換える。(最初のval削っただけですね)

 この2か所の変更で、onCreateの中でも外でも、sbがシークバーの配列として使えるようになりました。

「sbという配列はonCreateの外で宣言しないといけない、
 けど、宣言時にsbRとかのxml上のパーツをセットするのはonCreateでxml
 読み込んだ後でないといけない(setContentView(R.layout.activity_main)かな?)」
という事かと、とりあえず納得。

「lateinitってこういう時に使うんだ!!」と、なんとなく存在だけは知っていた要素の使いどころが分かってスッキリしました、というお話です。

 このブログで扱ってるプロジェクトに反映する時は、改めてまたサラッと手順だけ書きますね。

 

短いですが、今回はここまで!

 肝心の進行中のプロジェクトは全く触っていませんが、今回 の記事はここまで!

  もうちょっと考えをまとめてから、プロジェクトを進めていきたいと思います。

 次回、またよろしくです^^