Flutterアプリケーション開発概論

【グラデーション表現】画像の上に黒いグラデーションを重ねて文字を読みやすくする

この節で学ぶこと

前の節では、Home画面の上部に大きな背景画像を表示し、その上にロゴ・作品タイトル・Playボタンを重ねる方法を学びました。

今回は、その中でも特に大切な グラデーション表現 を詳しく見ていきます。

動画アプリ風のUIでは、背景画像の上に文字を重ねることがよくあります。

ただし、画像の上にそのまま白い文字を置くと、画像の明るい部分では文字が読みにくくなることがあります。

そこで使うのが、黒いグラデーションです。

背景画像を表示する
↓
その上に黒い半透明のグラデーションを重ねる
↓
さらにその上に文字やボタンを置く
↓
文字が読みやすくなる

グラデーションは、見た目をかっこよくするためだけではありません。

ユーザーが文字を読みやすくするための、とても実用的な工夫です。


今回見るコード

Home画面上部では、背景画像の上に次のようなグラデーションを重ねています。

Positioned.fill(
  child: DecoratedBox(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: [
          NetflixColors.black,
          Colors.black.withValues(alpha: 0.92),
          Colors.black.withValues(alpha: 0.28),
          Colors.black.withValues(alpha: 0.78),
          NetflixColors.black,
        ],
        stops: const [0.0, 0.16, 0.38, 0.78, 1.0],
      ),
    ),
  ),
),

少し長く見えますが、やっていることはシンプルです。

上から下に向かって、黒の濃さを少しずつ変えている

ということです。


そもそも、なぜ文字が読みにくくなるのか

背景画像の上に文字を置くと、画像の色によって文字の見え方が変わります。

たとえば、黒い背景の上に白い文字を置けば読みやすいです。

黒背景 + 白文字 = 読みやすい

でも、明るい空や白い服の上に白文字を置くと、文字が背景に溶けてしまいます。

明るい画像 + 白文字 = 読みにくい

この問題を解決するために、画像の上に黒い半透明のレイヤーを重ねます。

そうすると、画像は見えたまま、文字の後ろだけ少し暗くなります。

結果として、白い文字が読みやすくなります。


Stackの重なりを思い出そう

グラデーションは、Stack の中で背景画像の上に重ねています。

重なり順は、このようになっています。

1. 背景画像
2. 黒いグラデーション
3. ヘッダー
4. ロゴ
5. 作品タイトル
6. ボタン

コード上では、Stackchildren に書いた順番で下から上に重なります。

つまり、先に書いたものが奥、後に書いたものが手前になります。

背景画像を先に置き、そのあとにグラデーションを置くことで、画像の上に黒いレイヤーが重なります。


Positioned.fillで全体に重ねる

グラデーション部分は、Positioned.fill で囲まれています。

Positioned.fill(
  child: DecoratedBox(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        ...
      ),
    ),
  ),
),

Positioned.fill は、Stack の中で使うWidgetです。

意味は、

親のStackいっぱいに広げる

です。

今回の場合、Home画面上部のエリア全体にグラデーションを広げています。

もし Positioned.fill を使わないと、グラデーションが一部にしかかからないことがあります。

背景画像全体を暗くしたいので、ここでは Positioned.fill が合っています。


DecoratedBoxとは?

グラデーションは、DecoratedBox の中で指定しています。

DecoratedBox(
  decoration: BoxDecoration(
    gradient: LinearGradient(
      ...
    ),
  ),
)

DecoratedBox は、背景色・枠線・グラデーションなどの装飾をつけるためのWidgetです。

今回は、何か文字を表示しているわけではありません。

ただ、背景画像の上に「黒いグラデーションの装飾」を重ねたいので使っています。

似たようなことは Container でもできます。

Container(
  decoration: BoxDecoration(
    gradient: LinearGradient(
      ...
    ),
  ),
)

今回のコードでは、装飾だけを目的にしているので DecoratedBox を使っています。


LinearGradientとは?

グラデーション本体を作っているのが LinearGradient です。

LinearGradient(
  begin: Alignment.topCenter,
  end: Alignment.bottomCenter,
  colors: [
    ...
  ],
)

LinearGradient は、まっすぐな方向に色を変化させるグラデーションです。

今回の指定では、上から下に向かって色が変わります。

begin: Alignment.topCenter,
end: Alignment.bottomCenter,

これは、

上から始まって
下に向かって変化する

という意味です。


beginとendを見てみよう

今回のコードでは、次のように書かれています。

begin: Alignment.topCenter,
end: Alignment.bottomCenter,

それぞれの意味は次の通りです。

指定意味
Alignment.topCenter上の中央から始まる
Alignment.bottomCenter下の中央で終わる

つまり、縦方向のグラデーションです。

もし横方向にしたい場合は、次のようにできます。

begin: Alignment.centerLeft,
end: Alignment.centerRight,

これは、左から右に向かうグラデーションです。

ただし、今回のHome画面では、上部と下部を暗くしたいので、縦方向が合っています。


colorsで黒の濃さを決める

次に大切なのが colors です。

colors: [
  NetflixColors.black,
  Colors.black.withValues(alpha: 0.92),
  Colors.black.withValues(alpha: 0.28),
  Colors.black.withValues(alpha: 0.78),
  NetflixColors.black,
],

ここでは、上から下に向かって黒の濃さを変えています。

ざっくり見ると、こうです。

一番上:しっかり黒
少し下:かなり黒
中央:少しだけ黒
下の方:かなり黒
一番下:しっかり黒

中央を少し薄くしているので、背景画像も見えます。

一方で、上と下は暗くしているので、ヘッダーやタイトル、ボタンが読みやすくなります。


alphaとは?

この部分に注目してください。

Colors.black.withValues(alpha: 0.28)

alpha は、透明度を表す値です。

見え方
1.0完全に表示される
0.92かなり濃く表示される
0.78しっかり暗くなる
0.28うっすら暗くなる
0.0完全に透明になる

つまり、

Colors.black.withValues(alpha: 0.28)

は、

黒を少しだけ重ねる

という意味です。

背景画像を見せたい場所では、alphaを小さくします。

文字を読みやすくしたい場所では、alphaを大きくします。


stopsで色の位置を決める

次に stops を見てみましょう。

stops: const [0.0, 0.16, 0.38, 0.78, 1.0],

stops は、colors で指定した色を、どの位置に置くかを決めています。

0.0 が一番上、1.0 が一番下です。

stop位置のイメージ
0.0一番上
0.16上から16%くらい
0.38上から38%くらい
0.78上から78%くらい
1.0一番下

つまり、今回のグラデーションは、ただ均等に黒くしているわけではありません。

上、中央、下で黒の濃さを細かく調整しています。


今回のグラデーションの考え方

今回のHome画面では、上と下に大切なUIがあります。

上には、メニューアイコン、ロゴ、プロフィール画像、カテゴリタブがあります。

下には、作品タイトル、作品情報、Playボタンがあります。

だから、上と下は暗めにします。

一方で、中央は背景画像を見せたいので、黒を薄くしています。

上:ヘッダーがあるので暗くする
中央:画像を見せたいので少し明るくする
下:タイトルとボタンがあるので暗くする

このように、グラデーションは「なんとなくかける」のではなく、UIの配置に合わせて調整します。


まずカスタマイズしてみよう

今回は、中央部分の暗さを変えてみます。

次のコードを探してください。

Colors.black.withValues(alpha: 0.28),

これを、少し濃くしてみましょう。

Colors.black.withValues(alpha: 0.45),

保存して、Home画面を確認してください。

中央の背景画像が少し暗くなり、文字が読みやすくなります。

ただし、濃くしすぎると背景画像の魅力が弱くなります。

少しずつ数字を変えて、ちょうどよい見え方を探してみましょう。


よくあるつまずきポイント

Q. グラデーションが表示されません。

Stack の中で、背景画像より後にグラデーションを書いているか確認してください。

Positioned.fill(
  child: Image.network(...),
),

Positioned.fill(
  child: DecoratedBox(
    decoration: BoxDecoration(
      gradient: LinearGradient(...),
    ),
  ),
),

Stack では後に書いたものが上に重なります。

もしグラデーションを背景画像より前に書くと、画像の後ろに隠れて見えなくなります。

Q. 画面が暗くなりすぎました。

alpha の値が大きすぎる可能性があります。

たとえば、

Colors.black.withValues(alpha: 0.90),

のようにすると、かなり暗くなります。

背景画像を見せたい場合は、中央部分を次のように少し小さめにしてみましょう。

Colors.black.withValues(alpha: 0.25),

Q. withValues でエラーが出ます。

Flutterの環境によっては、withValues が使えない場合があります。

その場合は、次のように書き換えてください。

Colors.black.withOpacity(0.45)

たとえば、変更前がこちらです。

Colors.black.withValues(alpha: 0.45)

変更後はこうです。

Colors.black.withOpacity(0.45)

環境によって書き方が少し違うだけで、考え方は同じです。


チャレンジ

チャレンジ1:中央の暗さを少し濃くしよう

次のコードを探してください。

Colors.black.withValues(alpha: 0.28),

これを次のように変更します。

Colors.black.withValues(alpha: 0.45),

背景画像と文字の見え方がどう変わるか確認してください。

チャレンジ2:下の暗さを少し弱くしよう

次のコードを探してください。

Colors.black.withValues(alpha: 0.78),

これを次のように変更します。

Colors.black.withValues(alpha: 0.60),

タイトルやボタンの読みやすさがどう変わるか見てみましょう。

チャレンジ3:一番下の黒を少し透明にしよう

次のコードを探してください。

NetflixColors.black,

グラデーションの最後にある黒を、次のように変えてみます。

Colors.black.withValues(alpha: 0.90),

下のなじみ方が少し変わります。


チャレンジの答え

チャレンジ1の答え

変更前:

Colors.black.withValues(alpha: 0.28),

変更後:

Colors.black.withValues(alpha: 0.45),

中央部分が少し暗くなり、文字が読みやすくなります。

チャレンジ2の答え

変更前:

Colors.black.withValues(alpha: 0.78),

変更後:

Colors.black.withValues(alpha: 0.60),

下の方の背景画像が少し見えやすくなります。

チャレンジ3の答え

変更前:

NetflixColors.black,

変更後:

Colors.black.withValues(alpha: 0.90),

一番下が完全な黒ではなく、少しだけ背景画像が残る見え方になります。


この節のまとめ

この節では、画像の上に黒いグラデーションを重ねて、文字を読みやすくする方法を学びました。

大切なポイントは次の通りです。

  • 画像の上に白文字を置くと、背景によっては読みにくくなる。
  • 黒い半透明のグラデーションを重ねると、文字が読みやすくなる。
  • Stack では、後に書いたWidgetほど手前に表示される。
  • Positioned.fill を使うと、グラデーションを画面いっぱいに広げられる。
  • DecoratedBoxBoxDecoration でグラデーションを指定できる。
  • LinearGradient は、直線方向に色を変化させるグラデーション。
  • beginend でグラデーションの向きを決める。
  • colors で色の流れを決める。
  • alpha で黒の濃さを調整できる。
  • stops で、それぞれの色が出る位置を細かく決められる。
  • グラデーションは、見た目だけでなく読みやすさのためにも使う。

次のステップ

次の節では、Home画面上部にあるメニューアイコン、ロゴ、プロフィール画像、カテゴリタブを配置する AppBar UI を見ていきます。

画面の一番上にあるUIは、アプリ全体の印象を決める大切な部分です。

次は、上部ヘッダーをどのように作っているのかを確認していきましょう。

教材トップへ戻る