🦍

【Flutter】いろいろな角度の半円を実装する

2022/05/09に公開

作ったもの

画面端に表示する半円です。

コード全文

main.dart
import 'package:flutter/material.dart';
import 'package:flutter_try/half_button.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage());
  }
}

class MyHomePage extends StatelessWidget {
  double size = 220;
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Stack(
        children: <Widget>[
          Align(
            alignment: Alignment.centerLeft,
            child: HalfButton(size, Direction.left),
          ),
          Align(
            alignment: Alignment.centerRight,
            child: HalfButton(size, Direction.right),
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: HalfButton(size, Direction.top),
          ),
          Align(
            alignment: Alignment.topCenter,
            child: HalfButton(size, Direction.bottom),
          )
        ],
      ),
    );
  }
}

sizeで半円ボタンのサイズを調整し,Alignを使ってAlignmentを設定することで角に表示しています。

half_button.dart
import 'dart:math' as math;

import 'package:flutter/material.dart';

enum Direction { left, top, right, bottom }

class HalfButton extends StatelessWidget {
  HalfButton(
    this.size,
    this.direction,
  );
  double size;
  Direction direction;

  
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: HalfCirclePainter(context, direction),
      size: Size(size, size),
    );
  }
}

class HalfCirclePainter extends CustomPainter {
  HalfCirclePainter(
    this.context,
    this.direction,
  );
  BuildContext context;
  Direction direction;

  
  void paint(Canvas canvas, Size size) {
    canvas.drawArc(
        Rect.fromLTWH(
          direction == Direction.right
              ? size.width / 2
              : direction == Direction.left
                  ? -size.width / 2
                  : 0,
          direction == Direction.bottom
              ? size.width / -2
              : direction == Direction.top
                  ? size.width / 2
                  : 0,
          size.width,
          size.height,
        ),
        direction == Direction.right
            ? math.pi / 2
            : direction == Direction.left
                ? math.pi * 1.5
                : direction == Direction.bottom
                    ? 0
                    : math.pi,
        math.pi,
        true,
        Paint()..color = Colors.blue.withOpacity(0.2));
  }

  
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}


sizeDirectionを引数にとり,半円を表示させるクラスHalfButtonを実装しました。
sizeで半円の大きさを指定し,Directionで半円の向きを指定します。

CustomPainterを使って半円を描画しています。

補足

Alignを使用せず,MyHomePage内のbodyを以下のように書き換えてみます。

body:Center(
        child: Column(
          children: <Widget>[
            HalfButton(size, Direction.bottom),
            HalfButton(size, Direction.left),
            HalfButton(size, Direction.right),
            HalfButton(size, Direction.top),
          ],
        ),
      ),

Centerの中身に入れているせいでもありますが,一番上の半円以外は角に表示されません。
角に表示させたいときはAlignの中に入れましょう。

Discussion