カスタムビュー作成4:カスタムビューの属性をスタイル・テーマで指定

投稿日:  更新日:

Android SDKは様々なViewコンポーネント(TextView, Button, ImageViewなど)を含んでいます。

これだけで、十分に見栄えのあるアプリが開発できます。

ですが、全ての人やアプリの要望に対応することは難しく、アプリ開発中に「こんなViewが欲しい!」と思える場面があります。

そのような場合はカスタムビューの作成を検討してみましょう。「なければ作ってしまえ!」という訳です。

ここでは、「カスタムビューの属性をスタイル・テーマで指定」をまとめます。

※環境:Android Studio Flamingo | 2022.2.1

スポンサーリンク

スタイルで指定

スタイルとテーマは同じものです。ただ、指定の対象が異なります。

スタイルは対象がViewです。そのViewの属性を格納し、Viewの見栄えを決めるものです。

スタイルの定義

スタイルはstyles(values/styles.xml)ファイルに、以下のようなフォーマットで定義します。

継承なし継承あり(1)継承あり(2)
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="スタイル名">
        <item name="属性名1">属性値</item>
        <item name="属性名2">属性値</item>
                       :
    </style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="スタイル名(子)" parent="スタイル名(親)">
	    <item name="属性名1">属性値</item>
        <item name="属性名2">属性値</item>
                       :
    </style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="スタイル名(親).スタイル名(子)">
	    <item name="属性名1">属性値</item>
        <item name="属性名2">属性値</item>
                       :
    </style>
</resources>
 「スタイル名」 

任意の名前が付けられます。

継承が可能です。既存のビューのスタイルを取り込んで、新たなスタイルを定義する場合に役立ちます。

 「属性名」 

定義済みの属性名です。

以下は、stylesファイルの例です。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CustomViewStyle">
        <item name="prm1">Prm1 is in Style.</item>
        <item name="prm2">20</item>
    </style>
</resources>

スタイルの指定

以下は、レイアウトファイルの例です。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
     
    ...
    <cカスタムビューのクラス名.CustomView
        android:id="@+id/customView"
        style="@style/CustomViewStyle"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    ...
 
</androidx.constraintlayout.widget.ConstraintLayout>

属性の参照

スタイルは展開されて、定義されていた属性はattrsに含まれます。

class CustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {

    private var prm1: String?
    private var prm2: Int

    init {
        context.obtainStyledAttributes(                            // 属性の取得
            attrs, R.styleable.CustomView5, defStyleAttr, defStyleRes)
            .apply {
                try {
                    prm1 = getString(R.styleable.CustomView_prm1)  // 属性の参照
                    prm2 = getInt(R.styleable.CustomView_prm2, -1) // 属性の参照
                    System.out.println("CustomView5 Prm1 = ${prm1}")
                    System.out.println("CustomView5 Prm2 = ${prm2}")
                }
                finally {
                    recycle()   // 最後にTypedArrayインスタンスを開放
                }
            }
    }
	
	...
}
I/System.out: Prm1 is in Style.
I/System.out: Prm2 = 20
スポンサーリンク

テーマで指定

スタイルとテーマは同じものです。ただ、指定の対象が異なります。

テーマは対象がActivityです。アプリで使用可能な全Viewの属性が入り、アプリの見栄えを決めるものです。

属性の指定

以下は、テーマファイルの例です。

テーマファイルはマニフェストファイル(AndroidManifest.xml)でActivityに指定されます。

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.LibCustomView" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
        <item name="prm1">Prm1 is in Theme.</item>
        <item name="prm2">30</item>
    </style>
</resources>

属性の参照

テーマに指定された属性はContext#obtainStyledAttributes( )の内部で取得され、attrsと統合されます。

class CustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {

    private var prm1: String?
    private var prm2: Int

    init {
        context.obtainStyledAttributes(                            // 属性の取得
            attrs, R.styleable.CustomView5, defStyleAttr, defStyleRes)
            .apply {
                try {
                    prm1 = getString(R.styleable.CustomView_prm1)  // 属性の参照
                    prm2 = getInt(R.styleable.CustomView_prm2, -1) // 属性の参照
                    System.out.println("CustomView5 Prm1 = ${prm1}")
                    System.out.println("CustomView5 Prm2 = ${prm2}")
                }
                finally {
                    recycle()   // 最後にTypedArrayインスタンスを開放
                }
            }
    }
	
	...
}
I/System.out: Prm1 is in Theme.
I/System.out: Prm2 = 30
スポンサーリンク

優先順位

表は属性の指定方法です。大きく分けて5つあります。

優先度指定単位指定対象指定先静・動
Immediate
1
各々の属性Viewクラスのプロパティ
動的
Layout
2
レイアウトファイル
静的
Style
3
複数の属性
Theme
4
Activityマニフェストファイル
Default
5
各々の属性Viewクラスのプロパティ(初期値)
※優先度:1(高)~5(低)

※Immediate:「カスタムビュー作成1:Viewの継承と…」で取り上げています。
※Layout:「カスタムビュー作成2:ビューの属性定義と…」で取り上げています。
※Style:本記事で取り上げています。
※Theme:同上
※Default:Viewクラスのプロパティ初期値による動作です。

優先順位とは、同じ属性が重複して指定された場合に、採用される属性を決めるルールです。優先順位の高いものが採用されます。

スポンサーリンク

関連記事:

Android SDKは様々なViewコンポーネント(TextView, Button, ImageViewなど)を含んでいます。 これだけで、十分に見栄えのあるアプリが開発できます。 ですが、全ての人やアプリの要望に対応することは難しく、アプリ開発中に「こんなViewが欲しい!」と思える場面があります。 そのような場合はカスタムビューの作成を検討してみましょう。「なければ作ってしまえ!」という訳です。 ここでは「Viewの継承とonDrawの役割」をまとめます。 ※環境:Android Studio Electric Eel | 2022.1.1 ...
Android SDKは様々なViewコンポーネント(TextView, Button, ImageViewなど)を含んでいます。 これだけで、十分に見栄えのあるアプリが開発できます。 ですが、全ての人やアプリの要望に対応することは難しく、アプリ開発中に「こんなViewが欲しい!」と思える場面があります。 そのような場合はカスタムビューの作成を検討してみましょう。「なければ作ってしまえ!」という訳です。 ここでは、「カスタムビューの属性の定義と指定方法」をまとめます。 ※環境:Android Studio Flamingo | 2022.2.1 ...
Android SDKは様々なViewコンポーネント(TextView, Button, ImageViewなど)を含んでいます。 これだけで、十分に見栄えのあるアプリが開発できます。 ですが、全ての人やアプリの要望に対応することは難しく、アプリ開発中に「こんなViewが欲しい!」と思える場面があります。 そのような場合はカスタムビューの作成を検討してみましょう。「なければ作ってしまえ!」という訳です。 ここでは、「カスタムビューの属性のタイプと使用例」をまとめます。 ※環境:Android Studio Flamingo | 2022.2.1 ...
Android SDKは様々なViewコンポーネント(TextView, Button, ImageViewなど)を含んでいます。 これだけで、十分に見栄えのあるアプリが開発できます。 ですが、全ての人やアプリの要望に対応することは難しく、アプリ開発中に「こんなViewが欲しい!」と思える場面があります。 そのような場合はカスタムビューの作成を検討してみましょう。「なければ作ってしまえ!」という訳です。 ここでは、「カスタムビューの動的な配置」をまとめます。 ※環境:Android Studio Flamingo | 2022.2.1 ...
スポンサーリンク