LoginSignup
5
2

【Flutter】紙の端が折れたようなContainerを作る

Last updated at Posted at 2023-06-08

環境

  • Android Studio: Flamingo 2022.2.1
  • Flutter: 3.7.12

考え方

  • Containerの右下に切り抜きを作る → Clipperをつかう
  • めくれた感じをつくる = 右下に小さいContainerを重ねる → Stackをつかう

完成イメージ

Screenshot_20230608-164310.png

コード

サンプルコード
import 'package:flutter/material.dart';

/// 折れたところのサイズを設定する
const _clipSize = Size(40, 40);

class OretaContainerPage extends StatefulWidget {
  const OretaContainerPage({super.key});

  @override
  State<StatefulWidget> createState() => _OretaContainerState();
}

class _OretaContainerState extends State<StatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('紙の端が折れたようなContainer')),
      body: _createContainer(),
    );
  }

  Widget _createContainer() {
    // Positionedで右下にめくれたようなUIを配置する

    return Padding(
      padding: const EdgeInsets.all(8),
      child: ClipPath(
        clipBehavior: Clip.antiAlias,
        clipper: PaperClipper(),
        child: Stack(
          children: [
            Container(
              width: double.infinity,
              height: 200,
              color: Colors.blue.shade100,
            ),
            Positioned(
              bottom: 0,
              right: 0,
              child: Container(
                width: _clipSize.width,
                height: _clipSize.height,
                color: Colors.blue.shade300,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/// 角折れを表現するためのClipper
class PaperClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    // 折れてるところだけを切り抜く
    final path = Path();
    path.lineTo(0, 0); // Start
    path.lineTo(size.width, 0); // 右上
    path.lineTo(size.width, size.height - _clipSize.height); // 折れてるところ
    path.lineTo(size.width - _clipSize.width, size.height); // 折れてるところ
    path.lineTo(0, size.height); // End
    path.close();
    return path;
  }

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

ここのコードには載せてませんが、
Materialで影とかつけたりしたらいい感じのUIになると思います。

【6/9 追記】
ClipしたUIに影をつけるのは、Materialでくくるだけではダメな模様。
→ stackoverflowに質問あった。
https://stackoverflow.com/questions/54753355/how-to-make-suitable-border-and-shadow-for-a-widget-created-by-customclipper

補足

  • CustomClipperの、getPath()の繋げ方のイメージ

image.png

参考サイト

  • Clipperの使い方


この紙の端が折れたUI、って正式名称はなんて名前なんでしょうか?
めくれてる、とか?

ググってもでてこなくて、自力でつくりました…

そもそも自力でつくるものではないのでしょうか? そういうプラグインがある?? :thinking:
UIに詳しい方、教えてください。

【2023/7/3 追記】

この紙の端が折れたUI、って正式名称はなんて名前なんでしょうか?

ドッグイアというらしいです。 :dog2:

5
2
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
5
2