F.M.
F.M.

Reputation: 760

Flutter - Quarter round Button

For my Flutter App I want that four buttons together are a circle. Here an Image of what i kinda want. enter image description here

I don't know how to style the corners of a button in flutter. In case of button 1 my idea would be to take the upper left corner and set the border radius and leave the other corners normal. With the other buttons I would do the same with the appropriated corners. To arrange my "pizza slices" i would use Colums and Rows. I just don't know and couldn't figure out how to style only one corner.

Thanks for everyone in advance for helping.

Upvotes: 1

Views: 768

Answers (4)

Huseyn
Huseyn

Reputation: 412

Hi I do that with Grid View and "Clip R Rec t" enter image description here

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: ClipRRect(
            borderRadius: BorderRadius.circular(100),
            child: Container(
              height: 120,
              width: 120,
              child: GridView.count(
                primary: false,
                padding: const EdgeInsets.all(0),
                crossAxisSpacing: 3,
                mainAxisSpacing: 3,
                crossAxisCount: 2,
                children: [
                  ElevatedButton(
                    onPressed: () {},
                    child: Text("1", textAlign: TextAlign.right),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {},
                    child: Text("2", textAlign: TextAlign.center),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {},
                    child: Text("3", textAlign: TextAlign.center),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {},
                    child: Text("4", textAlign: TextAlign.center),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

and you can use Align Widget and put your numbers in align to you have a beautiful UI like this : enter image description here

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: ClipRRect(
            borderRadius: BorderRadius.circular(100),
            child: Container(
              height: 120,
              width: 120,
              child: GridView.count(
                primary: false,
                padding: const EdgeInsets.all(0),
                crossAxisSpacing: 3,
                mainAxisSpacing: 3,
                crossAxisCount: 2,
                children: [
                  ElevatedButton(
                    onPressed: () {},
                    child: Align(
                      alignment: Alignment(0.5, 0),
                      child: Text("1", textAlign: TextAlign.center),
                    ),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {},
                    child: Align(
                      alignment: Alignment(-0.5, 0),
                      child: Text("2", textAlign: TextAlign.center),
                    ),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {},
                    child: Align(
                      alignment: Alignment(0.5, 0),
                      child: Text("3", textAlign: TextAlign.center),
                    ),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {},
                    child: Align(
                      alignment: Alignment(-0.5, 0),
                      child: Text("4", textAlign: TextAlign.center),
                    ),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blueGrey,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

you can compare between images and code and If you liked my answer and it was useful, I will be happy for you to rate my answer. Thank You.

Upvotes: 2

F.M.
F.M.

Reputation: 760

Thank you to everyone here! I got an solution based of this Question: [https://stackoverflow.com/questions/53138955/how-can-i-make-a-buttons-corner-only-rounded-on-the-top]

And based of the answer of @fusion

My solution looks like this:

import 'package:flutter/material.dart';

enum QuarterPosition { topLeft, topRight, bottomLeft, bottomRight }

class QuarterButton extends StatelessWidget {
  const QuarterButton({Key? key, required this.position, this.size = 100, this.text = ""}) : super(key: key);

  final QuarterPosition position;
  final double size;
  final String text;

  BorderRadiusGeometry _generateBorderRadius() {
    switch (position) {
      case QuarterPosition.topLeft:
        return BorderRadius.only(
          topLeft: Radius.circular(size),
        );
      case QuarterPosition.topRight:
        return BorderRadius.only(
          topRight: Radius.circular(size),
        );
      case QuarterPosition.bottomLeft:
        return BorderRadius.only(
          bottomLeft: Radius.circular(size),
        );
      case QuarterPosition.bottomRight:
        return BorderRadius.only(
          bottomRight: Radius.circular(size),
        );
    }
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
        onPressed: () {},
        child: Text(text, style: TextStyle(fontSize: 30, color: Colors.white)),
        style: ElevatedButton.styleFrom(
          primary: Colors.black54,
          fixedSize: Size(size, size),
          shape: RoundedRectangleBorder(
              borderRadius: _generateBorderRadius(),
              ),
              side: BorderSide(color: Colors.white)),
        );
  }
}

And I can use it now like that.

Column(
      children: [
        Row(
          children: [
            QuarterButton(position: QuarterPosition.topLeft, size: 100, text: "1"),
            QuarterButton(position: QuarterPosition.topRight, size: 100, text: "2"),
          ],
        ),
        Row(
          children: [
            QuarterButton(position: QuarterPosition.bottomLeft, size: 100, text: "3"),
            QuarterButton(position: QuarterPosition.bottomRight, size: 100, text: "4"),
          ],
        ),
      ],
    );

Thanks for all the quick answers. Great community! :)

Upvotes: 0

Omar Mahmoud
Omar Mahmoud

Reputation: 3087

you can do it inside a card like this

@override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('My App'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Card(
            clipBehavior: Clip.antiAlias,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(60.0),
            ),
            child: SizedBox(
              width: 120,
              height: 120,
              child: Center(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Expanded(
                      child: Row(
                        children: [
                          Expanded(
                            child: InkWell(
                                onTap: () {},
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: Text("1"),
                                )),
                          ),
                          Expanded(
                            child: InkWell(
                                onTap: () {},
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: Text("2"),
                                )),
                          )
                        ],
                      ),
                    ),
                    Expanded(
                      child: Row(
                        mainAxisSize: MainAxisSize.min,
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Expanded(
                            child: InkWell(
                                onTap: () {},
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: Text("1"),
                                )),
                          ),
                          Expanded(
                            child: InkWell(
                                onTap: () {},
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: Text("2"),
                                )),
                          )
                        ],
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        ));
  }

Upvotes: 0

fusion
fusion

Reputation: 457

One possible solution would be to create a Container with a fixed width and height. Then you set a background color and the border radius with BorderRadius.only for topLeft, topRight etc. Now you only have to create a column with two rows containing your respective containers.

E.g.:

// pizza_button.dart
enum PizzaPosition { topLeft, topRight, bottomLeft, bottomRight }

class PizzaButton extends StatelessWidget {
  final PizzaPosition pizzaPosition;
  final _buttonSize = 60.0;

  const PizzaButton({Key? key, required this.pizzaPosition}) : super(key: key);

  BorderRadiusGeometry? _generateBorderRadius() {
    switch (pizzaPosition) {
      case PizzaPosition.topLeft:
        return BorderRadius.only(
          topLeft: Radius.circular(_buttonSize),
        );
      case PizzaPosition.topRight:
        return BorderRadius.only(
          topRight: Radius.circular(_buttonSize),
        );
      case PizzaPosition.bottomLeft:
        return BorderRadius.only(
          bottomLeft: Radius.circular(_buttonSize),
        );
      case PizzaPosition.bottomRight:
        return BorderRadius.only(
          bottomRight: Radius.circular(_buttonSize),
        );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: _buttonSize,
      height: _buttonSize,
      margin: EdgeInsets.all(1.0),
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: _generateBorderRadius(),
      ),
      child: Text("1"),
    );
  }
}

And for the whole "pizza" an example widget would be

class Pizza extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              PizzaButton(pizzaPosition: PizzaPosition.topLeft),
              PizzaButton(pizzaPosition: PizzaPosition.topRight),
            ],
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              PizzaButton(pizzaPosition: PizzaPosition.bottomLeft),
              PizzaButton(pizzaPosition: PizzaPosition.bottomRight),
            ],
          )
        ],
      ),
    );
  }
}

Now to have it work as buttons you should wrap the containers inside PizzaButton in GestureDetectors and specify your action onTap which can be hold as another property of PizzaButton for example.

Upvotes: 1

Related Questions