I am trying to make a list view of songs using audioquery but the list is not showing I ran it with no-null safety, this is my tracks.dart file whats wrong with my code?
I am getting only the appbar in the output
import 'package:flutter/material.dart';
import 'package:flutter_audio_query/flutter_audio_query.dart';
import 'dart:io';
class Tracks extends StatefulWidget {
_TracksState createState() => _TracksState();
}
class _TracksState extends State<Tracks> {
final FlutterAudioQuery audioQuery = FlutterAudioQuery();
List<SongInfo> songs = [];
void initState() {
super.initState();
getTracks();
}
void getTracks() async {
songs = await audioQuery.getSongs();
setState(() {
songs = songs;
});
}
Widget build(context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
leading: Icon(Icons.music_note, color: Colors.black),
title: Text('Music App', style: TextStyle(color: Colors.black)),
),
body: ListView.separated(
separatorBuilder: (context, index) => Divider(),
itemCount: songs.length,
itemBuilder: (context, index) => ListTile(
leading: CircleAvatar(
backgroundImage: songs[index].albumArtwork == null
? AssetImage('assets/img.jpg') as ImageProvider
: FileImage(File(songs[index].albumArtwork)),
),
title: Text(songs[index].title),
subtitle: Text(songs[index].artist),
onTap: () {},
),
),
);
}
}
One of the solutions for your problem would be using using only the songs = await audioQuery.getSongs(); line in the initState() function.
But if you want to keep using your getTracks() function, I think you have to declare the songs variable (at the first line of the method) and then use the 'this' keyword in the setState() method (to specify the global songs List reference being initialized).
Related
I am a complete newbie of flutter.
I want to download a simple carparkList from Firestore and put it into a list (or a map??). It appears that the dataset has been successfully downloaded (proved by actually seeing the data from the print(cp)).
But synatx error (a red undeline) apppears at the "[" of both lines:
title: Text(widget.carparkList[index].data().['name']),
subtitle: Text(widget.carparkList[index].data().['district']),
Pls help point out how to correct the syntax error for the following code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class DownloadDataScreen extends StatefulWidget {
List<DocumentSnapshot> carparkList = []; //List for storing carparks
#override
_DownloadDataScreen createState() => _DownloadDataScreen();
}
class _DownloadDataScreen extends State<DownloadDataScreen> {
#override
void initState() {
readFromFirebase();
super.initState();
}
void readFromFirebase() async {
await FirebaseFirestore.instance
.collection('carpark')
.get()
.then((QuerySnapshot snapshot) {
snapshot.docs.forEach((DocumentSnapshot cp) {
widget.carparkList.add(cp);
// the following 'print' proves that data are successfully downloaded from firestore.
print('printing cp');
print(cp.data().runtimeType);
print(cp.data());
});
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(
'Car Park',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
centerTitle: true,
),
body: Column(
children: [
ListView.builder(
itemCount: widget.carparkList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(widget.carparkList[index].data().['name']),
subtitle: Text(widget.carparkList[index].data().['district']),
);
},
),
],
),
);
}
}
Change them to this:
title: Text(widget.carparkList[index].get('name')),
subtitle: Text(widget.carparkList[index].get('district')),
I need to grab a list of all messages in the database where the level is less than or equal to the user's current level. To do this I am attempting to use a nested streambuilder. First one pulls the user info, then I use the user level to make the second query. My problem is I get an error.
Null check operator used on null value
I do not understand this error. I checked firestore to see that there is data in the collection, and I also made sure to put the proper rules in place. I've tried several variations of this code and this is the only one so far that at least doesn't give me an error in the emulator. My emulator shows the appbar and the body is blank.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../screens/welcome_screen.dart';
class MessagesScreen extends StatefulWidget {
static const String id = 'messages_screen';
#override
_MessagesScreenState createState() => _MessagesScreenState();
}
class _MessagesScreenState extends State<MessagesScreen> {
final _firestore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
User loggedInUser;
int _userCurrentLevel;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() {
try {
final user = _auth.currentUser;
if (user != null) {
loggedInUser = user;
}
} catch (e) {
print(e);
}
}
getMessages(AsyncSnapshot<QuerySnapshot> snapshot2) {
return snapshot2.data.docs
.map((doc) => new ListTile(title: Text(doc['from']), subtitle: Text(doc['text'])))
.toList();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Darker Slate'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.chat),
tooltip: 'Messages',
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.exit_to_app),
tooltip: 'Log Out',
onPressed: () {
_auth.signOut();
Navigator.pushNamed(context, WelcomeScreen.id);
},
),
],
),
body: StreamBuilder<DocumentSnapshot>(
stream: _firestore.collection('users')
.doc(_auth.currentUser.uid)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red[900],
),
);
}
_userCurrentLevel = snapshot.data['userlevel'];
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages')
.where('level', isLessThanOrEqualTo: _userCurrentLevel).snapshots(),
builder: (context, snapshot2) {
if (!snapshot2.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red[900],
),
);
}
return Column(
children: [
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot2.data.docs.length,
itemBuilder: (_, index) {
return new ListView(children: getMessages(snapshot2));
}),
],
);
}
);
}),
);
}
}
I wan't to add a loading screen t my flutter app when it's processing the data using the asyn but i am limited and don't know where to start from and this is my database.dart file which handles the firestore connections and configurations. Help me where can i add a function inside the DatabaseService which will be showing the loading screen and then after the async is done it displays the 'homepage' text.
Database.dart:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:kopala_dictionary/models/words.dart';
class DatabaseService {
//cloud databse colection for words
final CollectionReference wordsCollection =
Firestore.instance.collection('words');
Future insertData(String word, String english_translation,
String bemba_translation, String user_id, DateTime date_posted) async {
return await wordsCollection.document().setData({
'word': word,
'english_translation': english_translation,
'bemba_translation': bemba_translation,
'user_id': user_id,
'date_posted': date_posted
});
}
//words list from snappshots
List<Words> _wordsFromSnapShots(QuerySnapshot snapshot) {
return snapshot.documents.map((doc) {
return Words(
word: doc.data['word'],
englishTranslation: doc.data['english_translation'],
bembaTranslation: doc.data['bemba_translation'],
);
}).toList();
}
//Stream snapshots
Stream<List<Words>> get words {
// This forces an ordering on the documents in the collection
return wordsCollection.orderBy('word').snapshots().map(_wordsFromSnapShots);
}
}
My homepage
logged_home.dart:
import 'package:flutter/material.dart';
import 'package:kopala_dictionary/main/about.dart';
import 'package:kopala_dictionary/models/words.dart';
import 'package:kopala_dictionary/screens/author/profile_page.dart';
import 'package:kopala_dictionary/screens/home/words_list.dart';
import 'package:kopala_dictionary/screens/wrapper.dart';
import 'package:kopala_dictionary/services/auth.dart';
import 'package:kopala_dictionary/services/database.dart';
import 'package:kopala_dictionary/shared/app_bar.dart';
import 'package:provider/provider.dart';
class LoggedInUserHome extends StatelessWidget {
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
return StreamProvider<List<Words>>.value(
value: DatabaseService().words,
child: Scaffold(
backgroundColor: Colors.green[10],
appBar: LoggedBar(),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text(
'Kopalationary Menu',
style: TextStyle(color: Colors.white),
),
decoration: BoxDecoration(
color: Colors.green[800],
),
),
ListTile(
title: Text('Home'),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Wrapper()));
},
),
ListTile(
title: Text(
'My profile',
),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => ProfilePage()));
},
),
ListTile(
title: Text('Logout'),
onTap: () async {
dynamic result = await _auth.logoutUser();
},
),
ListTile(
title: Text(
'About',
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => About()),
);
},
),
],
),
),
body: WordsList(),
),
);
}
}
You probably need a StreamBuilder for this. An example might look something like this. You pass a stream into the builder and handle whatever the state of the stream is inside of the builder by looking at the snapshot. If it has an data, you show the content for the data otherwise you show a loading screen or an error screen if there was an error while retrieving the data.
class MyScreen extends StatefulWidget {
#override
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
Stream<List<Words>> wordStream;
#override
void initState() {
super.initState();
wordStream = DatabaseService().words;
}
#override
Widget build(BuildContext context) {
return StreamBuilder<List<Words>>(
stream: wordStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return ErrorWidget();
} else if (snapshot.hasData) {
return ContentWidget(snapshot.data);
} else {
return LoadingWidget();
}
},
);
}
}
There are some other connectionStates on the snapshot, that you might want to handle, but this handles the standard cases.
I am trying to build a list where each item contains an icon on the far side. However, when I try and access the list when more than one item is added I get the error:
Invalid value: Only valid value is 0: 1
Here is the code:
import 'package:flutter/material.dart';
import './images.dart';
class LikedList extends StatefulWidget {
#override
_LikedListState createState() => _LikedListState();
}
class _LikedListState extends State<LikedList> {
static List<bool> _likes = List.filled(ImagesState.likes.length,true);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Liked List'),
),
body: ListView.separated(
separatorBuilder: (context, index) => Divider(),
itemCount: ImagesState.likes.length,
itemBuilder: (context, index) {
final item = ImagesState.likes[index];
return ListTile(
title: Text(item),
trailing: IconButton(
icon: _likes[index]
? Icon(
Icons.favorite_border,
color: Colors.grey,
)
: Icon(
Icons.favorite,
color: Colors.red,
),
onPressed: () {
setState(() {
print(_likes);
_likes[index] = !_likes[index];
print(_likes);
});
},
),
onLongPress: () {
setState(() {
print(ImagesState.likes[index]);
ImagesState.likes.removeAt(index);
});
},
);
},
),
);
}
}
Does anyone know why this is happening?
Similar suggestions point to itemCount not being set, but I am using that.
You appear to be creating a fixed length list with the statement:
static List<bool> _likes = List.filled(ImagesState.likes.length,true);
That will create a filled fixed length list of length .likes.length, containing values 'true'.
You need to add a third parameter 'growable: true' in your method call to be able to add to the list.
I am Flutter beginner. I'm trying to make News Feeder App.
I would like to Favorite Function Button on each List on my App.
But I don't know how to make it.
I tried to show favorite icons on each list. But It doesn't work.
I would like to select favorite button multiply.
Could you help it?
Here is the codes.
This code is that to show the news title and thumbnail as list.
I would like to put favorite Icon and work "active and non active function".
newslist_screen.dart
import 'package:flutter/material.dart';
import 'package:technewsfeeder/webview_screen.dart';
import 'package:technewsfeeder/fetch_newsdata.dart';
class NewsListScreen extends StatefulWidget {
// "static const" is always as this value.
static const String id = 'newslist_screen';
#override
_NewsListScreenState createState() => _NewsListScreenState();
}
class _NewsListScreenState extends State<NewsListScreen> {
Future<List<NewsDataList>> _savedList;
// Animation controller init method
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Tech News App'),
),
body: FutureBuilder(
future: fetchNewsData(),
builder: (context, snapshot) {
return snapshot.data != null
? listViewWidget(snapshot.data)
: Center(child: CircularProgressIndicator());
}),
);
}
Widget listViewWidget(List<NewsDataList> article) {
return Container(
child: ListView.builder(
itemCount: 20,
padding: const EdgeInsets.all(2.0),
itemBuilder: (context, position) {
return Card(
child: ListTile(
title: Text(
'${article[position].title}',
style: TextStyle(
fontSize: 18.0,
color: Colors.black,
fontWeight: FontWeight.bold),
),
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
child: article[position].urlToImage == null
? Image(
image: AssetImage(''),
)
: Image.network('${article[position].urlToImage}'),
height: 100.0,
width: 100.0,
),
),
// *******
// I would like to put Favorite function here.
// *****
onTap: () {
print(article[position].url);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WebViewScreen(url: article[position].url)),
);
},
),
);
}),
);
}
}
}
This is to get Json data from URL.
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
class NewsDataList {
final String title;
final String url;
final String urlToImage;
NewsDataList({this.title, this.url, this.urlToImage});
factory NewsDataList.fromJson(Map<String, dynamic> json) {
return NewsDataList(
title: json['title'] as String,
url: json['url'] as String,
urlToImage: json['urlToImage'] as String,
);
}
}
Future<List<NewsDataList>> fetchNewsData() async {
List<NewsDataList> list;
String url = "http://newsapi.org/v2/top-headlines?country=jp&category=technology&apiKey=f289d460a5f94d4087d54cd187becceb";
var res = await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
print(res.body);
if(res.statusCode == 200){
var data = json.decode(res.body);
var rest = data["articles"] as List;
print(rest);
list = rest.map<NewsDataList>((json) => NewsDataList.fromJson(json)).toList();
return list;
} else {
throw Exception('Failed to load album');
}
}
V/r,
here is how you can about setting up the favourite button.
from list tile constructors we can use the trailing widget to set up a favorite button
const
ListTile(
{Key key,
Widget leading,
Widget title,
Widget subtitle,
Widget trailing,
bool isThreeLine: false,
bool dense,
EdgeInsetsGeometry contentPadding,
bool enabled: true,
GestureTapCallback onTap,
GestureLongPressCallback onLongPress,
bool selected: false}
)
First set up your list tile
ListTile(
leading: FlutterLogo(),
title: Text("article Title here"),
trailing: IconButton(
icon: Icon(
Icons.favorite,
color: _selectedIndex != null && _selectedIndex == position
? Colors.redAccent
: Colors.grey,
),
onPressed: (){
_onSelected(position);})
then how to change icon color on tap
int _selectedIndex;
_onSelected(int index) {
//https://inducesmile.com/google-flutter/how-to-change-the-background-color-of-selected-listview-in-flutter/
setState(() {
_selectedIndex = index;
});
}