因此,每当我调试我的应用程序时,都会显示图表和信息,但每当我尝试使用发布的 apk 时,它都会显示为这些灰色框。
如果您对为什么会发生这种情况或如何解决它或任何其他问题有任何想法,我将非常感激。 (如果我遗漏了什么请告诉我,我会添加它)
提前谢谢你:)
这就是它们本来的样子
但它们在发布时看起来像这样
这是页面
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables, sized_box_for_whitespace, must_be_immutable, unnecessary_brace_in_string_interps, avoid_print, unused_local_variable
import 'package:flutter/material.dart';
import 'package:the_holy_trinity/models/food_model.dart';
import 'package:the_holy_trinity/modules/styles/text_styles.dart';
import 'package:the_holy_trinity/modules/widgets/amount_selection.dart';
import 'package:the_holy_trinity/modules/widgets/nutrients_display.dart';
import 'package:the_holy_trinity/services/getters/per_hundred.dart';
String? dropDownValue;
class FoodDetailsPage extends StatefulWidget {
Food food;
Serving? serving;
FoodDetailsPage({super.key, required this.food, required this.serving});
@override
State<FoodDetailsPage> createState() => _FoodDetailsPageState();
}
class _FoodDetailsPageState extends State<FoodDetailsPage> {
@override
Widget build(BuildContext context) {
String getAverage(double total, double individual) {
double averageValue = (individual / total) * 100;
String average = '${averageValue.toStringAsFixed(1)}%';
return average;
}
final Food food = widget.food;
final Serving serving = widget.serving!;
double protein = double.parse(serving.protein.toString());
double carbohydrate = double.parse(serving.carbohydrate.toString());
double fat = double.parse(serving.fat.toString());
double servingAmountD = double.parse(serving.metricservingamount.toString());
final nutritionPerHundred = NutritionPerHundred(servingSize: servingAmountD, fat: fat, carbs: carbohydrate, protein: protein);
final perHundred = nutritionPerHundred.calculateValuesPerHundred();
protein = perHundred.proteinPer100g;
carbohydrate = perHundred.carbsPer100g;
fat = perHundred.fatPer100g;
String proteinString = ('${protein.toString()}g');
String carbohydrateString = ('${carbohydrate.toString()}g');
String fatString = ('${fat.toString()}g');
return Scaffold(
appBar: AppBar(
title: HeaderStyle('${food.foodName}'),
),
body: Container(
height: MediaQuery.of(context).size.height * 1,
width: MediaQuery.of(context).size.width * 1,
child: Column(
children: [
Divider(),
BodyStyle('Per 100g'),
//Nutrients per 100
Container(
height: MediaQuery.of(context).size.height * 0.2,
width: MediaQuery.of(context).size.width * 1,
child: DisplayNutrientsPerHundred(carbohydrate: carbohydrate, fat: fat, protein: protein),
),
Divider(),
//Amount Selector
Container(
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width * 1,
child: SelectAmount(dropDownValue: dropDownValue),
)
],
),
),
);
}
}
这是详细图
// ignore_for_file: sized_box_for_whitespace
import 'package:flutter/cupertino.dart';
import 'package:the_holy_trinity/modules/styles/text_styles.dart';
import 'package:the_holy_trinity/modules/widgets/nutrients_pie_chart.dart';
class DisplayNutrientsPerHundred extends StatelessWidget {
double carbohydrate;
double fat;
double protein;
DisplayNutrientsPerHundred({
super.key,
required this.carbohydrate,
required this.fat,
required this.protein,
});
@override
Widget build(BuildContext context) {
String getAverage(double total, double individual) {
double averageValue = (individual / total) * 100;
String average = '${averageValue.toStringAsFixed(1)}%';
return average;
}
String proteinString = ('${protein.toString()}g');
String carbohydrateString = ('${carbohydrate.toString()}g');
String fatString = ('${fat.toString()}g');
double totalNutrients = protein + carbohydrate + fat;
String proteinPercent = getAverage(totalNutrients, protein);
String carbohydratePercent = getAverage(totalNutrients, carbohydrate);
String fatPercent = getAverage(totalNutrients, fat);
return Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: MediaQuery.of(context).size.height * 0.2,
width: MediaQuery.of(context).size.width * 0.5,
child: PieChart(sCarbsValue: carbohydrate, sFatValue: fat, sProteinValue: protein)
),
Container(
height: MediaQuery.of(context).size.height * 0.2,
width: MediaQuery.of(context).size.width * 0.5,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BodyStyle('Fat: ${fatString} - ${fatPercent}\n\nCarbs: ${carbohydrateString} - ${carbohydratePercent}\n\nProtein: ${proteinString} - ${proteinPercent}'),
],
)
),
],
),
);
}
}
这是绘制饼图的代码
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class ChartData {
final String x;
final double y;
final Color? color;
ChartData(this.x, this.y, [this.color]);
}
class PieChart extends StatelessWidget {
final double sProteinValue;
final double sCarbsValue;
final double sFatValue;
const PieChart({
super.key,
required this.sCarbsValue,
required this.sFatValue,
required this.sProteinValue,
});
@override
Widget build(BuildContext context) {
final List<ChartData> chartData = [
ChartData('Fat', sFatValue, const Color.fromARGB(255, 207, 144, 196)),
ChartData('Carbs', sCarbsValue, const Color.fromARGB(255, 126, 158, 126)),
ChartData('Protein', sProteinValue,const Color.fromARGB(255, 230, 220, 149)),
];
return Scaffold(
body: Center(
child: Container(
child: SfCircularChart(
legend: Legend(
isVisible: true,
position: LegendPosition.right,
textStyle: TextStyle(
fontFamily: 'Lato',
fontSize: 13,
color: Color.fromARGB(255, 138, 138, 138),
fontWeight: FontWeight.bold,
decorationColor: Color.fromARGB(255, 255, 255, 255),
decorationStyle: TextDecorationStyle.wavy,
)
),
series: <CircularSeries>[
DoughnutSeries<ChartData, String>(
dataSource: chartData,
pointColorMapper:(ChartData data, _) => data.color,
xValueMapper: (ChartData data, _) => data.x,
yValueMapper: (ChartData data, _) => data.y,
dataLabelMapper: (ChartData data, _) => data.x,
startAngle: 0,
endAngle: 180,
legendIconType: LegendIconType.circle,
)
]
)
)
)
);
}
}
这是选择尺寸的代码,就是那个小下拉菜单和底部的文本字段
// ignore_for_file: sized_box_for_whitespace
import 'package:flutter/material.dart';
import 'package:the_holy_trinity/modules/styles/text_styles.dart';
class SelectAmount extends StatefulWidget {
String? dropDownValue;
SelectAmount({super.key, required this.dropDownValue});
@override
State<SelectAmount> createState() => _SelectAmountState();
}
class _SelectAmountState extends State<SelectAmount> {
var dropDownValue;
@override
Widget build(BuildContext context) {
return Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: MediaQuery.of(context).size.width * 0.02),
Container(
height: MediaQuery.of(context).size.height * 0.035,
width: MediaQuery.of(context).size.width * 0.2,
child: const TextField(
decoration: InputDecoration(
disabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
keyboardType: TextInputType.numberWithOptions(),
)),
SizedBox(width: MediaQuery.of(context).size.width * 0.05),
Container(
height: MediaQuery.of(context).size.height * 0.05,
width: MediaQuery.of(context).size.width * 0.7,
child: DropdownButton<String>(
hint: BodyStyle('Select a value'),
value: dropDownValue,
onChanged: (String? newValue) {
if (newValue == '1g') {
print('1g');
} else if (newValue == '10g') {
print('10g');
} else {
print('100g');
}
setState(() {
dropDownValue = newValue;
print(newValue);
});
},
items: <String>['1g', '10g', '100g']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: BodyStyle(value),
);
}).toList(),
)
),
SizedBox(width: MediaQuery.of(context).size.width * 0.02),
],
),
);
}
}
我认为运行时会抛出异常,因为某些东西得到了空值,请确保在 Android 清单上添加了互联网权限
<manifest xmlns:android="...">
<uses-permission android:name="android.permission.INTERNET"/> <!-- Add this line -->
<application
......
......
</application>
</manifest>