Я работаю в приложении флаттера. Но мне трудно работать с пользовательским интерфейсом Flutter, потому что он не совсем соответствует пользовательскому интерфейсу.
Это дизайн пользовательского интерфейса.
И это текущий пользовательский интерфейс флаттера.
Это мой код.
Widget buildBottomBar() {
return BottomAppBar(
elevation: 0.0,
shape: const CircularNotchedRectangle(),
notchMargin: 5.0,
clipBehavior: Clip.antiAlias,
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 10,
color: Colors.transparent,
),
),
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
iconSize: 28,
elevation: 0.0,
currentIndex: selectedIndex,
selectedLabelStyle: robotoStyle(FontWeight.w500,
const Color.fromARGB(255, 49, 48, 54), null, null),
showUnselectedLabels: true,
unselectedLabelStyle:
robotoStyle(FontWeight.w500, const Color(0xff313036), null, null),
unselectedItemColor: const Color(0xff313036),
selectedItemColor: const Color(0xff313036),
selectedIconTheme: const IconThemeData(color: Color(0xffff2323)),
onTap: onBottomBarButtonTapped,
backgroundColor: Colors.transparent,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
activeIcon: Icon(
Icons.signal_cellular_alt_rounded,
color: Color(0xffff2323),
),
icon: Icon(
Icons.signal_cellular_alt_rounded,
color: Color(0xff313036),
),
label: "Trend",
),
BottomNavigationBarItem(
activeIcon: Icon(
CupertinoIcons.calendar,
color: Color(0xffff2323),
),
icon: Icon(
CupertinoIcons.calendar,
color: Color(0xff313036),
),
label: "Calendar",
),
BottomNavigationBarItem(
activeIcon: Icon(
Icons.search_rounded,
color: Colors.transparent,
),
icon: Icon(
Icons.search_rounded,
color: Colors.transparent,
),
label: "",
),
BottomNavigationBarItem(
activeIcon: Icon(
CupertinoIcons.arrow_2_circlepath,
color: Color(0xffff2323),
),
icon: Icon(
CupertinoIcons.arrow_2_circlepath,
color: Color(0xff313036),
),
label: "Restock",
),
BottomNavigationBarItem(
activeIcon: Icon(
Icons.account_circle,
color: Color(0xffff2323),
),
icon: Icon(
Icons.account_circle,
color: Color(0xff313036),
),
label: "Account",
),
],
),
),
// ),
);
}
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
resizeToAvoidBottomInset: false,
appBar: null,
backgroundColor: Colors.white,
body: ...,
bottomNavigationBar: buildBottomBar(),
floatingActionButton: Padding(
padding: const EdgeInsets.all(5.0),
child: FloatingActionButton(...)
),
}
И следующая проблема — это как раз радиус под плавающей кнопкой поиска. Как применить радиус границы, как этот дизайн?
Дайте мне знать, как это сделать как можно скорее.
Привет, @mohammadesmaili. Любые другие альтернативы? Это сводит меня с ума.
А как сделать отступ вокруг нижнего AppBar'а?
Я решил это, настроив стандартный пакет. Причина этому явление возникает из-за того, что край смещается вправо применяется Margin или Padding. То есть решение состоит в том, чтобы переместить клипера влево или вправо в зависимости от примененного поля или заполнения. Затем я ниже будет представлено пошаговое решение.
- Нажмите Ctrl+B (для Android Studio) или F12 (для VS Code) на BottomAppBar().
Нажмите целевую кнопку.
- Скопируйте файл bottom_app_bar.dart в каталог пользовательских библиотек, затем переименуйте его в custom_bottom_app_bar.dart.
- Измените часть кода в новом файле custom_bottom_app_bar.dart.
- Все сделано. Наслаждайтесь новым виджетом.
- Ниже я добавлю полный пример кода.
custom_bottom_app_bar.dart
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.*
import 'package:flutter/foundation.dart';
// import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
// import 'bottom_app_bar_theme.dart';
// import 'elevation_overlay.dart';
// import 'package:flutter/material.dart';
// import 'scaffold.dart';
// import 'theme.dart';
// Examples can assume:
// late Widget bottomAppBarContents;
/// A container that is typically used with [Scaffold.bottomNavigationBar], and
/// can have a notch along the top that makes room for an overlapping
/// [FloatingActionButton].
///
/// Typically used with a [Scaffold] and a [FloatingActionButton].
///
/// {@tool snippet}
/// ```dart
/// Scaffold(
/// bottomNavigationBar: CustomBottomAppBar(
/// color: Colors.white,
/// child: bottomAppBarContents,
/// ),
/// floatingActionButton: const FloatingActionButton(onPressed: null),
/// )
/// ```
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows the [CustomBottomAppBar], which can be configured to have a notch using the
/// [CustomBottomAppBar.shape] property. This also includes an optional [FloatingActionButton], which illustrates
/// the [FloatingActionButtonLocation]s in relation to the [CustomBottomAppBar].
///
/// ** See code in examples/api/lib/material/bottom_app_bar/bottom_app_bar.1.dart **
/// {@end-tool}
///
/// See also:
///
/// * [NotchedShape] which calculates the notch for a notched [CustomBottomAppBar].
/// * [FloatingActionButton] which the [CustomBottomAppBar] makes a notch for.
/// * [AppBar] for a toolbar that is shown at the top of the screen.
class CustomBottomAppBar extends StatefulWidget {
/// Creates a bottom application bar.
///
/// The [clipBehavior] argument defaults to [Clip.none] and must not be null.
/// Additionally, [elevation] must be non-negative.
///
/// If [color], [elevation], or [shape] are null, their [BottomAppBarTheme] values will be used.
/// If the corresponding [BottomAppBarTheme] property is null, then the default
/// specified in the property's documentation will be used.
const CustomBottomAppBar({
super.key,
this.color,
this.elevation,
this.shape,
this.clipBehavior = Clip.none,
this.notchMargin = 4.0,
this.child,
this.positionInHorizontal = 0.0,
}) : assert(elevation == null || elevation >= 0.0);
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.ProxyWidget.child}
///
/// Typically this the child will be a [Row], with the first child
/// being an [IconButton] with the [Icons.menu] icon.
final Widget? child;
/// The bottom app bar's background color.
///
/// If this property is null then [BottomAppBarTheme.color] of
/// [ThemeData.bottomAppBarTheme] is used. If that's null then
/// [ThemeData.bottomAppBarColor] is used.
final Color? color;
/// The z-coordinate at which to place this bottom app bar relative to its
/// parent.
///
/// This controls the size of the shadow below the bottom app bar. The
/// value is non-negative.
///
/// If this property is null then [BottomAppBarTheme.elevation] of
/// [ThemeData.bottomAppBarTheme] is used. If that's null, the default value
/// is 8.
final double? elevation;
/// The notch that is made for the floating action button.
///
/// If this property is null then [BottomAppBarTheme.shape] of
/// [ThemeData.bottomAppBarTheme] is used. If that's null then the shape will
/// be rectangular with no notch.
final NotchedShape? shape;
/// {@macro flutter.material.Material.clipBehavior}
///
/// Defaults to [Clip.none], and must not be null.
final Clip clipBehavior;
/// The margin between the [FloatingActionButton] and the [CustomBottomAppBar]'s
/// notch.
///
/// Not used if [shape] is null.
final double notchMargin;
final double positionInHorizontal;
@override
State createState() => _CustomBottomAppBarState();
}
class _CustomBottomAppBarState extends State<CustomBottomAppBar> {
late ValueListenable<ScaffoldGeometry> geometryListenable;
final GlobalKey materialKey = GlobalKey();
static const double _defaultElevation = 8.0;
@override
void didChangeDependencies() {
super.didChangeDependencies();
geometryListenable = Scaffold.geometryOf(context);
}
@override
Widget build(BuildContext context) {
final BottomAppBarTheme babTheme = BottomAppBarTheme.of(context);
final bool hasFab = Scaffold.of(context).hasFloatingActionButton;
final NotchedShape? notchedShape = widget.shape ?? babTheme.shape;
final CustomClipper<Path> clipper = notchedShape != null && hasFab
? _BottomAppBarClipper(
geometry: geometryListenable,
shape: notchedShape,
materialKey: materialKey,
notchMargin: widget.notchMargin,
position2MoveHorizontal: widget.positionInHorizontal,
)
: const ShapeBorderClipper(shape: RoundedRectangleBorder());
final double elevation =
widget.elevation ?? babTheme.elevation ?? _defaultElevation;
final Color color =
widget.color ?? babTheme.color ?? Theme.of(context).bottomAppBarColor;
final Color effectiveColor =
ElevationOverlay.applyOverlay(context, color, elevation);
return PhysicalShape(
clipper: clipper,
elevation: elevation,
color: effectiveColor,
clipBehavior: widget.clipBehavior,
child: Material(
key: materialKey,
type: MaterialType.transparency,
child: widget.child == null ? null : SafeArea(child: widget.child!),
),
);
}
}
class _BottomAppBarClipper extends CustomClipper<Path> {
const _BottomAppBarClipper({
required this.geometry,
required this.shape,
required this.materialKey,
required this.notchMargin,
required this.position2MoveHorizontal,
}) : super(reclip: geometry);
final ValueListenable<ScaffoldGeometry> geometry;
final NotchedShape shape;
final GlobalKey materialKey;
final double notchMargin;
final double position2MoveHorizontal;
// Returns the top of the CustomBottomAppBar in global coordinates.
//
// If the Scaffold's bottomNavigationBar was specified, then we can use its
// geometry value, otherwise we compute the location based on the AppBar's
// Material widget.
double get bottomNavigationBarTop {
final double? bottomNavigationBarTop =
geometry.value.bottomNavigationBarTop;
if (bottomNavigationBarTop != null) {
return bottomNavigationBarTop;
}
final RenderBox? box =
materialKey.currentContext?.findRenderObject() as RenderBox?;
return box?.localToGlobal(Offset.zero).dy ?? 0;
}
@override
Path getClip(Size size) {
// button is the floating action button's bounding rectangle in the
// coordinate system whose origin is at the appBar's top left corner,
// or null if there is no floating action button.
final Rect? button = geometry.value.floatingActionButtonArea
?.translate(position2MoveHorizontal, bottomNavigationBarTop * -1.0);
return shape.getOuterPath(Offset.zero & size, button?.inflate(notchMargin));
}
@override
bool shouldReclip(_BottomAppBarClipper oldClipper) {
return oldClipper.geometry != geometry ||
oldClipper.shape != shape ||
oldClipper.notchMargin != notchMargin;
}
}
дом.дарт
Widget buildBottomBar() {
Map bottomAppBarMargin = {
'left': 20.0,
'right': 20.0,
'bottom': 12.0,
'top': 0.0,
};
return Container(
margin: EdgeInsets.only(
left: bottomAppBarMargin['left'],
right: bottomAppBarMargin['right'],
bottom: bottomAppBarMargin['bottom'],
top: bottomAppBarMargin['top'],
),
child: CustomBottomAppBar(
elevation: 0.0,
positionInHorizontal: (0.0-bottomAppBarMargin['left']),
color: Colors.white,
shape: const CircularNotchedRectangle(),
notchMargin: 5.0,
clipBehavior: Clip.antiAlias,
child: SizedBox(...)
),
);
}
Результат
Вы не можете сделать так много изогнутых, но есть пакет curved_navigation_bar, который делает то, что вам нравится, но проблема в том, что вы не можете сделать фиксированное плавание