我正在做一个口袋妖怪去应用程序,需要作为输入的口袋妖怪截图,并从它的一些属性创建一个小部件。除了ListView. builder之外,一切都正常工作。以前的输入被转换为小部件,小部件作为字符串列表存储在Hive框中。当我添加照片以前的小部件,我在当前会话中添加转换成最后一个。这个问题一直持续到我重新启动应用程序。我不想使用setState作为解决方案,因为我知道它不是最佳的。感谢您的帮助!
https://imgur.com/a/2zmgnEu第四张图片是重新启动应用程序后发生的事情,第五张是口袋妖怪的示例截图。不要介意StunkFisk的身高。
import 'package:flutter/material.dart';
import 'package:pokemon_app/main_screen.dart';
import 'package:hive_flutter/hive_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
await Hive.openBox<List<String>>('pokeBox');
runApp(
const MyApp(),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MainScreen(),
);
}
}
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:pokemon_app/provider/poke_provider.dart';
import 'package:pokemon_app/poke_card/poke_class.dart';
class MainScreen extends StatefulWidget {
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
late final pokeProvider;
@override
void initState() {
pokeProvider = PokeProvider();
super.initState();
}
@override
Widget build(BuildContext context) {
var pokeBox = Hive.box<List<String>>('pokeBox');
return Scaffold(
appBar: AppBar(
title: const Text('Main Screen'),
actions: [
IconButton(
onPressed: () {
pokeBox.clear();
setState(() {});
},
icon: const Icon(Icons.delete),
),
IconButton(
onPressed: pokeProvider.getImageFromGallery,
icon: const Icon(
Icons.add_outlined,
color: Colors.white,
),
),
],
),
body: Center(
child: ValueListenableBuilder<Box<List<String>>>(
valueListenable: pokeBox.listenable(),
builder: (context, pokeBox, _) {
return pokeBox.isEmpty
? const Center(
child: Text(''),
)
: ListView.builder(
itemCount: pokeBox.length,
padding: const EdgeInsetsDirectional.only(bottom: 8),
itemBuilder: (context, index) {
return PokeCard(
singlePokeList: pokeProvider.getFromBox(index),
);
},
);
},
),
),
);
}
}
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';
import 'package:hive_flutter/hive_flutter.dart';
class PokeProvider{
final imagePicker = ImagePicker();
late File? imagePath;
late File croppedImageFile;
final textRecognizer = TextRecognizer(script: TextRecognitionScript.latin);
int x = 0;
var pokeBox = Hive.box<List<String>>('pokeBox');
List<String> pokeList = [
'Name',
'CP',
'Height',
'Weight'
]; //Limited size string, contents will be changed later. Variables will line like this.
String pokeName = 'Name';
String pokeCp = 'cp';
String pokeHeight = 'Height';
String pokeWeight = 'Weight';
getImageFromGallery() async {
final dummyImage = await imagePicker.pickImage(source: ImageSource.gallery);
if (dummyImage == null) return;
final imagePath = File(dummyImage.path);
final Image image =
Image(image: FileImage(imagePath)); // Getting image resolution for cropping desired part.
Completer<ui.Image> completer = Completer<ui.Image>();
image.image.resolve(const ImageConfiguration()).addListener(
ImageStreamListener(
(ImageInfo image, bool _) {
completer.complete(image.image);
},
),
);
ui.Image info = await completer.future;
int width = info.width; //taking images width and height to crop a spesific part
int height = info.height;
final imageBytes = img.decodeImage(imagePath.readAsBytesSync());
final croppedImage = img.copyCrop(imageBytes!,
x: 0,
y: (height * 0.35).round(),
width: width,
height: (height * 0.15).round());
final directory = await getTemporaryDirectory(); // for saving cropped images to temporary directory.
final directoryPath = directory.path; // so I can use text recognition on cropped image.
final croppedImagePng = img.encodePng(croppedImage);
croppedImageFile = await File(
'$directoryPath/CroppedImageFile$x.png')
.writeAsBytes(croppedImagePng);
final croppedInputImage = InputImage.fromFile(croppedImageFile); // image recognition on whole image.
final inputImage = InputImage.fromFile(imagePath); // image recognition on cropped image.
final RecognizedText recognizedText =
await textRecognizer.processImage(inputImage);
final RecognizedText croppedRecognizedText =
await textRecognizer.processImage(croppedInputImage);
for (TextBlock block in croppedRecognizedText.blocks) { //to get pokemon name from the cropped image.
for (TextLine line in block.lines) { // Its always on the first line so I break after one loop.
pokeName = line.text;
break;
}
break;
}
for (TextBlock block in recognizedText.blocks) { // I get other desired metrics here.
for (TextLine line in block.lines) {
if (line.text.contains('kg') ||
line.text.contains('m') ||
line.text.contains('CP') ||
line.text.contains('DG')
) {
if (line.text.contains('kg')) {
pokeWeight = line.text;
} else if (line.text.contains('m')) {
pokeHeight = line.text;
} else if (line.text.contains('CP') ||line.text.contains('DG')) {
pokeCp = line.text;
}
}
}
}
x++;
putToBox(pokeName, pokeCp, pokeWeight, pokeHeight);
textRecognizer.close();
}
void putToBox(String name, String cp, String weight, String height) {
pokeList[0] = name;
pokeList[1] = cp;
pokeList[2] = weight;
pokeList[3] = height;
pokeBox.add(pokeList);
}
List<String> getFromBox(int index) {
return pokeBox.getAt(index)!;
}
}
class PokeCard extends StatelessWidget {
const PokeCard(
{super.key,
required this.singlePokeList});
/* final String name;
final String combatPower;
final String height;
final String weight; */
final List<String> singlePokeList;
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Container(
margin: const EdgeInsets.only(bottom: 8),
decoration: BoxDecoration(
color: Colors.amber.shade100,
borderRadius: const BorderRadius.all(Radius.circular(15)),
),
width: screenSize.width * 0.55,
height: screenSize.height * 0.1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Text(singlePokeList[0]),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(singlePokeList[1]),
//Divider(thickness: 5,color: Colors.black, height: 12),
const VerticalDivider(),
Text(singlePokeList[2]),
const VerticalDivider(),
Text(singlePokeList[3]),
],
),
],
),
);
}
}
我使用提供程序包,然后改为ValueListanableBuilder,因为我看到它被用于另一个职位,但这并没有改变任何东西。
1条答案
按热度按时间vi4fp9gy1#
问题不是listView,而是字符串列表框。我创建了一个口袋妖怪类,并开始保存他们在数据库中。现在一切正常