Flutterラボ
【Flutter】背景を追加してUIを向上させよう! -Stack入門-
#UIデザイン#アプリ開発#Flutter#dart#ハッチアウトスクール#Flutter入門

今回はアプリ画面に背景を追加してUIを向上させていきたいと思います。実際にどのように背景機能を実装するのかというとStack Widgetを使用します。

完成予想図

画像3

Layout Builderとは

Layout Builderは親Widgetで指定されたサイズを引数として使用することで、Builder内の子Widgetをレスポンシブなデザインにすることができます。

参照元 動画 (Flutter公式)


背景Widgetの作成 (app_background.dart)

app_backgroundというdartファイルを作成しましょう。

LayoutBuilderを追加する

import 'package:flutter/material.dart';

class AppBackground extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return LayoutBuilder(builder: (context, contraint) {
     return Container();
     );
   });
 }
}

上記でも説明した通り、LayoutBuilderは親Widgetのサイズをcontraintという引数で返してくれます。今回はデバイスの大きさを取りたいのでmaxHeightとmaxWidthをそれぞれheightとwidgth変数に代入します。

こちらの2行を

final height = contraint.maxHeight;
final width = contraint.maxWidth;

このように追加する

import 'package:flutter/material.dart';

class AppBackground extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return LayoutBuilder(builder: (context, contraint) {
     final height = contraint.maxHeight;
     final width = contraint.maxWidth;
     return Container();
   });
 }
}

これでデバイスのheightとwidthを取得することができました。次はStackを使用して背景に使用したい画像、Widgetなどを追加していきます。

import 'package:flutter/material.dart';

class AppBackground extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return LayoutBuilder(builder: (context, contraint) {
     final height = contraint.maxHeight;
     final width = contraint.maxWidth;

     //Stackの追加
     return Stack(
       children: <Widget>[
       ],
     );
   });
 }
}

Stackを使用するのが初めての方はこちらの記事も参照ください。

Stackは子Widgetを重ねて表示するWidgetだということがわかりました。今回は背景色、球体Widget 2つ合計3つのWidgetを[]内に追加していきましょう。

まずはStackの最下層に淡い色の背景を追加しましょう

Stack(
       children: <Widget>[
       Container(
           color: Color(0xFFE4E6F1),
         ),
   ],
 );

するとこのようになります。

画像2


Positionedウィジェットを追加する

Container()の後にPositionedウィジェットを追加します。

Positioned Widgetとは

Positionedを使用するとStack内のWidgetの位置を指定することができます。主にtop, bottom, left, rightプロパティを使用します。

今回は球体型のContainer()を使用してデザインします。

左側

Positioned(
   top: -height * 0.10,
   left: -height * 0.39,
   child: Container(
     height: height,
     width: width,
     decoration: BoxDecoration(
         shape: BoxShape.circle, color: Colors.white.withOpacity(0.2)),
   ),
 ),

Colors.white.withOpacity(0.2)とすることでwhiteの色の透過率を20%にすることができます。

画像4

右側

Positioned(
   top: height * 0.20,
   left: height * 0.35,
   child: Container(
     height: height,
     width: width,
     decoration: BoxDecoration(
         shape: BoxShape.circle, color: Colors.white.withOpacity(0.4)),
   ),
 ),

画像3

これでAppBackgroundに球体2つと背景色の3つを合わせたStackウィジェットを作成することができました。

AppBackgroundの全体コード

import 'package:flutter/material.dart';

class AppBackground extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return LayoutBuilder(builder: (context, contraint) {
     final height = contraint.maxHeight;
     final width = contraint.maxWidth;

     return Stack(
       children: <Widget>[
         Container(
           color: Color(0xFFE4E6F1),
         ),
         Positioned(
           top: height * 0.20,
           left: height * 0.35,
           child: Container(
             height: height,
             width: width,
             decoration: BoxDecoration(
                 shape: BoxShape.circle, color: Colors.white.withOpacity(0.4)),
           ),
         ),
         Positioned(
           top: -height * 0.10,
           left: -height * 0.39,
           child: Container(
             height: height,
             width: width,
             decoration: BoxDecoration(
                 shape: BoxShape.circle, color: Colors.white.withOpacity(0.2)),
           ),
         ),
       ],
     );
   });
 }
}

アプリ画面にAppBackgroundを追加

こちらもStackを使用して下層部に背景を表示します。

注): app_background.dartをimportすることを忘れないように。

//main.dart
Scaffold(
     appBar: AppBar(
       title: Text('Background Demo'),
     ),
     body: Stack(
       children: [
         AppBackground(),
         SingleChildScrollView(
           padding: EdgeInsets.all(8),
           child: Center(
             child: Column(
               mainAxisAlignment: MainAxisAlignment.end,
               crossAxisAlignment: CrossAxisAlignment.center,
               children: [
                 Text('This is a background Demo'),
                 //省略可能
                 Image.asset(
                   'assets/hatch_logo.jpg',
                   width: 100,
                 ),
                 Text('By Hatchout School')
               ],
             ),
           ),
         )
       ],
     ),
   );


完成イメージ

画像1

参照ソースコード

app_background.dart

import 'package:flutter/material.dart';

class AppBackground extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return LayoutBuilder(builder: (context, contraint) {
     final height = contraint.maxHeight;
     final width = contraint.maxWidth;

     return Stack(
       children: <Widget>[
         Container(
           color: Color(0xFFE4E6F1),
         ),
         Positioned(
           top: height * 0.20,
           left: height * 0.35,
           child: Container(
             height: height,
             width: width,
             decoration: BoxDecoration(
                 shape: BoxShape.circle, color: Colors.white.withOpacity(0.4)),
           ),
         ),
         Positioned(
           top: -height * 0.10,
           left: -height * 0.39,
           child: Container(
             height: height,
             width: width,
             decoration: BoxDecoration(
                 shape: BoxShape.circle, color: Colors.white.withOpacity(0.2)),
           ),
         ),
       ],
     );
   });
 }
}

main.dart

import 'package:flutter/material.dart';
import 'package:hatch_sample_app/app_background.dart';

void main() {
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Hatch Demo',
     theme: ThemeData(
       primarySwatch: Colors.blue,
       visualDensity: VisualDensity.adaptivePlatformDensity,
     ),
     home: HomePage(),
   );
 }
}

class HomePage extends StatefulWidget {
 @override
 _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text('Background Demo'),
     ),
     body: Stack(
       children: [
         AppBackground(),
         SingleChildScrollView(
           padding: EdgeInsets.all(8),
           child: Center(
             child: Column(
               mainAxisAlignment: MainAxisAlignment.end,
               crossAxisAlignment: CrossAxisAlignment.center,
               children: [
                 Text('This is a background Demo'),
                 Image.asset(
                   'assets/hatch_logo.jpg',
                   width: 100,
                 ),
                 Text('By Hatchout School')
               ],
             ),
           ),
         )
       ],
     ),
   );
 }
}

まとめ

今回はLayoutBuilderとStackを使用して背景ウィジェットを作成しました。