简体   繁体   中英

Flutter : Achieved Sliverappbar Shape

I'm found some Appbar design in Dribble https://dribbble.com/shots/9175650-Beauty-Salon-App/attachments/1218583?mode=media , I try to create same like that but i confused get border radius each other side.

Trial 1 Without Background :

Trial 2 With Scaffold Background Color Blue

Trial 3 With background Color Deep Orange

How can i achieved appbar design like the link ?

Source Code

import 'package:flutter/material.dart';
import 'package:flutter_iconpicker/flutter_iconpicker.dart';

class TestingScreen extends StatelessWidget {
  static const routeName = "/testing-screen";
  @override
  Widget build(BuildContext context) {
    var mediaQuery = MediaQuery.of(context);

    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            expandedHeight: mediaQuery.size.height / 4,
            backgroundColor: Colors.deepOrange,
            shape: RoundedRectangleBorder(
                borderRadius:
                    BorderRadius.only(bottomRight: Radius.circular(80))),
          ),
          SliverList(
            delegate: SliverChildListDelegate(
              [
                Container(
                  height: mediaQuery.size.height,
                  decoration: BoxDecoration(
                      color: Colors.blue,
                      borderRadius:
                          BorderRadius.only(topLeft: Radius.circular(80))),
                  child: Center(child: Text('data')),
                )
              ],
            ),
          )
        ],
      ),
    );
  }
}

You can actually use CustomClipper to do this, with a method of Path quadraticBezierTo :

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Stack(
          children: <Widget>[
            Container(color: Colors.orange),
            ClipPath(
              clipper: TheCustomClipper(),
              child: Container(
                color: Colors.greenAccent,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class TheCustomClipper extends CustomClipper<Path> {
  @override
  getClip(Size size) {
    var path = Path();
    path.lineTo(0, size.height / 3);
    var firstControlPoint = Offset(0, size.height / 3.5); // adjust the height to move start of the first curve
    var firstEndPoint = Offset(size.width / 4.2, size.height / 3.5 + 10); // adjust the width to add the end controll point and height to move end of the first curve

    var secControlPoint = Offset(size.width, size.height / 2.8); // adjust the height to move end of the second curve
    var secEndPoint = Offset(size.width, size.height / 3 - 40); // adjust the width to add the right first controll point and height to move start of the second curve

    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstEndPoint.dx, firstEndPoint.dy);
    path.quadraticBezierTo(
        secControlPoint.dx, secControlPoint.dy, secEndPoint.dx, secEndPoint.dy);

    path.lineTo(size.width, size.height / 3);
    path.lineTo(size.width, 0);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper oldClipper) {
    return null;
  }
}

Do note that, I only added curve to first widget. If you want to add another CustomClipper to the first Container of the Stack , do it by doing the reverse of the logic.

Output:

在此处输入图片说明

Source Code:

import 'package:flutter/material.dart';

import '../../../shared/app_colors.dart';

class WelcomenPage extends StatelessWidget {
  static const id = 'welcomen_page';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Stack(
        children: <Widget>[
          ClipPath(
            child: Container(
              height: MediaQuery.of(context).size.height,
              color: AppColors.primary,
            ),
            clipper: BottomWaveClipper(),
          ),
        ],
      ),
    );
  }
}

class BottomWaveClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    var path = Path();
    path.lineTo(0, size.height * .65);

    var firstControlPoint = Offset(0, size.height * .75);
    var firstEndPoint = Offset(size.width / 6, size.height * .75);

    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstEndPoint.dx, firstEndPoint.dy);

    path.lineTo(size.width / 1.2, size.height * .75);

    var secControlPoint = Offset(size.width, size.height * .75);
    var secEndPoint = Offset(size.width, size.height * 0.85);

    path.quadraticBezierTo(
        secControlPoint.dx, secControlPoint.dy, secEndPoint.dx, secEndPoint.dy);

    path.lineTo(size.width, 0);
    path.close();

    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

Output: image

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM