start select image

PHOTO_PICKER_LDE
Lucas Delanier 2 years ago
parent 1abcd1a5a9
commit b520ad5204

@ -1,15 +1,120 @@
import 'package:flutter/Material.dart'; import 'package:flutter/Material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:ionicons/ionicons.dart';
import '../values/constants.dart'; import '../values/constants.dart';
class ButtonPostComponent extends StatelessWidget { class PhotoPostComponent extends StatelessWidget {
const ButtonPostComponent({Key? key}) : super(key: key); final bool empty;
const PhotoPostComponent({Key? key, required this.empty}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return empty
padding: EdgeInsets.fromLTRB(20, 5, 20, 5), ? Container(
color: postbutton, padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: postbutton, borderRadius: BorderRadius.circular(8)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Ionicons.camera,
size: 15,
color: Colors.white,
),
SizedBox(
width: 10,
),
Text(
'Prendre un selfie',
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontSize: 12),
)
]),
)
: Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: fillButton, borderRadius: BorderRadius.circular(8)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Selfie enregistré",
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontSize: 12),
),
SizedBox(
width: 10,
),
Icon(
Icons.close,
size: 12,
color: Colors.white,
),
]),
);
}
}
class LocationPostComponent extends StatelessWidget {
final bool empty;
const LocationPostComponent({Key? key, required this.empty})
: super(key: key);
@override
Widget build(BuildContext context) {
return empty
? Container(
width: double.infinity,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: postbutton, borderRadius: BorderRadius.circular(8)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.location_on,
size: 15,
color: Colors.white,
),
SizedBox(
width: 10,
),
Text(
'Ajouter un lieu',
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontSize: 12),
)
]),
)
: Container(
width: double.infinity,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: fillButton, borderRadius: BorderRadius.circular(8)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Lieu enregistré",
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontSize: 12),
),
SizedBox(
width: 10,
),
Icon(
Icons.close,
size: 12,
color: Colors.white,
),
]),
); );
} }
} }

@ -1,24 +1,33 @@
import 'dart:io'; import 'dart:io';
import 'package:animated_appear/animated_appear.dart';
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:circular_reveal_animation/circular_reveal_animation.dart';
import 'package:flutter/Material.dart'; import 'package:flutter/Material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:insta_image_viewer/insta_image_viewer.dart';
import 'package:justmusic/values/constants.dart'; import 'package:justmusic/values/constants.dart';
import 'package:text_scroll/text_scroll.dart';
import '../model/Music.dart';
import 'buttonPostComponent.dart';
class EditablePostComponent extends StatefulWidget { class EditablePostComponent extends StatefulWidget {
final Function callback; final Music? music;
const EditablePostComponent({Key? key, required this.callback}) const EditablePostComponent({Key? key, this.music}) : super(key: key);
: super(key: key);
@override @override
State<EditablePostComponent> createState() => _EditablePostComponentState(); State<EditablePostComponent> createState() => _EditablePostComponentState();
} }
class _EditablePostComponentState extends State<EditablePostComponent> { class _EditablePostComponentState extends State<EditablePostComponent>
with TickerProviderStateMixin {
final ImagePicker picker = ImagePicker(); final ImagePicker picker = ImagePicker();
late Animation<double> animation;
late AnimationController animationController;
File? image; File? image;
Future pickImage() async { Future pickImage() async {
@ -34,6 +43,20 @@ class _EditablePostComponentState extends State<EditablePostComponent> {
} }
} }
@override
void initState() {
animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
);
animation = CurvedAnimation(
parent: animationController,
curve: Curves.easeInOutSine,
);
animationController.forward();
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ClipRRect( return ClipRRect(
@ -42,16 +65,15 @@ class _EditablePostComponentState extends State<EditablePostComponent> {
constraints: BoxConstraints(maxWidth: 400, minHeight: 500), constraints: BoxConstraints(maxWidth: 400, minHeight: 500),
width: double.infinity, width: double.infinity,
color: warningBttnColor, color: warningBttnColor,
child: Column(
children: [
CircularRevealAnimation(
animation: animation,
centerOffset: Offset(30.w, -100),
child: Stack( child: Stack(
alignment: Alignment.topCenter,
children: [ children: [
AspectRatio( AspectRatio(
aspectRatio: 1 / 1, aspectRatio: 1 / 1,
child: GestureDetector(
onTap: () {
print("cc");
widget.callback;
},
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
// add border // add border
@ -62,53 +84,146 @@ class _EditablePostComponentState extends State<EditablePostComponent> {
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(18), borderRadius: BorderRadius.circular(18),
// implement image // implement image
child: const Image( child: widget.music == null
image: AssetImage("assets/images/exemple_cover.png"), ? Container(
color: grayColor,
width: double.infinity,
)
: Image(
image:
NetworkImage(widget.music?.cover ?? ""),
fit: BoxFit.cover, fit: BoxFit.cover,
width: double.infinity, width: double.infinity,
), ),
), ),
), ),
),
image != null
? Positioned(
top: 10,
right: 10,
child: AnimatedAppear(
delay: Duration(milliseconds: 500),
duration: Duration(milliseconds: 400),
child: Container(
width: 110,
height: 110,
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(image!),
fit: BoxFit.cover,
),
color: grayColor,
borderRadius: BorderRadius.circular(20),
border: Border.all(
style: BorderStyle.solid,
color: Colors.white,
width: 4)),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: InstaImageViewer(
backgroundIsTransparent: true,
child: Image(
image: FileImage(image!),
fit: BoxFit.cover,
),
),
),
),
))
: Container()
],
)), )),
Positioned( widget.music != null
bottom: 40, ? Padding(
child: Padding( padding: const EdgeInsets.all(10),
padding: EdgeInsets.fromLTRB(15, 25, 15, 25),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
AutoSizeText( Flexible(
"France, Lyon", flex: 8,
child: TextScroll(
(widget.music?.title)!,
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontSize: 13.sp), height: 1,
maxFontSize: 20, color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 26.h),
mode: TextScrollMode.endless,
pauseBetween: Duration(milliseconds: 500),
velocity:
Velocity(pixelsPerSecond: Offset(20, 0)),
)),
Padding(
padding: EdgeInsets.only(
bottom: 10.h, right: 5.w, left: 5.w),
child: ClipOval(
child: Container(
width: 5.h,
height: 5.h,
color: Colors.white,
), ),
image == null
? GestureDetector(
child: Image(
image:
AssetImage("assets/images/camera_icon.png"),
width: 30,
), ),
onTap: () {
print("cc2");
pickImage();
},
)
: Container(
height: 80,
width: 80,
child: Image.file(image!),
), ),
Flexible(
flex: 6,
child: Padding(
padding: EdgeInsets.only(bottom: 2),
child: TextScroll(
(widget.music?.artists[0].name)!,
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white,
fontWeight: FontWeight.w300,
fontSize: 16.h),
mode: TextScrollMode.endless,
velocity:
Velocity(pixelsPerSecond: Offset(50, 20)),
pauseBetween: Duration(milliseconds: 500),
),
)),
Container(width: 10),
AutoSizeText( AutoSizeText(
"10 Juil. 2023", "2013",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontSize: 13.sp), color: Colors.white.withOpacity(0.5),
fontWeight: FontWeight.w300,
fontSize: 16.h),
textAlign: TextAlign.end,
maxFontSize: 20, maxFontSize: 20,
), ),
], ],
), ),
)
: Container(),
Container(
padding: EdgeInsets.fromLTRB(15, 15, 15, 25),
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 5,
child: GestureDetector(
onTap: () {
manageImage();
},
child: PhotoPostComponent(
empty: image == null,
),
),
),
SizedBox(
width: 15,
),
Expanded(
flex: 5,
child: LocationPostComponent(
empty: true,
),
),
],
), ),
), ),
Padding( Padding(
@ -155,4 +270,14 @@ class _EditablePostComponentState extends State<EditablePostComponent> {
), ),
)); ));
} }
void manageImage() {
if (image != null) {
setState(() {
image = null;
});
} else {
pickImage();
}
}
} }

@ -9,7 +9,7 @@ class MusicListComponent extends StatelessWidget {
final bool playing; final bool playing;
final int index; final int index;
final Function(int) callback; final Function(int) callback;
const MusicListComponent({ MusicListComponent({
Key? key, Key? key,
required this.music, required this.music,
required this.playing, required this.playing,

@ -10,8 +10,8 @@ class PlayButtonComponent extends StatefulWidget {
final Music music; final Music music;
final Function callback; final Function callback;
final int index; final int index;
bool playing; final bool playing;
PlayButtonComponent( const PlayButtonComponent(
{Key? key, {Key? key,
required this.music, required this.music,
required this.callback, required this.callback,
@ -63,7 +63,9 @@ class _PlayButtonComponentState extends State<PlayButtonComponent> {
child: AnimatedPlayButton( child: AnimatedPlayButton(
stopped: false, stopped: false,
color: Colors.grey.withOpacity(0.3), color: Colors.grey.withOpacity(0.3),
onPressed: () {}, onPressed: () {
print("cc");
},
), ),
)); ));
} }

@ -5,6 +5,7 @@ import 'package:justmusic/components/back_button.dart';
import 'package:justmusic/screens/search_song_screen.dart'; import 'package:justmusic/screens/search_song_screen.dart';
import '../components/editable_post_component.dart'; import '../components/editable_post_component.dart';
import '../components/post_button_component.dart'; import '../components/post_button_component.dart';
import '../model/Music.dart';
import '../values/constants.dart'; import '../values/constants.dart';
class PostScreen extends StatefulWidget { class PostScreen extends StatefulWidget {
@ -18,7 +19,8 @@ class _PostScreenState extends State<PostScreen>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
final scrollController = ScrollController(); final scrollController = ScrollController();
late AnimationController _controller; late AnimationController _controller;
late Animation<double> _animation;
Music? selectedMusic;
@override @override
void initState() { void initState() {
@ -27,15 +29,16 @@ class _PostScreenState extends State<PostScreen>
duration: const Duration(milliseconds: 400), duration: const Duration(milliseconds: 400),
); );
_animation = Tween<double>(begin: 0.0, end: 400.0).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeOut,
),
);
super.initState(); super.initState();
} }
void _selectMusic(Music music) {
Navigator.pop(context);
setState(() {
selectedMusic = music;
});
}
void openDetailPost() { void openDetailPost() {
showModalBottomSheet( showModalBottomSheet(
transitionAnimationController: _controller, transitionAnimationController: _controller,
@ -51,10 +54,10 @@ class _PostScreenState extends State<PostScreen>
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20))), topLeft: Radius.circular(20), topRight: Radius.circular(20))),
builder: ((context) { builder: ((context) {
return const ClipRRect( return ClipRRect(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20)), topLeft: Radius.circular(20), topRight: Radius.circular(20)),
child: SearchSongScreen()); child: SearchSongScreen(callback: _selectMusic));
}), }),
); );
} }
@ -90,10 +93,7 @@ class _PostScreenState extends State<PostScreen>
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
child: Stack( child: ScrollConfiguration(
alignment: Alignment.topCenter,
children: [
ScrollConfiguration(
behavior: ScrollBehavior().copyWith(scrollbars: false), behavior: ScrollBehavior().copyWith(scrollbars: false),
child: SingleChildScrollView( child: SingleChildScrollView(
controller: scrollController, controller: scrollController,
@ -103,7 +103,9 @@ class _PostScreenState extends State<PostScreen>
SizedBox( SizedBox(
height: 100.h, height: 100.h,
), ),
EditablePostComponent(callback: openDetailPost), GestureDetector(
onTap: openDetailPost,
child: EditablePostComponent(music: selectedMusic)),
SizedBox( SizedBox(
height: 40.h, height: 40.h,
), ),
@ -115,8 +117,6 @@ class _PostScreenState extends State<PostScreen>
), ),
), ),
), ),
],
),
), ),
); );
} }

@ -11,7 +11,8 @@ import '../values/constants.dart';
import '../main.dart'; import '../main.dart';
class SearchSongScreen extends StatefulWidget { class SearchSongScreen extends StatefulWidget {
const SearchSongScreen({Key? key}) : super(key: key); final Function callback;
const SearchSongScreen({Key? key, required this.callback}) : super(key: key);
@override @override
State<SearchSongScreen> createState() => _SearchSongScreenState(); State<SearchSongScreen> createState() => _SearchSongScreenState();
@ -169,25 +170,35 @@ class _SearchSongScreenState extends State<SearchSongScreen> {
itemCount: filteredData.length, itemCount: filteredData.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (playingIndex == index) { if (playingIndex == index) {
return Padding( return InkWell(
padding: const EdgeInsets.symmetric(horizontal: 20), onTap: () {
widget.callback(filteredData[index]);
},
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20),
child: MusicListComponent( child: MusicListComponent(
music: filteredData[index], music: filteredData[index],
playing: true, playing: true,
callback: playMusic, callback: playMusic,
index: index, index: index,
), ),
); ));
} }
return Padding( return InkWell(
padding: const EdgeInsets.symmetric(horizontal: 20), onTap: () {
widget.callback(filteredData[index]);
},
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20),
child: MusicListComponent( child: MusicListComponent(
music: filteredData[index], music: filteredData[index],
playing: false, playing: false,
callback: playMusic, callback: playMusic,
index: index, index: index,
), ),
); ));
}), }),
)) ))
], ],

@ -21,6 +21,7 @@ const grayText = Color(0xFF898989);
const settingColor = Color(0xFF232323); const settingColor = Color(0xFF232323);
const searchBarColor = Color(0xFF161616); const searchBarColor = Color(0xFF161616);
const postbutton = Color(0xFF1B1B1B); const postbutton = Color(0xFF1B1B1B);
const fillButton = Color(0xFF633AF4);
// All constants important too us // All constants important too us
const defaultPadding = 30.0; const defaultPadding = 30.0;

@ -1,6 +1,14 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
animated_appear:
dependency: "direct main"
description:
name: animated_appear
sha256: "53097d7bb6d5e4a1a3a74c8f3028c47c87101c6ec8903f2002372d1eb5aee991"
url: "https://pub.dev"
source: hosted
version: "0.0.4"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -368,6 +376,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.1" version: "0.2.1"
insta_image_viewer:
dependency: "direct main"
description:
name: insta_image_viewer
sha256: "9a81432b1ab907ea91c255ec079440afe43f999533422badffaa482dfb7fdfbb"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
ionicons: ionicons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -488,6 +504,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.7" version: "2.1.7"
pinch_zoom:
dependency: "direct main"
description:
name: pinch_zoom
sha256: ad12872281742726afaf03438d99a4572c584a612630768953beb6dfd6f9389a
url: "https://pub.dev"
source: hosted
version: "1.0.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@ -517,6 +541,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
smooth_list_view:
dependency: "direct main"
description:
name: smooth_list_view
sha256: d6eb3bed78881c50d4574b0dd466ed3321972477688c1c021178f3132155112a
url: "https://pub.dev"
source: hosted
version: "1.0.4"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:

@ -54,6 +54,10 @@ dependencies:
ionicons: ^0.2.2 ionicons: ^0.2.2
top_snackbar_flutter: ^3.1.0 top_snackbar_flutter: ^3.1.0
image_picker: ^1.0.1 image_picker: ^1.0.1
insta_image_viewer: ^1.0.2
pinch_zoom: ^1.0.0
smooth_list_view: ^1.0.4
animated_appear: ^0.0.4
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save