Widget ordering but how - flutter

Here is my code:
#override
Widget build(BuildContext context) {
return FutureBuilder<Categories>(
future: _futureCategories,
builder: (BuildContext context, AsyncSnapshot<Categories> snapshot) {
if (snapshot.hasData) {
final name = snapshot.data?.data;
return DefaultTabController(
length: 1,
child: Scaffold(
body: ListView.builder(
itemCount: name?.length,
itemBuilder: (BuildContext context, int index) {
return Text(
' ${name?[index].name}',
);
},
),
appBar: AppBar(
title: const Text('List User Example'),
bottom: TabBar(
indicatorColor: Colors.lime,
tabs: [
Text(' ${name?[0].name}'.toUpperCase()),
],
isScrollable: true,
labelColor: Colors.black,
),
),
),
);
} else if (snapshot.hasError) {
return NewsError(
errorMessage: '${snapshot.hasError}',
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
);
}
}
This code fetching categories from JSON and uses them on Tabcontroller. The problem is in this current code I cannot access index value.
I am newbie and trying to understand the widget system of Flutter. How can I use Tabcontroller to use int index value on TabController?

return Text(' ${name?[index].name}',);
change
return Text(' ${snapshot.data.name}',);

Related

Class '_JsonDocumentSnapshot' has no instance getter 'docs'. Receiver: Instance of '_JsonDocumentSnapshot' Tried calling: docs

#override
Widget build(BuildContext context) {
File? myImage;
User? user = FirebaseAuth.instance.currentUser;
return Scaffold(
appBar: AppBar(
title: const Text('Settings Page'),
centerTitle: true,
backgroundColor: Colors.blueGrey,),
body: Center(
child: FutureBuilder(
future: FirebaseFirestore.instance.collection('users').doc(user!.uid).get(),
builder: (context,AsyncSnapshot snapshot) {
if(snapshot.hasData) {
var emmi = snapshot.data;
return ListView.builder(
itemCount: emmi.docs.length,
itemBuilder: (context,index) {
return Column(
children: [
ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(80),
child: CachedNetworkImage(
imageUrl:emmi['image'],
height:120,
),
),
),
SizedBox(height: 15,),
ElevatedButton(onPressed: selectFile, child: const Text("select file")),
ElevatedButton(onPressed: uploadFile, child: const Text("upload file")),
],
);
});
}
return Center(
child: Text("error"),
);
},
),
),
);
}
}
I'm doing a settings page and i'm trying to pull current user's image from firestore and then update the user's image.
i have been searching solutions for the problem but unfortunately i try every solution i found for the similiar error but error didnt go away.I appreciate if you have any answers.
i figured it out how to pull user's image and if anyone wants to do same thing here my solution
Widget build(BuildContext context) {
final user = FirebaseAuth.instance.currentUser;
return Scaffold(
appBar: AppBar(
title: const Text('Settings Page'),
centerTitle: true,
backgroundColor: Colors.blueGrey,),
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection('users').where('uid', isEqualTo: user!.uid).snapshots(),
builder: (context,AsyncSnapshot snapshot) {
if(snapshot.hasData) {
if(snapshot.data.docs.length > 0) {
var snap = snapshot.data;
return ListView.builder(
itemCount: snap.docs.length,
itemBuilder: (context,index) {
var snaps = snapshot.data.docs[index];
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(150),
child: CachedNetworkImage(
imageUrl:snaps['image'],
placeholder: (conteext,url)=>CircularProgressIndicator(),
errorWidget: (context,url,error)=>Icon(Icons.error,),
height: 150,
),
),
);
});
}
} return Center(child: CircularProgressIndicator(),);
},
),
);
}

The body might complete normally, causing null to be returned

How can I fix this code. I think i have to put return value but to where. Any help?
Widget build(BuildContext context) {
Container(
padding: const EdgeInsets.all(
10.0,
),
child: FutureBuilder<Categories>(
future: _futureCategories,
builder: (BuildContext context, AsyncSnapshot<Categories> snapshot) {
if (snapshot.hasData) {
final name = snapshot.data?.data;
return ListView.builder(
itemCount: name!.length,
itemBuilder: (BuildContext context, int index) {
return DefaultTabController(
length: name.length,
child: Scaffold(
appBar: AppBar(
bottom: const TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
],
),
),
),
);
});
} else if (snapshot.hasError) {
return NewsError(
errorMessage: '${snapshot.hasError}',
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
Widget build underline is red. When I put under Widget line
return Container(
the error disappaer but I see only blank black screen when I execute the code
You are missing return before Container.
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(
10.0,
),
child: FutureBuilder(
future: _futureCategories(),
Does it solve ?
Instead of returning the last part in else, just return it without using else, and also return Container, like this:
Widget build(BuildContext context) {
return
Container(
padding: const EdgeInsets.all(
10.0,
),
child: FutureBuilder<Categories>(
future: _futureCategories,
builder: (BuildContext context, AsyncSnapshot<Categories> snapshot) {
if (snapshot.hasData) {
final name = snapshot.data?.data;
return ListView.builder(
itemCount: name!.length,
itemBuilder: (BuildContext context, int index) {
return DefaultTabController(
length: name.length,
child: Scaffold(
appBar: AppBar(
bottom: const TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
],
),
),
),
);
});
} else if (snapshot.hasError) {
return NewsError(
errorMessage: '${snapshot.hasError}',
);
}
return const Center(
child: CircularProgressIndicator(),
);
},

Problem wiht multiple listviews inside column / Horizontal viewport was given unbounded height

I am still new to flutter and trying to achieve a following layout of two listviews, one is displaying the top news articles, another one is showing further articles. The first one is supposed to be horizontal, the second one vertical, but both are element of one single scrollview.
Something like this here:
I am using cubit to have different states, while it loads the articles, but in combination with the SingleChildScrollView, I can never get the second, vertical listview to display, I always get
"Horizontal viewport was given unbounded height."
How can i fix this?
Also, if two widgets share the same list fetched by a bloc, is there a good way to reuse that list, instead of having two BlocBuilders?
Here is my code:
body.dart
class Body extends StatelessWidget {
Widget buildArticleWidgets(List<Article> articles) {
return ListView.builder(
scrollDirection: Axis.horizontal,
primary: false,
itemBuilder: (BuildContext context, int index) {
return ArticleWidget(articles[index]);
},
itemCount: 5,
);
}
Widget _buildSmallArticleWidgets(List<Article> articles) {
return ListView.builder(
scrollDirection: Axis.horizontal,
primary: false,
itemBuilder: (BuildContext context, int index) {
return SmallArticle(articles[index]);
},
itemCount: 5,
);
}
#override
Widget build(BuildContext context) {
final articleCubit = context.bloc<ArticlesCubit>();
articleCubit.getArticles();
return Column(
children: [
CategoriesTab(),
Expanded(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.centerLeft,
child: Text('Popular News',
style: TextStyle(
color: Colors.black,
fontSize: 18,
)),
),
SizedBox(
height: 200,
child: BlocBuilder<ArticlesCubit, ArticlesState>(
builder: (context, state) {
if (state is ArticlesInitial) {
return Container();
} else if (state is ArticlesLoading) {
return Container();
} else if (state is ArticlesLoaded) {
return buildArticleWidgets(state.articles);
}
return Container();
},
)),
Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.centerLeft,
child: Text('More News',
style: TextStyle(
color: Colors.black,
fontSize: 18,
)),
),
BlocBuilder<ArticlesCubit, ArticlesState>(
builder: (context, state) {
if (state is ArticlesInitial) {
return Container();
} else if (state is ArticlesLoading) {
return Container();
} else if (state is ArticlesLoaded) {
return _buildSmallArticleWidgets(state.articles);
}
return Container();
},
)
],
)))
],
);
}
}
home_screen.dart
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: SvgPicture.asset("assets/icons/menu.svg"),
onPressed: () {
Scaffold.of(context).openDrawer();
},
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
);
},
),
title: Text(
'NewsLab',
),
centerTitle: true,
),
drawer: Drawer(),
backgroundColor: Colors.white,
body: Body(),
);
}
}
and
main.dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "NewsLab",
theme: ThemeData(
scaffoldBackgroundColor: Colors.transparent,
primaryColor: Colors.blue,
textTheme:
Theme.of(context).textTheme.apply(bodyColor: Colors.transparent),
visualDensity: VisualDensity.adaptivePlatformDensity),
home: BlocProvider(
create: (context) => ArticlesCubit(ArticlesRepository()),
child: HomeScreen(),
),
);
}
}
In the second Column widget in your body, use Expanded widget on the children widgets.

Is it possible to drag DraggableScrollableSheet programmatically in flutter?

I want to know how to drag the DraggableScrollableSheet widget to go up or down programmatically. For example, based on a timer class.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SizedBox.expand(
child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
);
}
}

How to get the current offset of Text Span?

I'm working on a "search in a document" app . I want when I type the word it the custom scroll view automatically scrolls to the searched word.
I split my document to bunch of Text spans. how do I get the offset of only one of them. Is that even possible?
I tried but it doesn't work
with AutomaticKeepAliveClientMixin<WordViewPage> {
#override
bool get wantKeepAlive => true;
String previewedText;
ScrollController scrollController;
List<String> splitted = [''];
Color customColor = Colors.transparent;
#override
void initState() {
super.initState();
loadAsset().then((String loadedString) {
setState(() {
previewedText = loadedString;
splitter();
});
});
}
#override
Widget build(BuildContext context) {
super.build(context);
List<Widget> he = [wordFile()];
return Scaffold(
body: CustomScrollView(
controller: scrollController,
slivers: <Widget>[
SliverAppBar(
automaticallyImplyLeading: false,
title: searchBar(),
centerTitle: true,
backgroundColor: Color(0xfffc3b398),
),
SliverPadding(
padding: EdgeInsets.all(10),
sliver: SliverList(
delegate: SliverChildListDelegate(he),
),
)
],
));
}
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/test.txt');
}
You can extend your class with Search Delegate in flutter
Detail explanation and code : SearchDelegate
or you can see my code and see the RichText() widget
#override
Widget buildResults(BuildContext context){
return new FutureBuilder(
future: _getUser(query),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) => ListTile(
leading: Icon(Icons.person),
title: Text(snapshot.data[index].fName +
" " +
snapshot.data[index].lName),
title: RichText(
text: TextSpan(
text: suggestionList[index].substring(0, query.length),
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold)),
),
onTap: () {
},
),
);
}
},
);
}