どっこと備忘録群

アウトプットしないとインプットできない私が Androidアプリ開発をメインとした備忘録を載せています。

Viewを扱う

Viewを表示する

レイアウトファイルに要素を追加する。

ActivityFragmentの画面表示処理でレイアウトを指定するが、そのレイアウトに表示したいViewを追加する。

例えばAndroid Studioでシンプルなプロジェクトを新規作成すると、activity_main.xmlが生成されるので確認する。

<?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:id="@+id/main"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

ConstraintLayout は複数のViewを配置するときに使う ViewGroup 派生のクラスのひとつ(説明は割愛)。 その中にTextViewというテキストを表示するためのViewが配置されている。 新規作成したプロジェクトでは、↑のレイアウトをActivity.setContentView(resourceId)により表示している。

resourceId(リソースID)はリソースファイルを作成するとAndroid Studioが自動生成してくれる。 レイアウトファイルの場合はR.layout.filename が自動生成されるので、これを指定する。

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    // Activityで表示する画面として↑のレイアウトファイルを指定
    setContentView(R.layout.activity_main)
    ...
  }

Viewの大きさを設定する

レイアウトファイルにViewを配置する際、必須項目としてandroid:layout_widthandroid:layout_heightがある。 この設定項目でViewの大きさを指定することができる。

Viewの幅を設定する

android:layout_widthで設定する。以下のいずれかを指定する。

  • wrap_content。OSが必要な最小幅を計算して自動で大きさを決めてくれる。
  • match_parent。領域いっぱいに表示する。
  • 数値。dpという単位を使って指定する。例えば100を指定する場合はandroid:layout_width="100dp"となる。

Viewの高さを設定する

android:layout_heightで設定する。以下のいずれかを指定する。

  • wrap_content。OSが必要な最小の高さを計算して自動で大きさを決めてくれる。
  • match_parent。領域いっぱいに表示する。
  • 数値。dpという単位を使って指定する。例えば100を指定する場合はandroid:layout_height="100dp"となる。

背景を設定する

android:backgroundで設定する。以下の設定方法がある。

1. リソース指定

res/colors.xmlに設定した色や、drawableリソースを指定する。

  • 色の場合は @colors/resouce_nameで指定する。
  • drawableリソースの場合は @drawable/resource_nameで指定する。

例えばres/colors.xml に以下を定義してある場合、

<color name="background_color">#FF0000</color>

以下のように指定する。

<View
  ...
  android:background="@color/background_color" />

2. color指定

#RGB の形式で指定する。例えば赤色(FF0000)を指定する場合は以下。

<View
  ...
  android:background="#FF0000" />

不透明度(alpha)も合わせて指定可能。その場合は#ARGBで指定する。

背景をプログラム上で設定する

View.setBackgroundResource(resourceId)View.setBackgroundColor(color)を使う。

setBackgroundResource(resourceId) ではリソースIDを指定する。 drawableリソース(R.drawable.resource_name)、colorリソース(R.color.resource_name)どちらでも利用可能。

setBackgroundColor(color)ではRGB形式で色を指定する。 16進数であることを明示するためには0xRGB の形で設定する。

例えば赤色(FF0000)を指定する場合は以下。

val view = findViewById(R.id.view)
view.setBackgroundColor(0xFF0000)

また、不透明度(alpha)も合わせて指定可能。その場合は#ARGBで指定する。 android.graphics.Colorクラスによくある色指定の定義が実装されているのでこちらも参考にできる。

Viewの表示位置を設定する

android:layout_gravityで設定する。 親のViewGroupの領域に対してViewをどこに寄せて表示するかを設定でき、以下が設定できる。

  • center
  • center_vertical
  • center_horizontal
  • start(=left)
  • top
  • end(=right)
  • bottom

親ビューからはみ出して子ビューを表示する

「表示する領域のViewGroup」に以下を設定する。

android:clipChildren="false"

はみ出す子ビューの親ではなくはみ出した子ビューを表示する**領域のViewGroup**に設定すること。 つまり以下のように記述する。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:clipChildren="false"            // 押し込まれる領域にclipChildren:falseを設定
   android:layout_height="match_parent">

   <FrameLayout
     android:layout_width="250dp"
     android:layout_height="250dp"
     android:layout_gravity="center">
   
     <View
       android:layout_width="150dp"
       android:layout_height="50dp"
       android:layout_marginTop="-25dp" // 親のFrameLayoutの領域外
       android:background="@android:color/black"
       android:gravity="center" />
  </FrameLayout>
</FrameLayout>

参考

Viewのコンストラクタを理解する

Viewクラスには、主に3つのコンストラクタがある。

  • constructor(context: Context): コードからビューを生成する際に使用される。XML属性やスタイルは考慮されないため、必要に応じて手動で設定する必要がある。
  • constructor(context: Context, attrs: AttributeSet?): XMLレイアウトからビューがインフレートされる際に呼び出される。 styleが明示的に指定されていない場合のみ。
  • constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): これもXMLからインフレートされる際に呼び出されるが、 styleが明示的に指定されている場合はこちらが呼び出される。

既存コンポーネントを拡張する場合のstyle適用

既存のコンポーネントを拡張する場合、上記3つのコンストラクタと合わせてデフォルトのスタイルを継承させ、カスタムViewに適用させる。 例えば、EditTextを継承したHomeEditTextクラスを実装してみる。

1. カスタム属性の追加

attrs.xmlファイルで、カスタムビューのデフォルトスタイルを参照するためのカスタム属性を定義する。

<resources>
    <attr name="hogeEditTextStyle" format="reference" />
</resources>

2. カスタムスタイルの作成

styles.xmlでカスタムスタイルを定義する。 このとき定義するスタイルは親コンポーネントのデフォルトスタイルを継承する。 EditTextの場合はandroid:Widget.EditTextが該当。

<resources>
    <style name="HogeEditTextStyle" parent="android:Widget.EditText">
        </style>
</resources>

3. テーマへのリンク

アプリのテーマが定義されているthemes.xmlに、先ほど作成したカスタム属性とスタイルをリンクさせる。

<style name="Theme.AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
    <item name="hogeEditTextStyle">@style/HogeEditTextStyle</item>
</style>

4. コンストラクタの実装

カスタムビューのクラスでコンストラクタを正しく実装する。

それぞれのコンストラクタで、defStyleAttrを正しく設定しスーパークラスを呼び出すように実装することで、 XMLからでもコードからでも、カスタムビューが期待通りの外観となる。

import androidx.appcompat.widget.AppCompatEditText

class HogeEditText(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
    AppCompatEditText(context, attrs, defStyleAttr) {

    // ①のコンストラクタ(コードからの生成)
    constructor(context: Context) : this(context, null, R.attr.hogeEditTextStyle)

    // ②のコンストラクタ(XMLからのインフレート)
    constructor(context: Context, attrs: AttributeSet?) : this(
        context,
        attrs,
        R.attr.hogeEditTextStyle
    )
}

最終更新: 2025.9.12