Jonas
Jonas

Reputation: 7935

Container with rounded border but top border has different width than other sides

I'm trying to create a container that has a rounded border but the top border is wider than the rest to fit some text (probably using a Stack).

Something like this:

enter image description here

How ever I haven't found a way to achieve this. I tried this:

return Container(
  decoration: BoxDecoration(
    border: Border(
      left: BorderSide(color: MyColors.backgroundColor1(context), width: 5, style: BorderStyle.solid),
      right: BorderSide(color: MyColors.backgroundColor1(context), width: 5, style: BorderStyle.solid),
      bottom: BorderSide(color: MyColors.backgroundColor1(context), width: 5, style: BorderStyle.solid),
      top: BorderSide(color: MyColors.backgroundColor1(context), width: 25, style: BorderStyle.solid),
    ),
  ),
  child: ...
);

But this way I can't add any border radius.

Any idea how to achieve this in Flutter?

Upvotes: 1

Views: 1717

Answers (1)

Spencer Stolworthy
Spencer Stolworthy

Reputation: 1440

Here is a minimum reproducible sample:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(
          decoration: BoxDecoration(
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(10), topRight: Radius.circular(10))),
          clipBehavior: Clip.antiAlias,
          child: Container(
            decoration: BoxDecoration(
                border: Border(
              top: BorderSide(color: Colors.black, width: 20),
              left: BorderSide(color: Colors.black, width: 2),
              bottom: BorderSide(color: Colors.black, width: 2),
              right: BorderSide(color: Colors.black, width: 2),
            )),
          ),
        ),
      ),
    );
  }
}

You could also achieve this with a stack, though I suspect this is closer to what you're looking for. The key is the clip in the parent container. That will hide everything that overflows from that parent container.

EDIT After taking a closer look at your picture, I think a stack is the best way to go. That will easily allow you to put the text up in that top border. Here's an example widget:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Material(
        child: Padding(
          padding: EdgeInsets.all(20),
          child: Stack(
            children: [
              Positioned.fill(
                  child: Container(
                decoration: BoxDecoration(
                    color: Colors.black,
                    borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(10),
                        topRight: Radius.circular(10))),
              )),
              Positioned.fill(
                  child: Column(children: [
                Text("Sample Text",
                    style: TextStyle(color: Colors.white, fontSize: 18)),
                Expanded(
                    child: Padding(
                  padding: const EdgeInsets.all(2.0),
                  child: Container(
                    decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.only(
                            topLeft: Radius.circular(10),
                            topRight: Radius.circular(10))),
                  ),
                ))
              ]))
            ],
          ),
        ),
      ),
    );
  }
}

Basically, you stack a column on top of a container that is filled with your "border" color. The first element in that column is the text you want to show in the "border". Then, you fill the rest of the column with an expanded widget and container whose color is your background color. That container is wrapped in padding, which provides you with the border width on the left, right, and bottom of the widget.

Upvotes: 1

Related Questions