I'm trying to design this view.
I already have the basic design of the cards, but i would like to know how to change the card's background color, the card's border color and add the little green square according to the width size of the current card when the user click one of them. It's important to know that only one card can be painted in green when the user clicked it.
Here is my code:
CategoryCardModel
class CategoryCardModel {
final String? categoryCardModelName;
CategoryCardModel(this.categoryCardModelName);
}
CategoryCard
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: RoundedRectangleBorder(
side: const BorderSide(
color: Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
MyHomePage
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'category_card.dart';
import 'category_card_model.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// List of models
final categoryCardModelList = <CategoryCardModel>[
CategoryCardModel("Todas"),
CategoryCardModel("Smartphones"),
CategoryCardModel("Accesorios para celular"),
CategoryCardModel("TV")
];
List<CategoryCardModel>? _categoryCardModelListOf;
@override
void initState() {
super.initState();
setState(() {
_categoryCardModelListOf = List.of(categoryCardModelList);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
wasPressed: () {
print("Hello World");
setState(() {});
},
categoryCardName:
categoryCardModel.categoryCardModelName))
.toList())));
}
}
main
import 'package:flutter/material.dart';
import 'my_home_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "Caregory Cards"),
);
}
}
CodePudding user response:
Selected is needed for Card
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool isActive;
const CategoryCard(
{super.key,
required this.categoryCardName,
this.wasPressed,
this.isActive = false});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: const StadiumBorder(),
child: Container(
decoration: BoxDecoration(
color: (isActive ? Colors.green : Colors.grey).withOpacity(.1),
borderRadius: BorderRadius.circular(24.0),
border: Border.all(
width: 2, color: isActive ? Colors.green : Colors.grey)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
Create a state variable for selected model
CategoryCardModel? activeTab;
And use
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
isActive: activeTab == categoryCardModel,
wasPressed: () {
activeTab = categoryCardModel;
setState(() {});
},
categoryCardName: categoryCardModel.categoryCardModelName))
.toList(),
),
CodePudding user response:
Update your CategoryCard class like this, you may need to change the color according to your desire :
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool isSelected;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
this.isSelected = false,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: isSelected ? Colors.green : Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: isSelected ? Colors.greenAccent : const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0),
),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
And then change your _MyHomePageState class to this :
class _MyHomePageState extends State<MyHomePage> {
// List of models
final categoryCardModelList = <CategoryCardModel>[
CategoryCardModel("Todas"),
CategoryCardModel("Smartphones"),
CategoryCardModel("Accesorios para celular"),
CategoryCardModel("TV")
];
List<CategoryCardModel>? _categoryCardModelListOf;
CategoryCardModel? _selectedCardModel;
@override
void initState() {
super.initState();
setState(() {
_categoryCardModelListOf = List.of(categoryCardModelList);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
wasPressed: () {
print("Hello World");
setState(() {
_selectedCardModel = categoryCardModel;
});
},
categoryCardName: categoryCardModel.categoryCardModelName,
isSelected: _selectedCardModel == categoryCardModel,
))
.toList(),
),
),
);
}
}
CodePudding user response:
Use above two answers for highlighting selected option...and here is what missing...
The underline below selected tab...
for that update your category card as below,
as u have mentioned underline width must be in size of tab width,
I have used ** IntrinsicWidth**
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool? isselected;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
this.isselected=false
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: IntrinsicWidth(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(children: [
Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color:isselected==true?Colors.red: Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
if(isselected==true)
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Container(
color: Colors.red[200],
height: 5,
),
),
],),
),
),
);
}
}