I have 7 rows when I out the page and go again to the same page it show 14 rows - flutter

I have problem, when I run the code it works but when I out from the page and go back it show x2 for the rows its looping without any loop I make in my database 7 rows when I out and return to the same page it shows 14 rows but I have onlu 7 rows.
This is my code:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class my_ads extends StatefulWidget {
const my_ads({Key? key}) : super(key: key);
#override
State<my_ads> createState() => _my_adsState();
}
List list = [];
int select_item = 0;
class _my_adsState extends State<my_ads> {
#override
Future MyAds() async {
final response =
await http.get(Uri.parse('https://***.***.***.**/getData.php'));
if (response.statusCode == 200) {
var red = jsonDecode(response.body);
setState(() {
list.addAll(red);
});
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load Ads');
}
}
#override
void initState() {
super.initState();
GetData();
}
GetData() async {
await MyAds();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
margin: const EdgeInsets.only(left: 70, right: 60, top: 50),
height: 54.0,
width: 224.0,
child: Container(
decoration: BoxDecoration(
border:
Border.all(color: const Color(0xffF4AC47), width: 5),
color: const Color(0xff42A9D2),
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(40),
bottomRight: Radius.circular(40))),
child: const Center(
child: Text(
"MyAds",
style: TextStyle(
fontSize: 25,
color: Color(0xff072A52),
fontFamily: 'Cairo'),
textAlign: TextAlign.center,
),
//end logo
)),
),
const SizedBox(
height: 35,
),
Expanded(
child: ListView.builder(
itemCount: list.length,
itemBuilder: ((cts, i) {
return Column(
children: [
Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
height: 180.0,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: const Color(0xff42A9D2), width: 5),
borderRadius: BorderRadius.circular(8)),
child: Row(
children: [
const Expanded(
flex: 3,
child: Image(
image: AssetImage("assets/book.jpg"),
),
),
Expanded(
flex: 6,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"${list[i]["book_name"]}",
style: TextStyle(
fontSize: 20, color: Colors.black87),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("${list[i]["collage"]}"),
const Icon(Icons.perm_identity_rounded)
],
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("${list[i]["loc"]}"),
const Icon(Icons.store)
],
),
],
),
)
],
),
),
),
const SizedBox(height: 16),
],
);
}),
),
),
],
),
);
}
}
I tried to add this method to my PHP code $mysqli_connect-> close();
But its not working
This is my PHP code:
<?php
include("config.php");
$sql = "SELECT book_name,loc,com,spe,collage FROM ads";
$res = $connect->query($sql);
while($row = $res -> fetch_assoc()) {
$data[]=$row;
}
echo json_encode($data);
$mysqli_connect-> close();
?>

You declared list outside. It will maintain its state even when you change screens.
Either you declared it inside the state widget or replace :
list.addAll(red);
by :
list = red;

Related

i cant update itemcount

hey why is my itemcount not working i have 6 rows in my database but when i run the code it show me only one row and the other rows not showing it
this is my code:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class my_ads extends StatefulWidget {
const my_ads({Key? key}) : super(key: key);
#override
State<my_ads> createState() => _my_adsState();
}
List list = [];
int select_item = 0;
class _my_adsState extends State<my_ads> {
#override
Future ReadData() async {
var url = "https://***.***.***.**/getData.php";
var res = await http.get(Uri.parse(url));
if (res.statusCode == 200) {
var red = jsonDecode(res.body);
setState(() {
list.addAll(red);
});
print(list);
}
}
#override
void initState() {
super.initState();
GetData();
}
GetData() async {
await ReadData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: list.length,
itemBuilder: ((cts, i) {
return Container(
height: 800,
child: ListView(
children: [
Container(
margin: EdgeInsets.only(left: 70, right: 60),
height: 54.0,
width: 224.0,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Color(0xffF4AC47), width: 5),
color: Color(0xff42A9D2),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(40),
bottomRight: Radius.circular(40))),
child: new Center(
child: new Text(
"MyAds",
style: TextStyle(
fontSize: 25,
color: Color(0xff072A52),
fontFamily: 'Cairo'),
textAlign: TextAlign.center,
),
//end logo
)),
),
///start Section
Container(
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
height: 180.0,
width: 430.0,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Color(0xff42A9D2), width: 5),
borderRadius: BorderRadius.circular(8)),
child: new Container(
child: Row(
children: [
Expanded(
child: Image(
image: AssetImage("assets/book.jpg"),
)),
Container(
margin: EdgeInsets.only(
left: 110, top: 30, right: 13),
child: Column(
children: [
Text(
"test",
style: TextStyle(
fontSize: 20, color: Colors.black87),
),
SizedBox(
height: 20,
),
Row(
children: [
Text("test2"),
Icon(Icons.perm_identity_rounded)
],
),
SizedBox(
height: 5,
),
Row(
children: [
Text("}"),
Column(
children: [Icon(Icons.store)],
)
],
),
],
),
)
],
)
//end logo
)),
),
],
),
);
})));
}
}
i tried to change ListView to ListTile but the design will be detroyed becuse i need to make the same design to other pages but my problem is with itemcount its not making any changes ! please if you have any ideas with my problem give me ansewrs

Flutter: pass data from one screen to another based on a list that I fetch from API

I am building a Job Find app on flutter and I am facing some State Management problems. I have a screen where I show all of my job listings (job_list_screen.dart) and if the user press on a job the app loads this specific job with all the details(job_details_screen.dart).
enter image description here
enter image description here
As you can see, I have an apply button(the blue button) on both screens. When I press apply on the job_details_screen I send a put request on my database and it works fine. But, when I go back to my job_list_screen the button doesn't change even thought I wrapped it with a Consumer.
enter image description here
enter image description here
Here is all the code I wrote with the providers, the **screens **and the **widgets **I use.
The jobs provider:
First of all, this is how I fetch jobs from the API and I insert all my data in a List model:
`
/*
|--------------------------------------------------------------------------
| Fetch Jobs from database
|--------------------------------------------------------------------------
|
| 1. set the url for this function
| 2. GET the response from the server only if you are authenticated
| 3. Decode the
response.body: {
'listings': {
'data': (*Inside here, there are all the job list*)
}
}
| 4. For every job inside the data response
| add a new Job item in the List<Job>
| with the named variables from the current data.reposnse.job
*/
Future<List<Job>?> fetchJobs() async {
final key = await storage.read(key: 'auth');
final baseUrl = AppUrl.baseUrl;
try {
// 1.
var url = Uri.parse('$baseUrl/listings');
// 2.
var response = await http.get(
url,
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $key',
},
);
// print(key);
if (response.statusCode == 200 || response.statusCode == 201) {
// 3.
var jsonResponse = jsonDecode(response.body)['listings']['data'];
_jobs = [];
// 4.
for (var j in jsonResponse) {
Job job = Job(
id: j['id'],
title: j['title'],
employmentType: j['employmentType'],
major: j['major'],
city: j['city'],
companyName: j['companyName'],
experience: j['experience'],
date: j['date'],
views: j['views'],
description: j['description'],
benefits: j['benefits'],
requirements: j['requirements'],
hasApplied: j['hasApplied'],
hasViewed: j['hasViewed'],
);
_jobs.add(job);
notifyListeners();
}
notifyListeners();
return _jobs;
} else {
throw Exception('Problem loading jobs');
}
} catch (e) {
print(e);
}
}
`
This is the function that I call when the user presses the apply button:
`
/*
|--------------------------------------------------------------------------
| Apply for a job
|--------------------------------------------------------------------------
*/
Future<void> applyJob(String id) async {
final key = await storage.read(key: 'auth');
final baseUrl = AppUrl.baseUrl;
try {
var url = Uri.parse('$baseUrl/listings/$id/apply');
var response = await http.put(
url,
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $key',
},
);
if (response.statusCode == 200 || response.statusCode == 201) {
print(jsonDecode(response.body));
_hasApplied = jsonDecode(response.body)['hasApplied'];
notifyListeners();
} else {
print(jsonDecode(response.body));
notifyListeners();
}
} catch (e) {
print(e);
}
notifyListeners();
}
`
The job_card widget:
`
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:final_try/screens/job_details_screen.dart';
import '../models/job.dart';
import '../providers/jobs.dart';
import '../styles/colors.dart';
class JobCardBig extends StatefulWidget {
static const routeName = '/job-card-big';
#override
State<JobCardBig> createState() => _JobCardBigState();
}
class _JobCardBigState extends State<JobCardBig> {
#override
Widget build(BuildContext context) {
final job = Provider.of<Job>(context, listen: true);
return Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.only(bottom: 10),
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: lightgrey, width: 1),
borderRadius: BorderRadius.circular(5.0),
boxShadow: [
BoxShadow(
color: lightgrey.withOpacity(.5),
spreadRadius: 1,
blurRadius: 2,
offset: Offset(0, 1), // changes position of shadow
),
],
color: white,
),
child: Column(children: [
Container(
child: Row(
children: [
Container(
height: 50,
width: 50,
alignment: Alignment.center,
decoration:
BoxDecoration(shape: BoxShape.circle, color: lightgrey),
),
SizedBox(
width: 10,
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Container(
height: 70,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
job.title.toString(),
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
job.companyName.toString(),
style: TextStyle(
fontSize: 14,
color: lightgrey,
),
),
],
),
),
),
Container(
height: 70,
width: 50,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.remove_red_eye,
size: 14,
color: darkgrey,
),
SizedBox(
width: 5,
),
Text(
job.views == null
? job.views = '0'
: job.views.toString(),
style: TextStyle(
fontSize: 14,
color: darkgrey,
),
),
],
),
],
),
),
],
),
),
],
)),
SizedBox(
height: 5,
),
Divider(
thickness: 1,
),
SizedBox(
height: 5,
),
Container(
height: 80,
alignment: Alignment.bottomLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'Είδος Απασχόλησης:',
),
SizedBox(
width: 5,
),
Text(
Provider.of<Jobs>(context, listen: false)
.jobTypeFormat(job.employmentType.toString()),
style: TextStyle(color: lightgrey),
),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Προϋπηρεσία:'),
SizedBox(
width: 5,
),
Flexible(
child: job.experience == null
? Text(
'Δεν απαιτείται',
style: TextStyle(color: lightgrey),
)
: job.experience! > 1
? Text(
'${job.experience.toString()} χρόνια',
style: TextStyle(color: lightgrey),
)
: Text(
'${job.experience.toString()} χρόνο',
style: TextStyle(color: lightgrey),
),
),
],
),
Row(
children: [
Text('Τοποθεσία:'),
SizedBox(
width: 5,
),
Text(
job.city.toString(),
style: TextStyle(color: lightgrey),
),
],
),
Row(
children: [
Text('Δημοσιεύθηκε:'),
SizedBox(
width: 5,
),
Text(
Provider.of<Jobs>(context, listen: false)
.dateFormat(job.date),
// job.date.toString(),
style: TextStyle(color: lightgrey),
),
],
),
],
),
),
Container(
margin: EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
border: Border.all(color: darkgrey, width: 1),
borderRadius: BorderRadius.circular(5.0),
color: darkgrey,
),
child: Text(
'Περισσότερα',
style: TextStyle(color: white),
),
),
onTap: () {
Navigator.of(context)
.pushNamed(JobDetailsScreen.routeName, arguments: job.id)
.then((_) {
// Provider.of<Jobs>(context, listen: false).fetchJobs();
});
},
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: job.hasApplied == 1
? Color.fromARGB(255, 196, 76, 68)
: buttonColor,
),
child: Consumer<Job>(
builder: (context, job, child) {
return Text(
job.hasApplied == 1 ? 'Δεν ενδιαφέρομαι' : 'Αίτηση',
style: TextStyle(
color: white,
),
);
},
),
),
],
),
),
]),
);
}
}
`
The job_list_screen:
Here I load all my job_card widgets with ListView.builder
`
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import '../styles/colors.dart';
import '../providers/jobs.dart';
import '../widgets/header_screen.dart';
import '../widgets/job_card_big.dart';
class JobListScreen extends StatefulWidget {
static const routeName = '/job-list-screen';
const JobListScreen({super.key});
#override
State<JobListScreen> createState() => _JobListScreenState();
}
class _JobListScreenState extends State<JobListScreen> {
final controller = ScrollController();
bool _firstLoading = true;
var _isLoading = false;
int page = 1;
final _formKey = GlobalKey<FormState>();
String? _searchText;
bool _isFiltered = false;
#override
void initState() {
controller.addListener(() {
if (controller.position.maxScrollExtent == controller.offset) {
fetch();
}
});
super.initState();
}
Future fetch() async {
if (!_isFiltered) {
setState(() {
_isLoading = true;
page++;
Provider.of<Jobs>(context, listen: false)
.fetchMore(page)
.then((_) => _isLoading = false);
});
}
}
#override
void didChangeDependencies() {
if (_firstLoading) {
Provider.of<Jobs>(context, listen: true).fetchJobs().then((_) {
setState(() {
_firstLoading = false;
});
});
}
super.didChangeDependencies();
}
void searchJob() {
if(_searchText == null || _searchText == ''){
setState(() {
_isFiltered = false;
});
}
else setState(() {
Provider.of<Jobs>(context, listen: false).filterJobs(_searchText!);
_isFiltered = true;
});
}
#override
Widget build(BuildContext context) {
final jobsData = Provider.of<Jobs>(context, listen: true);
var jobsList = jobsData.jobs;
var filteredList = jobsData.filteredJobs;
// var jobsListFiltered = jobsData.filteredJobs;
return Scaffold(
body: Stack(
children: [
Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.only(
top: 20,
right: 20,
left: 20,
),
child: Column(
children: [
HeaderScreen(title: 'Αγγελίες'),
Container(
child: Form(
key: _formKey,
child: Row(
children: [
Expanded(
child: Container(
child: TextFormField(
decoration: InputDecoration(
hintText: 'Enter some text',
),
onSaved: (value) {
_searchText = value;
},
),
),
),
Container(
margin: EdgeInsets.only(top: 10, bottom: 5),
height: 40,
width: 40,
child: ElevatedButton(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all<Color>(white),
backgroundColor: MaterialStateProperty.all<Color>(
primaryColor),
),
child: Container(
child: Icon(Icons.search),
),
onPressed: () {
_formKey.currentState?.save();
searchJob();
},
),
),
],
),
),
),
SizedBox(
height: 10,
),
Divider(
thickness: 1,
),
SizedBox(
height: 10,
),
Expanded(
child: !_isFiltered
? Container(
child: !_firstLoading
? ListView.builder(
controller: controller,
itemCount: jobsList.length,
itemBuilder: (ctx, i) =>
ChangeNotifierProvider.value(
value: jobsList[i],
child: Column(
children: [
JobCardBig(),
],
),
),
)
: Center(
child: CircularProgressIndicator(),
),
)
: Container(
child: !_firstLoading
? ListView.builder(
controller: controller,
itemCount: filteredList.length,
itemBuilder: (ctx, i) =>
ChangeNotifierProvider.value(
value: filteredList[i],
child: Column(
children: [
JobCardBig(),
],
),
),
)
: Center(
child: CircularProgressIndicator(),
),
),
),
],
),
),
Positioned(
child: _isLoading
? Container(
width: double.infinity,
height: MediaQuery.of(context).size.height,
color: Color.fromARGB(52, 0, 0, 0),
child: Center(
child: CircularProgressIndicator(),
),
)
: Container(),
),
],
),
);
}
}
`
I tried to load my fetchJobs() function when the user exits the job_details_screen but even though it works, it is not the right solution. The reason why I say that this is not the right way, is because of this possible scenario:
If the user scrolls down a lot, and the app load 60 jobs, then if he presses on job 60, and he exit the job_details_screen, the app will load the first 15 jobs and the user will have to scroll down again. And that's not the user experience I want to provide.
I am searching for a solution that will update only the apply button and it will not need to recreate the whole list. Plus, with this solution the user will go back to the same scroll point he was when he entered the job_details_screen.
I hope I explained my problem properly. This is the first time I upload a question here and I would also like to mention that this is my first project on flutter so don't judge my code too harshly.
Thanks in advance!!

How to hide the tab name by clicking seach in flutter

I'm still new in flutter, does anyone know how to make the search in the tab card like picture below:
I try to figure it out how to solve this problem but still be like this:
Here is My code that I try to solve, I'm using the custom card, the custom dialog :
class TabbedCard extends StatefulWidget {
final List<Tab> tabs;
final List<Widget> children;
final bool showDeleteBtn;
final bool showPrimaryBtn;
const TabbedCard(
{Key? key,
required this.tabs,
required this.children,
this.showDeleteBtn = false,
this.showPrimaryBtn = true})
: super(key: key);
#override
State<TabbedCard> createState() => _TabbedCardState();
}
class _TabbedCardState extends State<TabbedCard> with TickerProviderStateMixin {
#override
Widget build(BuildContext context) {
double _scrHeight = MediaQuery.of(context).size.height - 150;
// String searchText = "";
TextEditingController textController = new TextEditingController();
TabController _controller =
TabController(length: widget.tabs.length, vsync: this);
TabBar _tabBar = new TabBar(
isScrollable: true,
labelColor: kPrimaryColor,
unselectedLabelColor: kTextGray,
controller: _controller,
tabs: widget.tabs,
);
return Container(
constraints: BoxConstraints(minHeight: _scrHeight),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.symmetric(
vertical: 1,
horizontal: 1,
),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.white.withOpacity(0.5),
spreadRadius: -4,
blurRadius: 35,
offset: const Offset(0, 9), // changes position of shadow
),
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Align(
alignment: Alignment.topLeft,
child: Row(
children: [
AnimSearchBar(
width: 400,
textController: textController,
onSuffixTap: (value) {
setState(() {});
},
),
const SizedBox(width: 10),
_tabBar,
const SizedBox(width: 10),
],
)),
const SizedBox(height: 10),
Container(
height: 440,
child: TabBarView(
controller: _controller,
children: widget.children,
),
),
],
),
),
const SizedBox(height: 10),
],
),
),
);
}
}
Really appreciate if anyone can help me with this problem ^^
You can try this:
first create bool showSearchView = false, then create two widget like this:
_tabView() {
return Row(
children: [
Container(
color: Colors.red,
width: 100,
height: 40,
),
Container(
margin: EdgeInsets.symmetric(horizontal: 16),
color: Colors.red,
width: 100,
height: 40,
),
Container(
color: Colors.red,
width: 100,
height: 40,
),
],
);
}
and
_searchView() {
return TextField();
}
then, use it like this:
Row(
children: [
InkWell(
onTap: () {
setState(() {
showSearchView = !showSearchView;
});
},
child: Icon(showSearchView ? Icons.close : Icons.search),
),
Expanded(
child: showSearchView ? _searchView() : _tabView(),
),
],
),

How to fetch data (Text) from Website in Flutter / dart?

So, I'm pretty new on Flutter (just about a week) and dart but I hope this Question is not toooooo stupid:
I'm trying to create an App for an existing Website (a forum). I dont want to use the flutter WebView, because I want to create an comepletly new Interface (The Website is not optimized for mobile View, that's why I'm builing this App).
The (german) Forum:
https://www.porsche-914.com/forum
I want to fetch the single forum topics as well as the posts itself including username, title and date and then map the text to a custom widget to display it. The Widget Part is no problem, it's already done but I cant figure out how to fetch that data from the website and how to store it.
I don't know, hope you can help me...
Thanks a lot for the taken time.
How the mapping should work:
fetched[index].title, fetched[index].text
Center(
child: NeumorphismPost(
title: fetched[index].title,
titleColor: Theme.of(context).cardColor,
textColor: Theme.of(context).cardColor,
text: fetched[index].text,
width: 370,
onTap: () {
_popupPage(context,
title: fetched[index].title,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Text(
fetched[index].text,
style: TextStyle(
color: Theme.of(context).cardColor,
fontSize: 18),
),
),
);
},
),
),
This is my custom Widget:
import 'package:flutter/material.dart';
class NeumorphismPost extends StatefulWidget {
final double width;
final double height;
final double borderRadius;
final String title;
final String text;
final Color titleColor;
final Color textColor;
final double titleSize;
final double textSize;
final Function onTap;
NeumorphismPost({
this.width = 185,
this.height = 185,
this.title = "Title",
this.text = "",
this.borderRadius = 20,
this.titleColor = const Color(0xFF424242),
this.textColor = const Color(0xFF424242),
this.titleSize = 22,
this.textSize = 18,
required this.onTap,
});
#override
State<NeumorphismPost> createState() => _NeumorphismPostState();
}
class _NeumorphismPostState extends State<NeumorphismPost> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
direction: Axis.vertical,
children: [
SingleChildScrollView(
child: SizedBox(
height: widget.height,
width: widget.width,
child: GestureDetector(
onTap: () {},
child: Scaffold(
backgroundColor: Colors.transparent,
body: SizedBox(
height: widget.height,
width: widget.width,
child: Center(
child: Container(
height: widget.height,
width: widget.width,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius:
BorderRadius.circular(widget.borderRadius),
boxShadow: [
BoxShadow(
color: Theme.of(context).hintColor,
offset: const Offset(5, 5),
blurRadius: 15,
spreadRadius: 1,
),
BoxShadow(
color: Theme.of(context).backgroundColor,
offset: Offset(-5, -5),
blurRadius: 15,
spreadRadius: 1,
)
],
),
child: Wrap(
direction: Axis.horizontal,
children: [
SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
Wrap(
direction: Axis.horizontal,
children: [
SizedBox(
height: widget.height / 3,
child: Wrap(
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets
.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.title,
textAlign:
TextAlign.center,
overflow:
TextOverflow.fade,
style: TextStyle(
fontSize:
widget.titleSize,
fontWeight:
FontWeight.bold,
color:
widget.titleColor,
),
),
),
],
),
],
),
),
],
),
Wrap(
direction: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
widget.onTap();
},
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 5),
child: SizedBox(
height: widget.height / 1.38,
child: Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: widget.textSize,
fontWeight:
FontWeight.normal,
color: widget.textColor,
),
),
),
),
),
),
],
),
],
),
),
),
],
),
),
),
),
),
),
),
),
],
),
);
}
}
From my point of view, you want to create a scraper. I checked the target website (https://www.porsche-914.com/forum), it can be scraped without any special technique (they don't have many Ajax calls (you may test by using Postman)). So it is a possible task. My suggestion flow is:
Load the raw HTML using any technique (http, dio, inappwebview ...)
Parse it using BeautifulSoup (https://pub.dev/packages/beautiful_soup_dart) (or any parser; it is just my favorite parser.)
Map it to your existing model.
Here is some example code. Hope it helps:
import 'package:http/http.dart' as http;
import 'package:beautiful_soup_dart/beautiful_soup.dart';
class TestParse {
excuteSample() async {
var url = Uri.parse('https://www.porsche-914.com/forum');
var response = await http.get(url);
BeautifulSoup bs = BeautifulSoup(response.body);
final allHeaderName = bs.findAll('td', attrs: {'class': 'oben'});
allHeaderName.forEach((element) {
print('the header: ${element.text}');
});
}
}
Here is the result:
The final result you need is a long story and long code. Hope this will give you a starting point.
UPDATE: I added the full demo code, using your requested code:
import 'package:beautiful_soup_dart/beautiful_soup.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(const MaterialApp(home: MyApp()));
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final testparse = TestParse();
List<String> yourModelPleaseReplaceThis = [];
#override
void initState() {
super.initState();
excuteRequestAndParse();
}
excuteRequestAndParse() async {
final result =
await testparse.excuteSample(); //[1] i guess you missing this await
setState(() {
yourModelPleaseReplaceThis = result;
});
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
return Center(
child: NeumorphismPost(
title: yourModelPleaseReplaceThis[index],
titleColor: Theme.of(context).cardColor,
textColor: Theme.of(context).cardColor,
text: yourModelPleaseReplaceThis[index],
width: 370,
onTap: () {
//THIS CODE BELOW IS YOUR CODE....
},
),
);
},
itemCount: yourModelPleaseReplaceThis.length,
);
}
}
// BELOW IS TESTING CODE....
class TestParse {
Future<List<String>> excuteSample() async {
var url = Uri.parse('https://www.porsche-914.com/forum');
var response = await http.get(url);
BeautifulSoup bs = BeautifulSoup(response.body);
final allHeaderName = bs.findAll('td', attrs: {'class': 'oben'});
allHeaderName.forEach((element) {
print('the header: ${element.text}');
});
return Future.value(allHeaderName.map((e) => e.text).toList());
}
}
class NeumorphismPost extends StatefulWidget {
final double width;
final double height;
final double borderRadius;
final String title;
final String text;
final Color titleColor;
final Color textColor;
final double titleSize;
final double textSize;
final Function onTap;
NeumorphismPost({
this.width = 185,
this.height = 185,
this.title = "Title",
this.text = "",
this.borderRadius = 20,
this.titleColor = const Color(0xFF424242),
this.textColor = const Color(0xFF424242),
this.titleSize = 22,
this.textSize = 18,
required this.onTap,
});
#override
State<NeumorphismPost> createState() => _NeumorphismPostState();
}
class _NeumorphismPostState extends State<NeumorphismPost> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
direction: Axis.vertical,
children: [
SingleChildScrollView(
child: SizedBox(
height: widget.height,
width: widget.width,
child: GestureDetector(
onTap: () {},
child: Scaffold(
backgroundColor: Colors.transparent,
body: SizedBox(
height: widget.height,
width: widget.width,
child: Center(
child: Container(
height: widget.height,
width: widget.width,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius:
BorderRadius.circular(widget.borderRadius),
boxShadow: [
BoxShadow(
color: Theme.of(context).hintColor,
offset: const Offset(5, 5),
blurRadius: 15,
spreadRadius: 1,
),
BoxShadow(
color: Theme.of(context).backgroundColor,
offset: Offset(-5, -5),
blurRadius: 15,
spreadRadius: 1,
)
],
),
child: Wrap(
direction: Axis.horizontal,
children: [
SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
Wrap(
direction: Axis.horizontal,
children: [
SizedBox(
height: widget.height / 3,
child: Wrap(
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets
.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.title,
textAlign:
TextAlign.center,
overflow:
TextOverflow.fade,
style: TextStyle(
fontSize:
widget.titleSize,
fontWeight:
FontWeight.bold,
color:
widget.titleColor,
),
),
),
],
),
],
),
),
],
),
Wrap(
direction: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
widget.onTap();
},
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 5),
child: SizedBox(
height: widget.height / 1.38,
child: Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 15,
vertical: 15),
child: Text(
widget.text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: widget.textSize,
fontWeight:
FontWeight.normal,
color: widget.textColor,
),
),
),
),
),
),
],
),
],
),
),
),
],
),
),
),
),
),
),
),
),
],
),
);
}
}
This is the result:
Please note:
This list I created is for sample, so it is just a list of Strings. You should create a complete Model.

How can I search the button I made in ListView with Search Bar?

I created a button shape called 'VocabularyWordsButton' and when I try it under a ListView it works just fine. But when I make 100 buttons under ListView, I want to find them via Search Bar. But I don't know how to do it somehow.
What I want to do: I want to distinguish the buttons by filtering the word 'englishWord' among the buttons listed below. When I enter the word in 'englishWord' in Search Bar, I want the buttons containing that word to be filtered.
If I do something like below, only the texts inside are listed, not the button I made.
VocabularyWordsButton.dart
import 'package:being_moroccan/AdHelper.dart';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:sizer/sizer.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:easy_localization/easy_localization.dart';
class VocabularyWordsButton extends StatefulWidget {
VocabularyWordsButton(
{required this.englishWord,
required this.trasncribedWord,
required this.arabicWord,
required this.sound});
final String englishWord;
final String trasncribedWord;
final String arabicWord;
final String sound;
#override
_VocabularyWordsButtonState createState() => _VocabularyWordsButtonState();
}
class _VocabularyWordsButtonState extends State<VocabularyWordsButton> {
AdHelper adHelper = AdHelper();
#override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
adHelper.myLargeBanner.load();
}
bool _canShowButton = true;
void hideWidget() {
setState(() {
_canShowButton = !_canShowButton;
});
}
final AudioCache _audioCache = AudioCache(
prefix: 'audio/',
fixedPlayer: AudioPlayer()..setReleaseMode(ReleaseMode.STOP),
);
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: !_canShowButton
? Column(
children: [
Container(
height: 195.h / 6,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Container(
height: 100,
child: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20))),
child: Center(
child: TextButton(
onPressed: () {
hideWidget();
},
child: Container(
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
widget.englishWord,
style: TextStyle(
fontSize: 30.sp / 2,
color: Colors.white),
),
),
),
),
),
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.transparent),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(20)),
),
),
),
onPressed: () {
print('cal');
_audioCache.play('${widget.sound}.mp3');
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(2.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'TRANSCRIBED'.tr(),
style: TextStyle(
fontSize: 25.sp / 2,
),
),
Container(
width:
MediaQuery.of(context).size.width /
2,
height: 60.h / 7,
child: Center(
child: Text(
widget.trasncribedWord,
style: TextStyle(
fontSize: 25.sp / 2,
),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'ARABIC'.tr(),
style: TextStyle(
fontSize: 25.sp / 2,
),
),
Container(
width:
MediaQuery.of(context).size.width /
2,
height: 60.h / 7,
child: Center(
child: Text(
widget.arabicWord,
style: TextStyle(
fontSize: 25.sp / 2,
),
),
),
),
],
),
),
],
),
),
),
],
),
),
),
Container(
height: 100,
child: AdWidget(ad: adHelper.myLargeBanner),
),
],
)
: Container(
width: MediaQuery.of(context).size.width / 2,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: Center(
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.transparent),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
),
onPressed: () {
hideWidget();
},
child: Container(
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
widget.englishWord,
style:
TextStyle(fontSize: 30.sp / 2, color: Colors.white),
),
),
),
),
),
),
);
}
}
DictionaryScreen.dart
import 'package:sizer/sizer.dart';
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'VocabularyWords/VocabularyWordsButton.dart';
class DictionaryScreen extends StatefulWidget {
static const String id = 'Dictionary_Screen';
const DictionaryScreen({Key? key}) : super(key: key);
#override
_DictionaryScreenState createState() => _DictionaryScreenState();
}
class _DictionaryScreenState extends State<DictionaryScreen> {
TextEditingController editingController = TextEditingController();
// final duplicateItems = List<String>.generate(10000, (i) => "Item $i");
// var items = List<String>();
List<VocabularyWordsButton> words = [
VocabularyWordsButton(
englishWord: 'To pray'.tr(),
trasncribedWord: 'Sella',
arabicWord: 'صْلّى',
sound: 'Sella',
),
VocabularyWordsButton(
englishWord: 'To prefer'.tr(),
trasncribedWord: 'Feddel',
arabicWord: 'فْضّلْ',
sound: 'Feddel',
)
];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
setState(() {});
},
controller: editingController,
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)))),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: words.length,
itemBuilder: (context, index) {
if (editingController.text.isEmpty) {
return ListTile(
title: Text('${words[index].englishWord} '),
);
} else if (words[index]
.englishWord
.toLowerCase()
.contains(editingController.text)) {
return ListTile(
title: Text('${words[index].englishWord} '),
);
} else {
return Container();
}
}),
),
],
),
),
);
}
}