Flutter では ClipRect, ClipOval を使用して Widget を Clip ことができます。
矩形切り取り
new ClipRect(
child: new Align(
alignment: Alignment.topCenter,
heightFactor: 0.5,
child: new Image.network(userAvatarUrl),
),
)
オーバル切り取り
new ClipOval(
child: new Align(
color: Colors.black,
alignment: Alignment.topCenter,
child: new Image.network(userAvatarUrl),
),
)
くり抜くには、ClipPath と CustomClipper を使用することで可能です。
ClipPath(
clipper: InvertedCircleClipper(),
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.8),
),
),
class InvertedCircleClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
return Path()
// くり抜き
..addOval(
Rect.fromCircle(
center: Offset(size.width / 2, size.height / 2),
radius: size.width * 0.25,
),
)
// 全体描画
..addRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height))
..fillType = PathFillType.evenOdd;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
こんな感じのことができます。
全体ソースコード
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: SafeArea(
child: Container(
constraints: BoxConstraints.expand(),
color: Colors.amber,
child: Column(
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
Container(
color: Colors.green,
alignment: Alignment.center,
child: Image.asset(
'images/lake.jpg',
fit: BoxFit.cover,
),
),
new ClipOval(
child: new Align(
alignment: Alignment.topCenter,
heightFactor: 0.5,
child: new Image.network(userAvatarUrl),
),
),
ClipPath(
clipper: InvertedCircleClipper(),
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.8),
),
),
],
),
),
],
),
),
),
);
}
}
class InvertedCircleClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
return Path()
// くり抜き
..addOval(
Rect.fromCircle(
center: Offset(size.width / 2, size.height / 2),
radius: size.width * 0.25,
),
)
// 全体描画
..addRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height))
..fillType = PathFillType.evenOdd;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
参考)