1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Flutter】Stackの備忘録

1
Posted at

はじめに

Stackについて基礎を学んだので記事にしました。

目次

  1. 基本
  2. Clip系と組み合わせる
  3. 参考文献

基本

Stackのchildrenに指定したWidgetを順番に重ねていく。
image.png

Container(
  width: 300,
  height: 500,
  color: Colors.white,
  child: Stack(
    children: [
      Container(
        width: 200,
        height: 200,
        color: Colors.red,
      ),
      Container(
        width: 100,
        height: 100,
        color: Colors.blue,
      ),
      Container(
        width: 50,
        height: 50,
        color: Colors.green,
      ),
    ]
  ),
)

Stackのalignmentを指定すると、その指定通りにwidgetが配置される。 下記はAlignmentDirectional.bottomCenterを指定したときの画像。

image.png

Positioned Widgetを使う

Stackに並べるwidgetをPositionedで囲うと指定した位置に配置できる。
image.png

Container(
              width: 300,
              height: 500,
              color: Colors.white,
              child: Stack(children: [
                Positioned(
                  top: 20,
                  left: 20,
                  child: Container(
                    width: 200,
                    height: 200,
                    color: Colors.red,
                  ),
                ),
                Positioned(
                  top: 50,
                  right: 50,
                  child: Container(
                    width: 100,
                    height: 100,
                    color: Colors.blue,
                  ),
                ),
                Positioned(
                  bottom: 0,
                  left: 50,
                  child: Container(
                    width: 50,
                    height: 50,
                    color: Colors.green,
                  ),
                ),
              ]),
            ),

※topとbottom、またはleftとright両方に値を指定すると下記のような感じで引き伸ばされる。

image.png

// 該当部分のみ抜粋
                Positioned(
                  top: 20,
                  left: 20,
                  bottom: 20,
                  child: Container(
                    width: 200,
                    height: 200,
                    color: Colors.red,
                  ),
                ),

またPositioned.fillとするとStack全体を覆うこともできる。

Clip系と組み合わせる

Clip系のWidgetと組み合わせるとさらにカスタマイズできるので紹介します。

ClipRect

ClipRectはwidgetを矩形で切り抜けます。
Stackと組み合わせると以下の画像のようなことができます。
image.png

ソースは以下です。

Stack(
  children: [
    Positioned.fill(
      child: Container(
        color: Colors.red,
      ),
    ),
    Positioned.fill(
      child: ClipRect(
        clipper: RectClipper(),
        child: Container(
          color: Colors.blue,
        ),
      ),
    ),
  ]
)


.....

class RectClipper extends CustomClipper<Rect> {
  @override
  Rect getClip(Size size) {
    return Rect.fromLTRB(20, 20, size.width - 20, size.height - 20);
  }

  @override
  bool shouldReclip(covariant CustomClipper oldClipper) {
    return false;
  }
}

青と赤は両方とも、Positioned.fillで大きさを同じにしていますが、青の方は端から20ずつカットしました。
ClipRectは下記のような書き方もできますが、Positioned.fillの中だとうまく機能しませんでした。

ClipRect(
  child: Align(
    alignment: Alignment.center,
    widthFactor: 0.4,
    heightFactor: 0.5,
    child: Container(
      color: Colors.blue,
    ),
  ),
),

ClipRRect

角丸で切り抜くと下記のようになります。

image.png

Stack(
  children: [
    Positioned.fill(
      child: Container(
        color: Colors.red,
      ),
    ),
    Positioned.fill(
      child: ClipRRect(
        borderRadius: BorderRadius.circular(100),
        child: Container(
          color: Colors.blue,
        ),
      ),
    ),
  ]
)

ClipOval

楕円で切り抜くと下記のようになります。

image.png

Stack(
  children: [
    Positioned.fill(
      child: Container(
        color: Colors.red,
      ),
    ),
    Positioned.fill(
      child: ClipOval(
        child: Container(
          color: Colors.blue,
        ),
      ),
    ),
  ]
)

ClipPath

ClipPathを使うと、指定したパス通りに切り抜けます。

image.png

Stack(
  children: [
    Positioned.fill(
      child: Container(
        color: Colors.red,
      ),
    ),
    Positioned.fill(
      child: ClipPath(
        clipper: FreeClipper(),
        child: Container(
          color: Colors.blue,
        ),
      ),
    ),
  ]
)

・・・
class FreeClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final path = Path();
    path.moveTo(0, 0);
    path.lineTo(size.width / 2, 0);
    path.lineTo(size.width / 2, size.height / 2);
    path.lineTo(size.width, size.height / 2);
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);
    path.lineTo(0, 0);
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper oldClipper) {
    return false;
  }
}

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?