答案 0 :(得分:1)
这对你有用吗?
您应该可以使用自定义 NotchedShape
来做到这一点:
class CustomNotchedShape extends NotchedShape {
const CustomNotchedShape();
@override
Path getOuterPath(Rect host, Rect guest) {
final x = math.min(host.width / 20, host.height / 3);
final guestMargin = guest == null ? 0 : 1.0;
if (guest == null || !host.overlaps(guest)) {
guest = Rect.fromCenter(
center: Offset(host.width / 2, host.top), width: 0, height: 0);
}
num degToRad(num deg) => deg * (math.pi / 180.0);
return Path()
..moveTo(host.left, host.bottom)
..quadraticBezierTo(
host.left + x, host.bottom, host.left + x, host.bottom - x)
..lineTo(host.left + x, host.top + x)
..quadraticBezierTo(host.left + x, host.top, host.left + 2 * x, host.top)
..lineTo(guest.left, host.top)
..arcTo(
Rect.fromCenter(
center: guest.center,
width: guest.width + 2 * guestMargin,
height: guest.width + 2 * guestMargin),
degToRad(180),
degToRad(-180),
false)
..lineTo(host.right - 2 * x, host.top)
..quadraticBezierTo(
host.right - x, host.top, host.right - x, host.top + x)
..lineTo(host.right - x, host.bottom - x)
..quadraticBezierTo(host.right - x, host.bottom, host.right, host.bottom)
..close();
}
}
然后,您使用此 CustomNotchedShape
作为您的 shape
的 BottomAppBar
:
class MyBottomNavigationBar extends HookWidget {
@override
Widget build(BuildContext context) {
final _currentIndex = useState(1);
void navigateTo(int index) => _currentIndex.value = index;
bool active(int index) => _currentIndex.value == index;
return BottomAppBar(
color: Theme.of(context).primaryColor,
shape: CustomNotchedShape(),
child: Container(
height: 50,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
onPressed: () => navigateTo(0),
icon: Icon(Icons.home_outlined),
color: active(0) ? Colors.white : Colors.black,
),
IconButton(
onPressed: () => navigateTo(1),
icon: Icon(Icons.horizontal_split_outlined),
color: active(1) ? Colors.white : Colors.black,
),
Padding(
padding: EdgeInsets.only(top: 24.0),
child: Text('New task'),
),
IconButton(
onPressed: () => navigateTo(2),
icon: Icon(Icons.access_time_outlined),
color: active(2) ? Colors.white : Colors.black,
),
IconButton(
onPressed: () => navigateTo(3),
icon: Icon(Icons.settings_outlined),
color: active(3) ? Colors.white : Colors.black,
),
],
),
),
),
),
);
}
}
为了方便复制粘贴。
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
scaffoldBackgroundColor: Color(0xffd3ccca),
primaryColor: Color(0xff86736c),
accentColor: Color(0xff76504e),
),
title: 'Flutter Demo',
home: Scaffold(
body: MyContent(),
bottomNavigationBar: MyBottomNavigationBar(),
floatingActionButton: FloatingActionButton(
mini: true,
onPressed: () => print('Adding new task...'),
child: Icon(Icons.add),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.miniCenterDocked,
),
),
);
}
class MyContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text('Does this work for you?'));
}
}
class MyBottomNavigationBar extends HookWidget {
@override
Widget build(BuildContext context) {
final _currentIndex = useState(1);
void navigateTo(int index) => _currentIndex.value = index;
bool active(int index) => _currentIndex.value == index;
return BottomAppBar(
color: Theme.of(context).primaryColor,
shape: CustomNotchedShape(),
child: Container(
height: 50,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
onPressed: () => navigateTo(0),
icon: Icon(Icons.home_outlined),
color: active(0) ? Colors.white : Colors.black,
),
IconButton(
onPressed: () => navigateTo(1),
icon: Icon(Icons.horizontal_split_outlined),
color: active(1) ? Colors.white : Colors.black,
),
Padding(
padding: EdgeInsets.only(top: 24.0),
child: Text('New task'),
),
IconButton(
onPressed: () => navigateTo(2),
icon: Icon(Icons.access_time_outlined),
color: active(2) ? Colors.white : Colors.black,
),
IconButton(
onPressed: () => navigateTo(3),
icon: Icon(Icons.settings_outlined),
color: active(3) ? Colors.white : Colors.black,
),
],
),
),
),
),
);
}
}
class CustomNotchedShape extends NotchedShape {
const CustomNotchedShape();
@override
Path getOuterPath(Rect host, Rect guest) {
final x = math.min(host.width / 20, host.height / 3);
final guestMargin = guest == null ? 0 : 1.0;
if (guest == null || !host.overlaps(guest)) {
guest = Rect.fromCenter(
center: Offset(host.width / 2, host.top), width: 0, height: 0);
}
num degToRad(num deg) => deg * (math.pi / 180.0);
return Path()
..moveTo(host.left, host.bottom)
..quadraticBezierTo(
host.left + x, host.bottom, host.left + x, host.bottom - x)
..lineTo(host.left + x, host.top + x)
..quadraticBezierTo(host.left + x, host.top, host.left + 2 * x, host.top)
..lineTo(guest.left, host.top)
..arcTo(
Rect.fromCenter(
center: guest.center,
width: guest.width + 2 * guestMargin,
height: guest.width + 2 * guestMargin),
degToRad(180),
degToRad(-180),
false)
..lineTo(host.right - 2 * x, host.top)
..quadraticBezierTo(
host.right - x, host.top, host.right - x, host.top + x)
..lineTo(host.right - x, host.bottom - x)
..quadraticBezierTo(host.right - x, host.bottom, host.right, host.bottom)
..close();
}
}