如何使用弯曲的背景创建这种类型的底部导航栏? [英] How to create this type of bottom navigation bar with curved background?

查看:89
本文介绍了如何使用弯曲的背景创建这种类型的底部导航栏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试了一些包装并与图片堆叠在一起,但是它对我不起作用.任何帮助都会很棒.

I have tried some packages and stack with image but it is not working for me. Any help would be great.

具有曲线的背景图像不起作用.

Background image with curve is not working.

推荐答案

这对您有用吗?

您应该能够使用自定义的 NotchedShape :

You should be able to do that with a custom 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 用作 BottomAppBar shape :

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();
  }
}

这篇关于如何使用弯曲的背景创建这种类型的底部导航栏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆