iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

【Android】Material Components の TextField でカーソルの色を変えるには

おはようございます。本日も Android Material Components 周りで調べたことをメモがわりに書いておきます🏃🏻‍♂️

結論

Material ComponentsTextFieldcursor color は、どうやら設定されている Themeprimary になるそうです。

github.com

今回僕は該当する Activityprimary を設定していなかったので、Android(標準?) の primary が適用されていたそうです。ということで cursor color を変えるために Themeprimary を追加してみます。

    <style name="AppDarkTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
        <item name="colorPrimary">@color/fideeBlue</item>
        <item name="colorPrimaryDark">@color/fideeBlack</item>
    </style>

また、それ以外のカスタム属性(hint, inputTextColor, helperなど)は下記のドキュメントの通り、それぞれの attribute で設定できます。

material.io

今回は僕が使用したのは Filled text field というスタイルで、下記のような項目を atributes からカスタム設定できます。また、この他にも Outlined Text Field というスタイルのものもあります。

f:id:yum_fishing:20210110104009p:plain

参照: https://material.io/components/text-fields#filled-text-field

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【Swift】Date型で同じ年、月、週かどうかを取得できるようにする

今回はタイトルの通り SwiftDate 型で、2つの Date が同じ年、月、週かどうかを取得する方法を紹介したいと思います🏃🏻‍♂️

方法

とりあえずコードは下記のようになります。今回は DateExtension として定義しています。

extension Date {
    func isEqual(to date: Date, toGranularity component: Calendar.Component, in calendar: Calendar = .current) -> Bool {
        calendar.isDate(self, equalTo: date, toGranularity: component)
    }

    func isInSameYear(as date: Date) -> Bool {
        isEqual(to: date, toGranularity: .year)
    }

    func isInSameMonth(as date: Date) -> Bool {
        isEqual(to: date, toGranularity: .month)
    }

    func isInSameWeek(as date: Date) -> Bool {
        isEqual(to: date, toGranularity: .weekOfYear)
    }
}

2つの Date の比較は Calendarインスタンスメソッド isDate(_:equalTo:toGranularity:) で行います。isDate(_:equalTo:toGranularity:) はメソッド名の通り二つの Date 型が等しいかどうかをチェックするためのメソッドで、第3引数の Calendar.Component でチェックする粒度を指定することができます。今回は .year.month.weekOfYear を設定していますが、この他にも .hour.minute など時間単位で指定することもできます。詳しくはドキュメントを参考にしてみてください🦅

developer.apple.com

ちなみに、同じ日かどうかは下記のように取得することができます。

    func isInSameDay(as date: Date) -> Bool {
        Calendar.current.isDate(self, inSameDayAs: date)
    }

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【Android】Material Button で設定した app:cornerRadius で反映されない

下記を参考に MaterialComponentsButton で、角丸のボタンを作成しようとすると app:cornerRadius で指定した値が反映されず、角丸にならないという問題が発生していました。

stackoverflow.com

解決法

どうやら MaterialComponents を使用するには、親のテーマを material theme にする必要があるらしく、style.xml で定義している AppThemeTheme.AppCompat.Light.DarkActionBar から Theme.MaterialComponents.Light.DarkActionBar に変更したところ、app:cornerRadius の値が反映され Button を角丸にすることができました🚀

    <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

stackoverflow.com

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【Swift】YPImagePicker を使ってみた

iOSPhotoVideo のいい感じのピッカーライブラリを探していたところ、YPImagePicker というものを見つけたので使い方を紹介したいと思います🏃🏻‍♂️

github.com

使ってみる

今回は1~3枚の間で複数選択を有効にして、全て正方形の画像として取得できるようにしてみます。下記が実装のサンプルになります。screens で、フォトライブラリとカメラを選択していますが、ビデオも追加したい場合は、ここに .video を追加します。また、複数選択時に同じアスペクト比で出力できるのは正方形の場合のみなので onlySquare で、1:1アスペクト比のみを許容するようにしています。画像の取得は delegate 経由ではなく、didFinishPickingcompletionHandler で行います。

            var config = YPImagePickerConfiguration()
            config.library.maxNumberOfItems = 3
            config.library.minNumberOfItems = 1
            config.screens = [.library, .photo]
            config.startOnScreen = .library
            config.showsCrop = .rectangle(ratio: 1)
            config.library.onlySquare = true
            config.library.mediaType = .photo
            let picker = YPImagePicker(configuration: config)
            navigationController?.present(picker, animated: true, completion: nil)

            picker.didFinishPicking {[unowned picker, self] items, cancelled in
                let images = items.compactMap { item -> UIImage? in
                    switch item {
                    case .photo(let p):
                        return p.image
                    default: return nil
                    }
                }
                updateImagesAction(images)
                picker.dismiss(animated: true, completion: nil)
            }

インスタグラムのように異なるアスペクト比でも統一できる機能はいまのところないようなので、今後に期待したいですね🦅 (暇があったらコミットチャンス)

github.com

という感じで本日も以上になります。

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【iOS】Fastlane で iOS の Build Number をインクリメント

今日はタイトルの通り Fastlane で、Xcode プロジェクトの build number をインクリメントする方法を紹介したいと思います。

それではやっていきましょ

結論

まずは、build number をインクリメントするためのレーンを Fastfile に追記します。ensure_git_status_clean は、Fastlane Actions の関数の一つで、コミットしていない変更がある場合に例外を発生させます。increment_build_numbergit_commit も同様に Fastlane Actions の関数の一つでそれぞれ名前の通り、build number をインクリメントし、変更をコミットします。

  lane :build_number_bump do
    ensure_git_status_clean

    new_build_version = (read_build_version + 1).to_s
    increment_build_number(build_number: new_build_version)
    git_commit(message: "Update build version to #{new_build_version}", path: "Parnovi")
  end

現在の build number を取得する方法については、以前記事に書いたので気になる方は覗いて見てください。

yamato8010.hatenablog.com

def read_build_version
  version = (`cd .. && xcodebuild -showBuildSettings | grep CURRENT_PROJECT_VERSION | tr -d 'CURRENT_PROJECT_VERSION ='`).strip.to_i
  return version
end

あとは、任意のタイミングでレーンを実行すれば build number をインクリメントさせることができます。

$ bundle exec fastlane build_number_bump

という感じで本日は以上になります👷‍♀️

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【Android】dpってなんぞや

今回は Android アプリ開発において、なんとなくなぁなぁにしていた dp の理解を深めていきたいと思います✍️

f:id:yum_fishing:20210105122326p:plain

そもそもなんで px 単位じゃない?

iOS アプリ開発においてもこれは言えることですが、基本的にモバイルアプリの開発はマルチデバイスでのレイアウトを考慮した上で設計していく必要があります。同じ解像度の端末でもデバイスの大きさが違えば UI の見え方(大きさやパディング)が違います。

例えば、極端に大きいオセロ盤と極端に小さいオセロ盤があったとしましょう。この二つのオセロ盤で同じくらいの大きさのコマを作りたいと思った場合にマス一つ分の大きさを基準にコマを作った場合どうなるでしょうか?大きいオセロ盤のコマは極端に大きく、小さいオセロ盤のコマは極端に小さくなってしまいます。オセロであれば、このようにコマの大きさに差異がでていてもいいかもしれませんが、モバイル端末において px を指定すると、このオセロの例のように px の物理的な大きさによって UI が構築され相対的な見た目を維持するのが難しくなってしまいます。

Android の場合iOS とは異なり、様々な会社が出しているデバイス上でアプリを動作させることができるため、解像度やサイズもデバイスによって極端に異なる可能性がでてきます。

そこで登場するのが dp です。

dp とは?

dp とは density independent pixels の略で、その名の通り px の密度に依存しない論理的な単位のことを指しています。つまり、解像度が同じで画面サイズが異なる端末同士でも、同じくらいの大きさの UI を配置することができる相対的な単位です。

なんとなく dp の概要が掴めるとこんな疑問が出てくると思います。「じゃあ、画面の横幅いっぱいに表示できる dp何dp なの?」この疑問を解消してくれるのが、dpi です。

dpi とは?

dpi とは dots per inch の略で、1インチあたりのピクセル数(ドット数)を表します。つまり、この値を使用すれば 1インチ という物理的に固定されたサイズを基準にピクセル数を計算することができます。 しかし、多種多様なデバイスがある Android では、それぞれの dpi ごとに px を計算していくのはあまり効率的ではありません。そこで登場したのが 汎用密度 です。

密度修飾子 倍率 説明
ldpi 0.75 低密度(ldpi)画面(~120dpi)に適用するリソース
mdpi 1.0(基準) 中密度(mdpi)の画面(~160dpi)に適用するリソース(基準密度)。
hdpi 1.5 高密度(hdpi)画面(~240dpi)に適用するリソース
xhdpi 2.0 超高密度(xhdpi)画面(~320dpi)に適用するリソース
xxhdpi 3.0 超超高密度(xxhdpi)画面(~480dpi)に適用するリソース
xxxhdpi 4.0 超超超高密度(xxxhdpi)の画面(~640dpi)用のリソース

参照: https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp

汎用密度dpiしきい値ごとに値が決まっていて、それぞれのデバイスはこの値ごとにピクセルの換算を行うことができます。

そしてここでようやく 「じゃあ、画面の横幅いっぱいに表示できるdp何dpなの?」 の問いに答えられるようになります。結論から述べると mdpi(基準) でのピクセル値が dp値になるので、そこから倍率をもとに計算することができます。

例えば解像度(px) が 480 x 800 で、汎用密度が hdpiGalaxy S があったとします。hdpimdpi の1.5倍なので、mdpi での横幅のピクセル値は 480 / 1.5 = 320px になります。これにより Galaxy S で横幅いっぱいに表示できる dp値は 320dp であるということが分かります。

結論として dp を使う際に気を付けることは?

ここまで長々と書いてきましたが結論として下記の記事を参照させていただくと、 Android を搭載したスマホであれば 320~410 に収まるように 指定すればとりあえずは極端にレイアウトが崩れてしまうということはなさそうです。👷‍♀️

【Android】いまさら聞けないdp入門 - Qiita

また、汎用密度を使う以上それぞれの端末での若干の差異は出るので注意しておきましょう。

それでは、また明日🦅

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【Android】Color ResourceでAlphaを追加する

Androidcolors.xml に追加する Color にAlpha を追加する方法が分からなかったので、メモ程度に残しておきます🦅

方法

RGB 同様に16進数で、アルファ値を指定することで追加することができます。今回の場合は、(# を除いた)先頭2文字がアルファ値を示しています。

<color name="whiteWithAlpha0.84">#D6FFFFFF</color>

また、フォーマットについては公式ドキュメントにも記載されている通り下記のいずれかで指定する必要があるそうです。

  • #RGB
  • #ARGB
  • #RRGGBB
  • #AARRGGBB

developer.android.com

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com