The value is effectively changing when clicking but the animation doesn't show :
Here's my code :
var editGender = Padding(
padding: const EdgeInsets.only(top: 12.0),
child: Column(
children: <Widget>[
CheckboxListTile(
value: _male,
onChanged: _maleChanged,
title: Text("Male"),
activeColor: Theme.of(context).primaryColor,
),
CheckboxListTile(
value: _female,
onChanged: _femaleChanged,
title: Text("Female"),
activeColor: Theme.of(context).primaryColor,
)
],
),
);
When tapping the edit button :
FlatButton(
onPressed: (){
buildShowRoundedModalBottomSheet(context, title, editGender, option);
},
child: Text('Edit'),
it shows the bottom sheet :
Future buildShowRoundedModalBottomSheet(BuildContext context, String title, Widget content,[String date]) {
return showRoundedModalBottomSheet(
context: context,
radius: 20.0,
builder: (context){
return Padding(
padding: const EdgeInsets.only(top: 20.0, bottom: 20.0, left: 20.0, right: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
title,
style: TextStyle(
fontFamily: 'SamsungSans',
fontSize: 20.0,
),
),
content,
...
I am passing the same context to the widget :/
setState would change the value but it wouldn't rebuild your bottom sheet as it is being called on a onPressed of a FlatButton. You are certainly not invoking that onPressed again but you wouldn't want to do it either.
As I mentioned in the comments a StatefulBuilder would do the job.
A working example
import 'package:flutter/material.dart';
import 'package:rounded_modal/rounded_modal.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool value = false;
void _incrementCounter() {
showRoundedModalBottomSheet(
context: context,
builder: (context) {
return StatefulBuilder(builder: (context, setState) {
return Container(
height: 200.0,
child: Checkbox(value: value, onChanged: (val) {
setState(() {
value = val;
});
}),
);
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
As commented by #10101010, you'll have to use a Stateful widget. And In _femaleChanged and _maleChanged, you'll have to use setState(). Example :
void _femaleChanged(bool value) => setState(() => _female = value);
Related
good evening. I am currently doing a To-do List in Flutter and I want to pass the Title of my List and the Description of my List when I click on a new screen but upon setting up Routes and and declaring the values on my next, it shows the "2 positional arguments expected, but 0 found" on the routes I've set up. Here are my codes:
Here is my 1st screen:
import 'package:flutter/material.dart';
import 'package:todo_list/details.dart';
import 'package:todo_list/note.dart';
class MyApp extends StatelessWidget {
final String text;
final int number;
final String listDescription;
const MyApp(
{super.key,
required this.text,
required this.number,
required this.listDescription});
#override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
DetailsPage.routeName: (ctx) => DetailsPage(),
},
home: CustomListTile(
text: text,
number: number,
listDescription: listDescription,
),
);
}
}
class CustomListTile extends StatelessWidget {
final String text;
final int number;
final String listDescription;
const CustomListTile(
{super.key,
required this.text,
required this.number,
required this.listDescription});
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
Navigator.pushNamed(context, DetailsPage.routeName,
arguments: Note(title: text, description: listDescription));
},
/* onTap: () {
Widget okButton = TextButton(
child: const Text("CLOSE"),
onPressed: () {
Navigator.of(context).pop();
},
);
AlertDialog alert = AlertDialog(
title: Text(text),
content: Text('This item in the list contains $listDescription'),
actions: [
okButton,
]);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
});
}, */
child: Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("$number. $text",
style: const TextStyle(
fontSize: 20,
)),
const Icon(Icons.chevron_right)
],
),
Text(
listDescription,
style: const TextStyle(fontSize: 14, color: Colors.grey),
),
const Divider()
],
),
),
);
}
}
and here is my 2nd screen:
import 'package:flutter/material.dart';
import 'note.dart';
class DetailsPage extends StatefulWidget {
static const String routeName = "/details";
final String text;
final String listDescription;
const DetailsPage(this.text, this.listDescription, {super.key});
#override
State<DetailsPage> createState() => _DetailsPageState();
}
class _DetailsPageState extends State<DetailsPage> {
late Note params;
#override
void didChangeDependencies() {
params = ModalRoute.of(context)!.settings.arguments! as Note;
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
Widget titleSection = Container(
padding: const EdgeInsets.all(32),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(bottom: 0),
child: Text(
params.title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
),
],
),
),
],
),
);
Color color = Theme.of(context).primaryColor;
Widget buttonSection = Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(
color,
Icons.edit,
'EDIT',
),
_buildButtonColumn(color, Icons.delete, 'DELETE'),
],
);
Widget textSection = Padding(
padding: const EdgeInsets.all(20),
child: Text(
params.description,
softWrap: true,
),
);
return MaterialApp(
title: 'Layout for a New Screen',
theme: ThemeData(
primarySwatch: Colors.brown,
),
home: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
title: Text(params.title),
),
body: ListView(
children: [
Image.asset(
'lib/images/placeholder.jpg',
width: 600,
height: 240,
fit: BoxFit.cover,
),
titleSection,
buttonSection,
textSection,
],
),
),
);
}
Column _buildButtonColumn(
Color color,
IconData icon,
String label,
) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: color),
Container(
margin: const EdgeInsets.only(top: 8),
child: Text(
label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
}
/* return Scaffold(
appBar: AppBar(title: Text(text)),
body: Center(
child: Row(
children: [Text(description)],
),
));
}
} */
How do I make it so that the data I'll pass such as the Title and the Description will appear on the 2nd screen without the error "2 positional argument(s) expected, but 0 found.
Try adding the missing arguments." appearing.
I tried the Quick Fixes on VS Code such as adding a const modifier but I think the const modifier wouldn't do a fix since both data I'm trying to pass are dynamic and may change from time to time.
As you've define details page
class DetailsPage extends StatefulWidget {
static const String routeName = "/details";
final String text;
final String listDescription;
const DetailsPage(this.text, this.listDescription, {super.key});
You need to pass two string as positional argument.
So it can be
routes: {
DetailsPage.routeName: (ctx) => DetailsPage("text","description"),
},
also while you are using route arguments, you can remove theses from widget class and just accept from state class context with ModalRoute.
You can check this example and development/ui/navigation .
I was using a list view builder which got its item count from the hive database. I managed to get it to work but its text appeared to be in brackets for example (Apollo, Jesus) any ideas on how to fix it. as in the formatting so it would appear as apollo,jesus. FYI I opened and initiated the box on the main.dart page
here is my code, I'm still learning sorry for bad code.
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
void main() {
runApp(nextpage());
}
class nextpage extends StatefulWidget {
const nextpage({Key? key}) : super(key: key);
#override
State<nextpage> createState() => _nextpageState();
}
class _nextpageState extends State<nextpage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(
Icons.chevron_left,
color: Colors.black,
),
onPressed: () => Navigator.pop(context),
),
backgroundColor: Colors.yellow,
centerTitle: true,
title: Text(
'Database',
style: TextStyle(color: Colors.black),
),
),
backgroundColor: Colors.yellow[200],
body: ListView.builder(
itemCount: Hive.box('db').length,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
Hive.box('db').values.toString(),
style: TextStyle(fontSize: 20),
),
),
],
),
);
},
),
),
),
);
}
}
I tried changing the text to Hive.box('db').values.toString but it didn't provide results
You need to open the box to receive data. You can do
void main() async {
await Hive.openBox('db');
runApp(nextpage());
}
or use FutureBuilder [.open() is a future method] before ListView.
More about using hivedb
Hi guys i am new to flutter. I have a grid of clickable buttons. Right now its only two, but it can grow to many. how can I refactor this to make it more dynamic and handle many future buttons? like a grid list of buttons that you can each click to navigate to different pages.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(30.0),
child: GridView.extent(
maxCrossAxisExtent: 150,
crossAxisSpacing: 15.0,
mainAxisSpacing: 15.0,
children: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ProductScreen(),
),
);
},
padding: EdgeInsets.only(top: 33),
child: Column(
children: [
Icon(
Icons.shopping_cart_outlined,
color: Colors.white,
),
Text(
"Products",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
FlatButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => MailScreen(),
),
);
},
padding: EdgeInsets.only(top: 33),
child: Column(
children: [
Icon(
Icons.mail,
color: Colors.white,
),
Text(
"Mail",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
],
),
),
);
}
}
Here is a solution:
1. Define a AppAction Model
class AppAction {
final Color color;
final String label;
final Color labelColor;
final IconData iconData;
final Color iconColor;
final void Function(BuildContext) callback;
AppAction({
this.color = Colors.blueGrey,
this.label,
this.labelColor = Colors.white,
this.iconData,
this.iconColor = Colors.white,
this.callback,
});
}
You could also have the route or its name instead of a callback function. Though, a callback will allow you to define other types of actions if needed. (example: launching an external URL, triggering a modal dialog, etc.)
2. Defining your Application Actions
final List<AppAction> actions = [
AppAction(
label: 'Products',
iconData: Icons.shopping_cart_outlined,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => ProductScreen()));
},
),
AppAction(
label: 'Mails',
iconData: Icons.mail,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => MailScreen()));
},
),
AppAction(
color: Colors.white,
label: 'Urgent',
labelColor: Colors.redAccent,
iconData: Icons.dangerous,
iconColor: Colors.redAccent,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => UrgentScreen()));
},
),
AppAction(
color: Colors.green.shade200,
label: 'News',
labelColor: Colors.black,
iconData: Icons.new_releases,
iconColor: Colors.green,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => NewsScreen()));
},
),
];
3. Define a generic ActionButton
class ActionButton extends StatelessWidget {
final AppAction action;
const ActionButton({
Key key,
this.action,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return OutlinedButton.icon(
onPressed: () => action.callback?.call(context),
style: OutlinedButton.styleFrom(
backgroundColor: action.color,
padding: const EdgeInsets.all(16.0),
),
label: Text(action.label, style: TextStyle(color: action.labelColor)),
icon: Icon(action.iconData, color: action.iconColor),
);
}
}
4. Simplify your HomePage
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Home Page',
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(30.0),
child: GridView.extent(
maxCrossAxisExtent: 120,
crossAxisSpacing: 15.0,
mainAxisSpacing: 15.0,
children: actions.map((action) => ActionButton(action: action)).toList(),
),
),
);
}
}
VoilĂ ! If you want, here is a full standalone code sample to play with:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class AppAction {
final Color color;
final String label;
final Color labelColor;
final IconData iconData;
final Color iconColor;
final void Function(BuildContext) callback;
AppAction({
this.color = Colors.blueGrey,
this.label,
this.labelColor = Colors.white,
this.iconData,
this.iconColor = Colors.white,
this.callback,
});
}
final List<AppAction> actions = [
AppAction(
label: 'Products',
iconData: Icons.shopping_cart_outlined,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => ProductScreen()));
},
),
AppAction(
label: 'Mails',
iconData: Icons.mail,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => MailScreen()));
},
),
AppAction(
color: Colors.white,
label: 'Urgent',
labelColor: Colors.redAccent,
iconData: Icons.dangerous,
iconColor: Colors.redAccent,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => UrgentScreen()));
},
),
AppAction(
color: Colors.green.shade200,
label: 'News',
labelColor: Colors.black,
iconData: Icons.new_releases,
iconColor: Colors.green,
callback: (context) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => NewsScreen()));
},
),
];
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Home Page',
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(30.0),
child: GridView.extent(
maxCrossAxisExtent: 120,
crossAxisSpacing: 15.0,
mainAxisSpacing: 15.0,
children:
actions.map((action) => ActionButton(action: action)).toList(),
),
),
);
}
}
class AppLayout extends StatelessWidget {
final String pageTitle;
final Widget child;
const AppLayout({Key key, this.pageTitle, this.child}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(pageTitle)),
body: child,
);
}
}
class ActionButton extends StatelessWidget {
final AppAction action;
const ActionButton({
Key key,
this.action,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return OutlinedButton.icon(
onPressed: () => action.callback?.call(context),
style: OutlinedButton.styleFrom(
backgroundColor: action.color,
padding: const EdgeInsets.all(16.0),
),
label: Text(action.label, style: TextStyle(color: action.labelColor)),
icon: Icon(action.iconData, color: action.iconColor),
);
}
}
class ProductScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: ('Products Page'),
child: Center(
child: Text('LIST OF PRODUCTS'),
),
);
}
}
class MailScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Mail Page',
child: Center(
child: Text('LIST OF MAIL'),
),
);
}
}
class UrgentScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'Urgent Page',
child: Center(
child: Text('URGENT', style: TextStyle(color: Colors.redAccent)),
),
);
}
}
class NewsScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AppLayout(
pageTitle: 'News Page',
child: Center(
child: Text('NEWS', style: TextStyle(color: Colors.green)),
),
);
}
}
Create a separate widget for the button and pass the color, icon, Text and route in the params.
Instead of using push in navigator use pushNamed and used the passed route name here.
I want to display 2 radio buttons horizontally on the subtitle of the ListTile.
I can see only one Radio Button.
List<QuestionsOptions> optionsList = [
QuestionsOptions(
index: 1,
name: "Yes",
),
QuestionsOptions(
index: 0,
name: "No",
),
];
subtitle:Column(
children: [
new Row(
children: <Widget>[
Expanded(
child: Container(
child: Column(
children:
optionsList.map((data) => RadioListTile(
title: Text("${data.name}"),
groupValue: 0,
value: data.index,
onChanged: (val) {
//_handleWeightChange(data.name,data.index);
},
)).toList(),
),
)),
],
),
]),
How to display both the radio buttons in horizontal in the subtitle of the Listtile
You can set a Row of RadioListTile in the subTitle of the ListTile. You can then use HashMap to track the selected RadioListTile on the List items. The map can be updated when the radio button is clicked. Or if you're using a List for your ListTiles, you can just add the Answer enum on the Object.
subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Row(
children: [
Expanded(
child: RadioListTile<Answer>(
title: const Text('Yes'),
value: Answer.yes,
groupValue: answerVal[index],
onChanged: (Answer? value) {
setState(() {
// Update map value on tap
answerVal[index] = value;
});
},
),
),
Expanded(
child: RadioListTile<Answer>(
title: const Text('No'),
value: Answer.no,
groupValue: answerVal[index],
onChanged: (Answer? value) {
setState(() {
answerVal[index] = value;
});
},
),
),
],
),
),
Here's the complete sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
enum Answer { yes, no }
class _MyHomePageState extends State<MyHomePage> {
Map<int, Answer?> answerVal = {};
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView.builder(
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: const EdgeInsets.all(16.0),
title: const Text('Question?'),
subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Row(
children: [
Expanded(
child: RadioListTile<Answer>(
title: const Text('Yes'),
value: Answer.yes,
groupValue: answerVal[index],
onChanged: (Answer? value) {
setState(() {
answerVal[index] = value;
});
},
),
),
Expanded(
child: RadioListTile<Answer>(
title: const Text('No'),
value: Answer.no,
groupValue: answerVal[index],
onChanged: (Answer? value) {
setState(() {
answerVal[index] = value;
});
},
),
),
],
),
),
);
},
),
);
}
}
I want to change the size of the CupertinoSwitch in flutter. I have tried putting the switch in Container but changing the size of the container does not affect the switch.
You can copy paste run full code below
You can use Transform.scale and set scale, 1 means normal size, 0.8 means smaller size
code snippet
Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
value: _switchValue,
onChanged: (bool value) {
setState(() {
_switchValue = value;
});
},
),
)
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CupertinoSwitchDemo(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class CupertinoSwitchDemo extends StatefulWidget {
static const String routeName = '/cupertino/switch';
#override
_CupertinoSwitchDemoState createState() => _CupertinoSwitchDemoState();
}
class _CupertinoSwitchDemoState extends State<CupertinoSwitchDemo> {
bool _switchValue = false;
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: const Text('Switch'),
// We're specifying a back label here because the previous page is a
// Material page. CupertinoPageRoutes could auto-populate these back
// labels.
previousPageTitle: 'Cupertino',
//trailing: CupertinoDemoDocumentationButton(CupertinoSwitchDemo.routeName),
),
child: DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Semantics(
container: true,
child: Column(
children: <Widget>[
Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
value: _switchValue,
onChanged: (bool value) {
setState(() {
_switchValue = value;
});
},
),
),
Text(
"Enabled - ${_switchValue ? "On" : "Off"}"
),
],
),
),
Semantics(
container: true,
child: Column(
children: const <Widget>[
CupertinoSwitch(
value: true,
onChanged: null,
),
Text(
'Disabled - On'
),
],
),
),
Semantics(
container: true,
child: Column(
children: const <Widget>[
CupertinoSwitch(
value: false,
onChanged: null,
),
Text(
'Disabled - Off'
),
],
),
),
],
),
),
),
),
);
}
}
The accepted answer solves almost everything you need. But keep in mind that, if you make your widget smaller with Transform.scale you still have the same invisible space that the widget had before scaling it. That means: even if you scale your Switch, it still occupies the original size. A workaround for that is just to wrap it with a container and give it a desired width and height.
Note: After scaling your Switch, in order to not apply the transformation when performing hit tests, set transformHitTests to false. That way you can more easily control the area where you can tap or click.
Container(
color: Colors.red,
height: 30, //set desired REAL HEIGHT
width: 35, //set desired REAL WIDTH
child: Transform.scale(
transformHitTests: false,
scale: .5,
child: CupertinoSwitch(
value: switchValue,
onChanged: (value) {
setState(() {
switchValue = value;
});
},
activeColor: Colors.green,
),
),
),
using Transform.scale is really a good way of doing it but can cause you some trouble designing or arranging widgets on the screen.
So instead, you can wrap your CupertinoSwitch in FittedBox which is inside another Container, giving you more control over your widget.
You can copy-paste the below code,
you only need to set height and width and make your FittedBox to BoxFit.contain.
Container(
height: 200.0,
width: 200.0,
child: FittedBox(
fit: BoxFit.contain,
child: CupertinoSwitch(
value: _switchValue,
onChanged: (value) {
setState(() {
_switchValue = value;
});
},
),
),
),