提问人:Globe 提问时间:11/24/2022 更新时间:11/24/2022 访问量:47
为什么我的 Flutter PageView 在用户选择新的任何权限时会重置 (iOS)
Why is my Flutter PageView resetting when new any permission is selected by a user (iOS)
问:
我的应用请求访问照片库、相机、麦克风和位置的权限。每当用户为这些权限提示选择任何选项时,由于某种原因,该选项都会重置并转到第一个选项卡。中没有任何代码调用此函数,并且仅在设置权限后才会发生。我无法弄清楚为什么会这样。CreatePostScreen()
PageView
create_post_screen.dart
create_post_screen.dart
:
class CreatePostScreen extends StatefulWidget {
const CreatePostScreen({Key? key}) : super(key: key);
@override
State<CreatePostScreen> createState() => _CreatePostScreenState();
}
class _CreatePostScreenState extends State<CreatePostScreen> {
final _locationNameFormKey = GlobalKey<FormState>();
final _locationNameController = TextEditingController();
bool _isLoading = false;
List<String> originalFiles = [];
List<File> imageFiles = [];
void selectImages() async {
final result = await showModalActionSheet(
context: context,
title: 'Select Image Source',
actions: [
const SheetAction(label: 'Existing Images', key: 'existing'),
const SheetAction(label: 'New Image', key: 'new')
]);
if (result == 'new' && imageFiles.length < 4) {
newImage();
} else if (result == 'existing' && imageFiles.length < 4) {
existingImages();
}
}
void newImage() async {
setState(() {
_isLoading = true;
});
final XFile? image =
await ImagePicker().pickImage(source: ImageSource.camera);
if (image == null) return;
cropImages([image.path]);
}
void existingImages() async {
setState(() {
_isLoading = true;
});
final List<XFile>? selectedImages = await ImagePicker().pickMultiImage();
if (selectedImages == null) return;
int ableToAdd = 4 - imageFiles.length;
if (selectedImages.length > ableToAdd) {
List<XFile>? filesToAdd = selectedImages.sublist(0, ableToAdd);
List<String> imagePaths = [];
for (var selectedImage in filesToAdd) {
imagePaths.add(selectedImage.path);
}
cropImages(imagePaths);
} else {
List<String> imagePaths = [];
for (var selectedImage in selectedImages) {
imagePaths.add(selectedImage.path);
}
cropImages(imagePaths);
}
}
void cropImages(List<String> paths) async {
for (var path in paths) {
originalFiles.add(path);
final ImageProperties properties =
await FlutterNativeImage.getImageProperties(path);
final int width = properties.width!;
final int height = properties.height!;
int imageSize = width < height ? width : height;
int x = 0;
int y = 0;
File imageFile =
await FlutterNativeImage.cropImage(path, x, y, imageSize, imageSize);
setState(() {
int index = originalFiles.indexOf(path);
imageFiles.insert(index, imageFile);
_isLoading = false;
});
}
}
void customCrop(int index) async {
final fileToCrop = originalFiles[index];
final croppedFile = await ImageCropper().cropImage(
sourcePath: fileToCrop,
aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1),
aspectRatioPresets: [
CropAspectRatioPreset.square
],
uiSettings: [
AndroidUiSettings(toolbarTitle: 'Crop Image'),
IOSUiSettings(title: "Crop Image", showCancelConfirmationDialog: true)
]);
setState(() {
imageFiles[index] = File(croppedFile!.path);
});
}
Position? position;
void _determinePosition() async {
LocationPermission permission;
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
Position positionResult = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.lowest);
setState(() {
position = positionResult;
});
}
pkg.User user = Supabase.auth.currentUser!;
final postId = DateTime.now().millisecondsSinceEpoch.toString();
void uploadPost() async {
if (_locationNameFormKey.currentState!.validate()) {
_locationNameFormKey.currentState!.save();
setState(() {
_isLoading = true;
});
String name = _locationNameController.text;
Location location = Location(
position!.latitude,
position!.longitude,
name,
);
List<String> uploadedUrls = [];
for (var file in imageFiles) {
String fileName = '${DateTime.now().millisecondsSinceEpoch}_post.png';
Supabase.storage
.from('posts')
.upload('${user.id}/$fileName', supaFile.File(file.path));
String url = Supabase.storage.from('posts').getPublicUrl('${user.id}/$fileName');
setState(() {
uploadedUrls.add(url);
});
if (imageFiles.length == uploadedUrls.length) {
Post post = Post(
postId,
uploadedUrls,
user.id,
// profile,
location,
DateTime.now().millisecondsSinceEpoch,
);
print(post);
try {
Supabase.db
.from('posts')
.insert(post.toJson())
.then((value) {
setState(() {
imageFiles = [];
originalFiles = [];
_locationNameController.clear();
position = null;
_isLoading = false;
});
});
} catch (error) {
setState(() {
_isLoading = false;
});
print(error);
}
}
}
}
}
Widget imageItem(int index) {
File imageFile = imageFiles[index];
return SizedBox(
height: 200,
width: 200,
child: Card(
clipBehavior: Clip.hardEdge,
child: Stack(
children: [
Image.file(imageFile, fit: BoxFit.fill),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(5),
child: Row(
children: [
SizedBox(
height: 35,
width: 35,
child: FittedBox(
child: FloatingActionButton(
onPressed: () {
setState(() {
customCrop(index);
});
},
child: const Icon(Icons.edit_outlined),
),
),
),
const SizedBox(width: 5),
SizedBox(
height: 35,
width: 35,
child: FittedBox(
child: FloatingActionButton(
onPressed: () {
setState(() {
imageFiles.removeAt(index);
originalFiles.removeAt(index);
});
},
child: const Icon(Icons.delete_forever_sharp),
),
),
),
],
),
),
)
],
),
),
);
}
Widget picker() {
return imageFiles.isEmpty
? GestureDetector(
onTap: () {
selectImages();
},
child: Center(
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFd3d8e9),
borderRadius: BorderRadius.circular(10),
),
height: 150,
width: 300,
child: const Center(
child: Text(
'Press to add Images - Required',
style: TextStyle(color: Colors.red),
),
),
),
),
)
: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFd3d8e9),
borderRadius: BorderRadius.circular(10),
),
child: DragAndDropGridView(
physics: const ScrollPhysics(),
itemCount: imageFiles.length,
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
return imageItem(index);
},
onWillAccept: () {
return true;
},
onReorder: (oldIndex, newIndex) {
final temp = imageFiles[newIndex];
imageFiles[newIndex] = imageFiles[oldIndex];
imageFiles[oldIndex] = temp;
setState(() {});
},
),
),
),
],
);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
Scaffold(
resizeToAvoidBottomInset: true,
appBar: FloatingAppBar(
leading: const SizedBox(),
title: const Text('Create Post',
style: TextStyle(color: Color(0xFF7157A0), fontSize: 20)),
actions: [
if (imageFiles.isEmpty || position == null)
const Icon(Icons.send_outlined, color: Colors.grey),
if (imageFiles.isNotEmpty && position != null)
IconButton(
onPressed: () {
uploadPost();
},
icon:
const Icon(Icons.send_outlined, color: Color(0xFF7157A0)),
),
],
),
body: SingleChildScrollView(
child: Column(
children: [
picker(),
Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: _locationNameFormKey,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 80,
width: MediaQuery.of(context).size.width - 40,
child: TextFormField(
controller: _locationNameController,
textInputAction: TextInputAction.done,
keyboardType: TextInputType.name,
decoration: const InputDecoration(
suffix: Icon(Icons.edit_location_outlined,
color: Color(0xFF6C74B4)),
labelText: "Location Name",
floatingLabelStyle:
TextStyle(color: Color(0xFF697CB4)),
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(8)),
borderSide: BorderSide(
color: Color(0xFF6B6FAB), width: 1)),
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(8)),
borderSide: BorderSide(
color: Color(0xFF697CB4), width: 1)),
),
validator: (name) {
if (name == null) {
return 'This cannot be left empty';
}
if (name.length < 4 || name.length > 15) {
return 'Must be 4-15 characters';
}
return null;
},
),
),
],
),
),
),
GestureDetector(
onTap: () {
_determinePosition();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: () {
_determinePosition();
},
child: const Icon(Icons.location_on_outlined),
),
const SizedBox(width: 10),
if (position == null)
const Text(
'Press to add location - Required',
style: TextStyle(color: Colors.red),
),
if (position != null)
Text(
'Current location: ${position!.latitude.round()}, ${position!.longitude.round()}')
],
),
),
],
),
),
),
if (_isLoading)
const Opacity(
opacity: 0.8,
child: ModalBarrier(dismissible: false, color: Colors.black),
),
if (_isLoading)
const Center(
child: CircularProgressIndicator(color: Color(0xFFb1bbd8)),
),
],
);
}
}
我感谢任何帮助。
答: 暂无答案
评论