I'm using this link from the coinapi web but it gives real time data I want a data when I press a button need solution or coinapi link I've read the coinapi complete documentation but I cant find any solution over there need a link or solution that gives me data when I clicked a button or when I require some data from coinapi.
code here:
class _MainPageState extends State<MainPage> {
double dollars;
String selectedValue = "USD";
List<DropdownMenuItem> getDropDown() {
List<DropdownMenuItem<String>> menuItems = [];
for (String items in list) {
var item = DropdownMenuItem(
child: Text(items),
value: items,
);
menuItems.add(item);
}
return menuItems;
}
#override
void initState() {
// TODO: implement initState
super.initState();
getNetData();
}
void getNetData() async {
HTTP.Response response = await HTTP.get(
'https://rest.coinapi.io/v1/exchangerate/BTC/USD?apikey=myKey';
if (response.statusCode == 200) {
setState(() {
dollars = jsonDecode(response.body)['rate'];
});
} else
print('Error');
}
#override
Widget build(BuildContext context) {
getNetData();
getDropDown();
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.all(20.0),
child: Container(
child: Card(
color: Colors.lightBlue,
child: ListTile(
title: Text(
'1 BTC = $dollars USD DOLLAR',
textAlign: TextAlign.center,
),
),
),
),
),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Container(
height: 150.0,
color: Colors.lightBlue,
child: Center(
child: DropdownButton(
value: selectedValue,
items: getDropDown(),
onChanged: (value) {
setState(() {
selectedValue = value;
});
},
),
),
),
),
],
),
],
);
}
}
In your code in build and initState methods you retrieving the data from WEB but is not correct. If you need get the data each time when screen opening, you can use FutureBuilder widget (with it you can add a loader to providing information about current data retrieving state) and not call getNetData from initState. For update the data from a button (if you are choose FutureBuilder), just call setState (which calls build method again and reload value).
Something like this:
class _MainPageState extends State<MainPage> {
String selectedValue = "USD";
Future<String> getRate() async {
HTTP.Response response = await HTTP.get('https://rest.coinapi.io/v1/exchangerate/BTC/$selectedValue?apikey=myKey');
if (response.statusCode == 200) {
return jsonDecode(response.body)['rate'];
} else {
// TODO: handle error code correctly
return '';
}
}
#override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getRate(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
// The data is loading, show progress
return CircularProgressIndicator();
}
final rate = snapshot.data;
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.all(20.0),
child: Container(
child: Card(
color: Colors.lightBlue,
child: ListTile(
title: Text(
'1 BTC = $rate USD DOLLAR',
textAlign: TextAlign.center,
),
),
),
),
),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Container(
height: 150.0,
color: Colors.lightBlue,
child: Center(
child: DropdownButton(
value: selectedValue,
items: getDropDown(),
onChanged: (value) => setState(() {}),
),
),
),
),
],
),
],
);
},
);
}
List<DropdownMenuItem> getDropDown() {
List<DropdownMenuItem<String>> menuItems = [];
for (String items in list) {
var item = DropdownMenuItem(
child: Text(items),
value: items,
);
menuItems.add(item);
}
return menuItems;
}
}
Related
I have listview.builder which gets data from FutureBuilder. When I press and hold any list item, first the whole listview gets rebuilt again, then the selected item is highlighted. I gunderstand this is because when setstate is called for item slecetion and the build method runs again, the future builder also fetches the data which causes this problem. How can I avoid this behavior and only highlight the selected item without rebuilding the whole listview? I'm not sure how can I implement Consumer in my code? This is my code:
_onSelected(int index) {
setState(() => _selectedIndex = index);
}
Color getColor( int index){
if(light_mode)
{
if(_selectedIndex != null && _selectedIndex == index)
return Color(0xFFFFB2FF);
else
return Color(0xFFFFFFFF);
}
else{
if(_selectedIndex != null && _selectedIndex == index)
return Color(0xFF8E8E8E);
else
return Color(0xFF6D6D6D);
}
}
#override
Widget build(BuildContext context) {
// TODO: implement build
final makeBody = Container(
decoration: BoxDecoration(
color: light_mode ? Color(0xFFFFFFFF) : Color(0xFF6D6D6D)),
child: setView()
);
}
Widget setView() {
return FutureBuilder<List<Juz>>(
future: getSurahData(context),
builder:( BuildContext context, AsyncSnapshot<List<Juz>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if ( snapshot.connectionState==ConnectionState.done) {
// Center(child: CircularProgressIndicator( value: 0.5, valueColor: AlwaysStoppedAnimation<Color>(Colors.white)));
//while(surahcountlist.isEmpty);
return returnListview();
}
else {
return Text("error");
}
);}
Widget returnListview(){
return Column(
textDirection: TextDirection.rtl,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
new Expanded(
child: SizedBox(
height: 200.0,
child: ListView.builder(
controller: hiding.controller,
itemCount:surahcountlist.length,
itemBuilder: (context, index) {
return new GestureDetector( //You need to make my child interactive
onLongPress: () => _onSelected(index),
child: Card(
color: getColor(index),
child: Column(
textDirection: TextDirection.rtl,
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: <Widget>[
showBSMLSV(index),
Wrap(
direction: Axis.horizontal,
alignment:
WrapAlignment.start,
runAlignment:
WrapAlignment.center,
textDirection:
TextDirection.rtl,
spacing: 2.0,
// gap between adjacent chips
runSpacing: 5.0,
children: makeSurahListview(
surahcountlist[index].surah_no,
surahcountlist[index].ayah_no,
surahcountlist[index].count)),
])));
}
) ))
]);
}
Use StatefulBuilder Widget for the list items and change state of that particular list item widget
flutter docs for stateful widget
I wrote my code in flutter, and used NewsAPI.org for getting content about news, such as heading, image, content etc. I made a class "News" and ArticleModel() for retrieving and using the information. I used Conditional Operator (? :) for checking if the data is received, then show it, else CircularProgressIndiactor() is shown. After running the app, CircularProgressIndiactor() shows up and no information is shown/loaded. Can anyone help me here??
No error or warning is shown, and code compiles successfully, but no information is shown up.
Here is the main file, home.dart -
import 'package:flutter/material.dart';
import 'package:news_app/helper/data.dart';
import 'package:news_app/helper/news.dart';
import 'package:news_app/models/article_model.dart';
import 'package:news_app/models/category_models.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<CategoryModel> categories = new List<CategoryModel>();
List<ArticleModel> articles = new List<ArticleModel>();
bool loading = true;
#override
void initState() {
// TODO: implement initState
super.initState();
categories = getCategories();
getNews();
}
getNews() async {
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
loading = false;
print('Done');
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Flutter',
style: TextStyle(
color: Colors.black,
),
),
Text(
'News',
style: TextStyle(
color: Colors.blue,
),
),
],
),
//elevation: 2.0,
),
body: loading
? Center(
child: Container(
child: CircularProgressIndicator(),
),
)
: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
///Categories
Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
height: 70.0,
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return CategoryTile(
imageUrl: categories[index].imageUrl,
categoryName: categories[index].categoryName,
);
},
),
),
///Blogs
Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: articles.length,
itemBuilder: (context, index) {
return BlogTile(
imageUrl: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
);
},
),
),
],
),
),
),
),
);
}
}
class CategoryTile extends StatelessWidget {
final imageUrl, categoryName;
CategoryTile({this.imageUrl, this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {},
child: Container(
margin: EdgeInsets.only(right: 16.0),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: Image.network(
imageUrl,
width: 120.0,
height: 160.0,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.center,
width: 120.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6.0)),
child: Text(
categoryName,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 14.0,
),
),
),
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageUrl, title, desc;
BlogTile(
{#required this.imageUrl, #required this.desc, #required this.title});
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Image.network(imageUrl),
Text(title),
Text(desc),
],
),
);
}
}
Here is the News.dart file -
import 'dart:convert';
import 'package:news_app/models/article_model.dart';
import 'package:http/http.dart' as http;
class News {
List<ArticleModel> news = [];
Future<void> getNews() async{
String url="http://newsapi.org/v2/top-headlines?country=in&category=business&apiKey=xxxxxxxxxxxxxxxxxx";
var response = await http.get(url);
var jsonData = jsonDecode(response.body);
if(jsonData["status"] == "ok") {
jsonData["articles"].forEach((element){
if(element['urlToImage'] != null && element['description'] != null) {
ArticleModel articleModel = ArticleModel(
title: element['title'],
author: element['author'],
description: element['description'],
url: element['url'],
urlToImage: element['urlToImage'],
content: element['content'],
);
news.add(articleModel);
}
});
}
}
}
And at last, ArticleModel.dart -
class ArticleModel {
String author, title, description;
String url, urlToImage;
String content;
ArticleModel({this.title, this.description, this.author, this.content, this.url, this.urlToImage});
}
Updating your request URL from http to https will give you expected result.
Update URL to: "https://newsapi.org/v2/top-headlines?country=in&category=business&apiKey="
Note: Don't share your API key in any open platforms for security reasons.
I want to get my API data's length to use in Listview.builder widget. I want to get my data from API which is 'mahalle'. And this data is a list of data. I want to get this data's length to build a list. But I got an error like this:
#4 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4546
...
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════
Class 'Future<dynamic>' has no instance getter 'length'.
Receiver: Instance of 'Future<dynamic>'
Tried calling: length
The relevant error-causing widget was
MahalleList
And the reference of the error is :
#action
Future<void> fetcMahalle() async {
// var data =
// await httpClient.getData(globals.SELECT_URL).then((mahalle) => mahalle);
networkService.getMahalle();
}
And I'm getting my data with :
Future getMahalle() async {
BaseOptions options = new BaseOptions(
baseUrl: globals.PROD_URL,
connectTimeout: 5000,
receiveTimeout: 3000,
);
Dio dio = new Dio(options);
dio.options.headers["Authorization"] = "Bearer ${globals.USER_TOKEN}";
try {
var response =
await dio.get(globals.SELECT_URL); //'api/hizlirapor/selects'
List<MahalleModel> mahalleList = response.data['mahalle']
.map<MahalleModel>((mahalle) => MahalleModel.fromJson(mahalle))
.toList();
return mahalleList;
} on DioError catch (e) {
debugPrint("ERRORR!!!!!!!!!!!!! ${e.error.toString()}");
return null;
}
}
And finally here's the widget I'm trying to use my list data's length :
Container _buildBody(
BuildContext context, ObservableFuture<List<MahalleModel>> future) {
return Container(
color: backgroundColor,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
_buildSearchBar(context),
RefreshIndicator(
onRefresh: mahalleStore.fetcMahalle,
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: mahalleList.length,
itemBuilder: (context, index) {
final mahalle = mahalleList[index];
return Container(
height: 100,
child: Card(
color: Colors.white,
margin: EdgeInsets.all(15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
color: mainColor,
width: 3,
height: 50,
),
SizedBox(
width: 15,
),
Icon(
AppIcon.mahalle_raporu,
color: mainColor,
),
SizedBox(
width: 15,
),
Text(
mahalle.mahalleAdi,
style: textStyle,
),
],
),
),
);
}),
),
],
),
);
}
Thanks for your all help !
FutureBuilder(
future:mahalleStore.fetchMahalle,
builder: (context, snapshot){
//whatever returns from this function, will be avaliable inside snapshot paremeter.
final mahalleList= snapshot.data;
switch (snapshot.connectionState) {
case ConnectionState.waiting:
{
return Center(child: CircularProgressIndicator(),);
}
case ConnectionState.done:
if (snapshot.hasData) {
// do what you want here
}
return Text("Error occured");
default:
//
}});
I deleted previous comment , check this one.
You should use FutureBuilder because getMahalle returns a Future.
i am trying to implement login functionality using bloc pattern in flutter. So I want to navigate to main page after authentication is successful. from loginBloc.dart I will get the status inside the streamBuilder in login.dart when the status is success I want to navigate to main.dart but I cant able to understand how to call the main.dart inside the streamBuilder in login.dart.
login.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_svg/svg.dart';
import 'package:hotelorders/bloc/LoginBloc.dart';
import 'package:hotelorders/screens/Home.dart';
class Login extends StatefulWidget
{
#override
State<StatefulWidget> createState() {
return LoginState();
}
}
class LoginState extends State<Login>
{
final LoginBloc _loginBloc = LoginBloc();
String _email,_password;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
#override
void dispose()
{
_loginBloc.dispose();
super.dispose();
}
Widget _progressBar()
{
return StreamBuilder<bool>(
stream: _loginBloc.progressStream,
builder: (BuildContext context,AsyncSnapshot<bool> snapShot) {
bool visible;
if(snapShot.data == null)
{
visible = false;
}
else
{
visible = snapShot.data;
}
return Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: visible,
child: Container(
child: Center(
child: SizedBox(
width: 60,
height: 60,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 1.0,
),
],
),
),
Center(
child: CircularProgressIndicator(),
)
],
),
)
)
),
);
}
);
}
Widget _emailTextField()
{
return TextFormField(
decoration: InputDecoration(
labelText: "Email id",
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
)
),
keyboardType: TextInputType.emailAddress,
validator: (String value){
if(value.isEmpty || !RegExp(r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?").hasMatch(value))
{
return "Enter a valid email id";
}
return null;
},
onSaved: (String value){
_email = value;
},
);
}
Widget _passwordTextField()
{
return TextFormField(
decoration: InputDecoration(labelText: "Password",
filled: true,
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
),
fillColor: Colors.white
),
keyboardType: TextInputType.text,
obscureText: true,
validator: (String value){
if(value.isEmpty)
{
return "Enter a valid password";
}
else if(value.length < 8)
{
return "Password is too short";
}
else
{
return null;
}
},
);
}
void _login()
{
if(!_formKey.currentState.validate())
{
return;
}
_formKey.currentState.save();
Map<String,String> map = new Map();
map['email'] = _email;
map['password'] = _password;
_loginBloc.login(map);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
alignment: Alignment.center,
margin: EdgeInsets.fromLTRB(0, 48, 0, 0),
child: Text(
"Take Orders and",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
),
),
Container(
child: Text(
"Track the Best Selling Items",
style: TextStyle(color: Theme.of(context).primaryColor,fontSize: 16),
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: SvgPicture.asset('assets/images/undraw_booking.svg',width: 100.0,height: 280.0,),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 0, 0),
child:Row(
children: <Widget>[
Text(
"Login To ",
style: TextStyle(color: Colors.black,fontSize: 20)
),
Text(
"Take orders",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
)
],
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 8, 16, 0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _emailTextField(),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _passwordTextField(),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: Align(
alignment: Alignment.centerLeft,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32.0)
),
padding: EdgeInsets.fromLTRB(64, 12, 64, 12),
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text(
"Login",
),
onPressed: (){
_login();
},
) ,
),
),
StreamBuilder<dynamic>(
stream:_loginBloc.loginStateStream,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapShot){
if(snapShot.data == "success")
{
// WidgetsBinding.instance.addPostFrameCallback((_){
// Navigator.push(context, MaterialPageRoute(
// builder: (context)=> Home()
// ));
// });
}
else if(snapShot.data != null && snapShot.data != "success")
{
WidgetsBinding.instance.addPostFrameCallback((_) {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('${snapShot.data}',
style: TextStyle(color: Colors.black),),
backgroundColor: Color(0xFFe5e5e5),
));
// showDialog(context: context,builder: (BuildContext con){
// return AlertDialog(
// title: Text('${snapShot.data}'),
// );
// });
});
}
return Container();
},
)
],
),
),
)
],
),
)
),
_progressBar(),
],
),
);
}
}
LoginBloc.dart
import 'dart:async';
class LoginBloc
{
// here event comes in and state goes out
//stream conntroller for output
final _loginStateController = StreamController<String>();
//stream controller for input
final _loginEventController = StreamController<Map<String,String>>();
final _progressController = StreamController<bool>();
StreamSink<String> get loginStateSink => _loginStateController.sink;
Stream<String> get loginStateStream => _loginStateController.stream;
Sink<Map<String,String>> get loginEventSink => _loginEventController.sink;
Stream<bool> get progressStream => _progressController.stream;
StreamSink<bool> get progressSink => _progressController.sink;
LoginBloc()
{
progressSink.add(false);
_loginEventController.stream.listen(login);
}
login(Map<String,String> loginDetails)
{
progressSink.add(true);
Timer(Duration(seconds: 3), () {
progressSink.add(false);
loginStateSink.add("success");
});
// when we pass data in sink we get the output from stream
}
void dispose()
{
_loginEventController.close();
_loginStateController.close();
_progressController.close();
}
}
You are almost there. The following should work :
if(snapShot.data == "success")
{
Navigator.push(
context, MaterialPageRoute(builder: (context)=> Home()));
}
Note : WidgetsBinding.instance.addPostFrameCallback is used to get a callback when widget tree is loaded.
I want to get an image path from selected multiple images, I'm using this link to select multiple images but I got assets, I want paths from selected multiple images because I want to upload into the API.
I added this dependency in pubspec.yaml If there any good way to do this, please tell me
multi_image_picker: ^4.6.3
This is my file upload class, This UI looks similar to Facebook.
import 'dart:typed_data';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:multi_image_picker/multi_image_picker.dart';
class UpdateStatus extends StatefulWidget {
#override
_UpdateStatusState createState() => _UpdateStatusState();
}
class _UpdateStatusState extends State<UpdateStatus> {
List<Asset> images = List<Asset>();
String _error = 'No Error Dectected';
Future<ByteData> byteData;
// List<int> imageData = byteData.buffer.asUint8List();
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Create Post'),
actions: <Widget>[
Padding(
padding: const EdgeInsets.all(18.0),
child: InkWell(child: Text('POST',style: TextStyle(fontSize: 18.0),),onTap: ()
{
print('Post this post');
},),
)
],
),
body: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
width:MediaQuery.of(context).size.width ,
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
height: 300.0,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
keyboardType: TextInputType.multiline,
maxLines: 100,
style: new TextStyle(
fontSize: 18.0,
color: Colors.black
),
decoration: InputDecoration(
hintText: 'Enter your Post Details Here !',
border: InputBorder.none,
),
),
),
),
Divider(
thickness: 1.0,
),
Column(
children: <Widget>[
Container(
height: 40.0,
color: Colors.white70,
child: Padding(
padding:EdgeInsets.only(left: 18.0,),
child: InkWell(
child: Row(
children: <Widget>[
Icon(Icons.add_a_photo,),
Text(" Choose Image",style: TextStyle(fontSize: 24.0,),),
],
),
onTap: ()
{
print(images.toList().toString());
print('choose image from local');
},
),
),
),
Divider(
thickness: 1.0,
),
Container(
height: 40.0,
color: Colors.white70,
child: Padding(
padding:EdgeInsets.only(left: 18.0,),
child: InkWell(
child: Row(
children: <Widget>[
Icon(Icons.add_photo_alternate,),
Text(" Choose Video",style: TextStyle(fontSize: 24.0,),),
],
),
onTap: ()
{
print('choose video from local');
},
),
),
),
],
),
Divider(
thickness: 1.0,
),
Container(
height: 200,
child: Column(
children: <Widget>[
Center(child: Text('Error: $_error')),
RaisedButton(
child: Text("Pick images"),
onPressed: loadAssets,
),
Expanded(
child: buildGridView(),
)
],
),
),
/*
Column(
children: <Widget>[
Center(child: Text('Error: $_error')),
RaisedButton(
child: Text("Pick images"),
onPressed: loadAssets,
),
Expanded(
child: buildGridView(),
)
],
),
*/
],
),
),
),
);
}
Future<void> loadAssets() async {
List<Asset> resultList = List<Asset>();
String error = 'No Error Dectected';
ByteData byteData;
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
enableCamera: true,
selectedAssets: images,
cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
materialOptions: MaterialOptions(
actionBarColor: "#abcdef",
actionBarTitle: "Ilma",
allViewTitle: "All Photos",
useDetailsView: false,
selectCircleStrokeColor: "#000000",
),
);
} on Exception catch (e) {
error = e.toString();
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
images = resultList;
_error = error;
print('000000000000000000000');
print('000000000000000000000');
print(images);
print('000000000000000000000');
print('000000000000000000000');
});
}
Widget buildGridView() {
return GridView.count(
crossAxisCount: 3,
children: List.generate(images.length, (index) {
Asset asset = images[index];
byteData=asset.getByteData();
print('0000');
print(byteData);
print('0000');
return AssetThumb(
asset: asset,
width: 300,
height: 300,
);
}),
);
}
}
Padding(
padding: const EdgeInsets.all(18.0),
child: InkWell(
child: Text(
'POST',
style: TextStyle(fontSize: 18.0),
),
onTap: () async {
List<MultipartFile> multipart = List<MultipartFile>();
for (int i = 0; i < images.length; i++) {
var path = await FlutterAbsolutePath.getAbsolutePath(images[i].identifier);
}
},
),
)
I'm Using below Code to select multiple images by using file_picker: ^2.0.7 Library.
Long press to select multiple image. Once Image Selected you can use f arr to display the images.
List<File> f = List();
RaisedButton(
child: Text("Pick Image"),
onPressed: () async {
FilePickerResult result = await FilePicker.platform.pickFiles(
allowMultiple: true,
type: FileType.custom,
allowedExtensions: ['jpg', 'png', 'jpeg'],
);
if (result != null) {
f = result.paths.map((path) => File(path)).toList();
setState(() {});
print(f);
}
},
),
Sample API Call For image upload and normal data. Image uploaded column should be arr ( photo[] ).
List<MultipartFile> newList = new List<MultipartFile>();
Future<String> ImageUpload() async {
var request = http.MultipartRequest('POST', url);
request.headers["Authorization"] = pref.getString("token");
request.headers["Accept"] = "application/json";
//Image Data
for (int i = 0; i < f.length; i++) {
newList.add(await http.MultipartFile.fromPath('photo[]', f[i].path));
}
request.files.addAll(newList);
Map<String, dynamic> data = Map<String, String>();
//normal data
data["user_id"] = user_id;
data["project_id"] = pro_id;
request.fields.addAll(data);
var res = await request.send();
if (res.statusCode == 200) {
debugPrint("Status${res}");
}else {
debugPrint("status code${res}");
}
}
Try This You can select and upload multiple images easily. Thank you.
Use multi_image_picker 4.7.14 library to pick Multiple Images. use below code you can send selected asset image as a file. `
//Inside Widget Builder
FlatButton(
child: Image.asset(
"assets/images/camera.png",
color: Colors.grey,
),
onPressed: loadAssets,
),
SizedBox(
// height: SizeConfig.safeBlockHorizontal * 10,
height: MediaQuery.of(context).size.height / 2,
child: Column(
children: <Widget>[
Expanded(
child: buildGridView(),
),
],
),
)
List<File> fileImageArray = [];
List<String> f = List();
List<Asset> resultList = List<Asset>();
List<Asset> images = List<Asset>();
Future<void> loadAssets() async {
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 4,
enableCamera: true,
selectedAssets: images,
cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
materialOptions: MaterialOptions(
actionBarColor: "#abcdef",
actionBarTitle: "Example App",
allViewTitle: "All Photos",
useDetailsView: false,
selectCircleStrokeColor: "#000000",
),
);
} on Exception catch (e) {
error = e.toString();
}
if (!mounted) return;
for (int i = 0; i < resultList.length; i++) {
var path =
await FlutterAbsolutePath.getAbsolutePath(resultList[i].identifier);
print(path);
f.add(File(path));
}
setState(() {
images = resultList;
});
// return fileImageArray;
}
//image PreView
Widget buildGridView() {
return GridView.count(
crossAxisCount: 4,
children: List.generate(images.length, (index) {
Asset asset = images[index];
return AssetThumb(
asset: asset,
width: 50,
height: 50,
);
}),
);
}
API Call : while image uploading place use multipart file
List<MultipartFile> newList = new List<MultipartFile>();
Future<String> multiImagePostAPI() async {
var request = http.MultipartRequest('POST', url);
request.headers["Authorization"] = pref.getString("token");
request.headers["Accept"] = "application/json";
for (int i = 0; i < f.length; i++) {
newList.add(await http.MultipartFile.fromPath('photo[]', f[i].path));
}
request.files.addAll(newList);
Map<String, dynamic> data = Map<String, String>();
data["user_id"] = user_id;
data["project_id"] = pro_id;
data["title"] = titleController.text;
request.fields.addAll(data);
var res = await request.send();
if (res.statusCode == 200) {
debugPrint("Status$res");
}else {
debugPrint("status : $res");
}
}
You can also select multiple images using file_picker: ^1.5.0+2 library and easy to get path of selected images
Future<int> getFilePath() async {
try {
files = await FilePicker.getMultiFile();
if (files == '') {
return 0;
}
else
{
setState(() {
this._filePath = files;
return 1;
});
}
} on PlatformException catch (e) {
print("Error while picking the file: " + e.toString());
}
}
show selected images by using ListView Builder like this
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _filePath.length,
itemBuilder: (context,c)
{
return Card(
child: Image.file(_filePath[c],
fit: BoxFit.fill,
width: 400,
height: 400,
),
);
}
),