اضافة امكانية اختيار الصور مثل الموجوده في تطبيق انستقرام داخل تطبيقات فلاتر
في هذا المقال سوف نشرح معكم كيف تقوم بامكانية عمل خاصية اختيار الصور مثل التي توجد في تطبيق انستقرام كما هو موضح بالصورة الخاصه بالمقال من اجل تحسين تطبيقك على الانترنت وزيادة انتشار التطبيق وكما نعلم ان كل هذه العوامل تساعد بشكل كبير جدا في انتشار التطبيق لان المستخدم عندما يفضل استخدام تطبيقك قد يخبر به اصدقاءه وهذا يساعدك في انتشار التطبيق بصورة كبيره جدا وكل هذه العوامل مع عوامل تطوير تطبيقات الجوال الناجحه ونحن نقدم لكم دائما كل ما هو جديد في مجال تطوير تطبيقات الهواتف بمختلف اللغات البرمجية .
add packages:
flutter_localizations:
sdk: flutter
insta_assets_picker:
How to add Instagram selectable images for flutter app
بعد تثبيت المكتبات السابقة تستطيع عزيري القارئ ان تقوم بعمل تصميم ال ui وايضا تصميم الشكل المناسب الذي ترغب به وهذا الكود هو نفس الكود الموجود في الصورة الخاصه بالمقال وهو مقسوم لجزئين تستطيع النقر على النص حتى يتم فتح معك نافذة اختيار الصور كما هو موضح وبعد اختيار الصور سوف تظهر في النافذه الاخرى ويتم تخزينها قيمتها حتى تستطيع رئيتها او رفعها على الانترنت سواء api او firebase او غيرها من المنصات .
android sdk manager تحميل flutter developers applications create app android android studio mac
ui.dart
class MyMobileBody extends StatefulWidget {
const MyMobileBody({Key? key}) : super(key: key);
@override
State<MyMobileBody> createState() => _MyMobileBodyState();
}
class _MyMobileBodyState extends State<MyMobileBody> {
final _instaAssetsPicker = InstaAssetPicker();
final _provider = DefaultAssetPickerProvider(maxAssets: 10);
List<AssetEntity> selectedAssets = <AssetEntity>[];
InstaAssetsExportDetails? exportDetails;
@override
void dispose() {
_provider.dispose();
_instaAssetsPicker.dispose();
super.dispose();
}
Future<void> callRestorablePicker() async {
final List<AssetEntity>? result =
await _instaAssetsPicker.restorableAssetsPicker(
context,
title: 'Restorable',
closeOnComplete: true,
provider: _provider,
onCompleted: (cropStream) {
// example withtout StreamBuilder
cropStream.listen((event) {
if (mounted) {
setState(() {
exportDetails = event;
});
}
});
},
);
if (result != null) {
selectedAssets = result;
if (mounted) {
setState(() {});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Insta picker')),
body: DefaultTabController(
length: 2,
child: Column(
children: <Widget>[
const Material(
color: Colors.deepPurple,
child: TabBar(
tabs: [
Tab(text: 'Normal picker'),
Tab(text: 'Restorable picker'),
],
),
),
Expanded(
child: TabBarView(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Center(
child: Text(
'The picker will push result in a new screen',
style: TextStyle(fontSize: 18),
),
),
TextButton(
onPressed: () => InstaAssetPicker.pickAssets(
context,
title: 'Select images',
maxAssets: 10,
onCompleted: (cropStream) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PickerCropResultScreen(
cropStream: cropStream),
),
);
},
),
child: const Text(
'Open the Picker',
style: TextStyle(fontSize: 20),
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Center(
child: Text(
'The picker will restore the picker state.\n'
'The preview, selected album and scroll position will be the same as before pop\n'
'Using this picker means that you must dispose it manually',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
),
TextButton(
onPressed: callRestorablePicker,
child: const Text(
'Open the Restorable Picker',
style: TextStyle(fontSize: 20),
),
),
],
),
),
CropResultView(
selectedAssets: selectedAssets,
croppedFiles: exportDetails?.croppedFiles ?? [],
progress: exportDetails?.progress,
)
],
),
],
),
),
],
),
),
);
}
}
class PickerCropResultScreen extends StatelessWidget {
const PickerCropResultScreen({super.key, required this.cropStream});
final Stream<InstaAssetsExportDetails> cropStream;
@override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height - kToolbarHeight;
return Scaffold(
appBar: AppBar(title: const Text('Insta picker result')),
body: StreamBuilder<InstaAssetsExportDetails>(
stream: cropStream,
builder: (context, snapshot) => CropResultView(
selectedAssets: snapshot.data?.selectedAssets ?? [],
croppedFiles: snapshot.data?.croppedFiles ?? [],
progress: snapshot.data?.progress,
heightFiles: height / 2,
heightAssets: height / 4,
),
),
);
}
}
class CropResultView extends StatelessWidget {
const CropResultView({
super.key,
required this.selectedAssets,
required this.croppedFiles,
this.progress,
this.heightFiles = 300.0,
this.heightAssets = 120.0,
});
final List<AssetEntity> selectedAssets;
final List<File> croppedFiles;
final double? progress;
final double heightFiles;
final double heightAssets;
Widget _buildTitle(String title, int length) {
return SizedBox(
height: 20.0,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(title),
Container(
margin: const EdgeInsets.symmetric(horizontal: 10.0),
padding: const EdgeInsets.all(4.0),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.deepPurpleAccent,
),
child: Text(
length.toString(),
style: const TextStyle(
color: Colors.white,
height: 1.0,
),
),
),
],
),
);
}
Widget _buildCroppedImagesListView(BuildContext context) {
if (progress == null) {
return const SizedBox.shrink();
}
return Expanded(
child: Stack(
alignment: Alignment.center,
children: [
ListView.builder(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 8.0),
scrollDirection: Axis.horizontal,
itemCount: croppedFiles.length,
itemBuilder: (BuildContext _, int index) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 16.0,
),
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.0),
),
child: Image.file(croppedFiles[index]),
),
);
},
),
if (progress! < 1.0)
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
color:
Theme.of(context).scaffoldBackgroundColor.withOpacity(.5),
),
),
),
if (progress! < 1.0)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(5)),
child: SizedBox(
height: 6,
child: LinearProgressIndicator(
value: progress,
semanticsLabel: '${progress! * 100}%',
),
),
),
),
],
),
);
}
Widget _buildSelectedAssetsListView() {
if (selectedAssets.isEmpty) return const SizedBox.shrink();
return Expanded(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 8.0),
scrollDirection: Axis.horizontal,
itemCount: selectedAssets.length,
itemBuilder: (BuildContext _, int index) {
final AssetEntity asset = selectedAssets.elementAt(index);
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 16.0,
),
// TODO : add delete action
child: RepaintBoundary(
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image(image: AssetEntityImageProvider(asset)),
),
),
);
},
),
);
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AnimatedContainer(
duration: kThemeChangeDuration,
curve: Curves.easeInOut,
height: croppedFiles.isNotEmpty ? heightFiles : 40.0,
child: Column(
children: <Widget>[
_buildTitle('Cropped Images', croppedFiles.length),
_buildCroppedImagesListView(context),
],
),
),
AnimatedContainer(
duration: kThemeChangeDuration,
curve: Curves.easeInOut,
height: selectedAssets.isNotEmpty ? heightAssets : 40.0,
child: Column(
children: <Widget>[
_buildTitle('Selected Assets', selectedAssets.length),
_buildSelectedAssetsListView(),
],
),
),
],
);
}
}