CTK 1.0.2
This commit is contained in:
@@ -62,8 +62,7 @@ class _LoggedHomeScreenState extends State<LoggedHomeScreen>
|
||||
static const String _kPendingQuizScopeKey = 'pending_quiz_scope_v1';
|
||||
|
||||
static const double _collapsedAppBarHeight = kToolbarHeight;
|
||||
static const double _expandedAppBarHeight = 226;
|
||||
static const double _nameOnlyAppBarHeight = 160;
|
||||
static const double _expandedAppBarHeight = 256;
|
||||
|
||||
int _index = 0;
|
||||
|
||||
@@ -349,9 +348,11 @@ class _LoggedHomeScreenState extends State<LoggedHomeScreen>
|
||||
// um NestedScrollView em vez do AppBar fixo usado nas outras abas,
|
||||
// para que a altura acompanhe o scroll em vez de ficar sempre cheia
|
||||
// (o que cortava o conteúdo do card do quiz contra a barra ao rolar).
|
||||
final double expandedHeight = hasScore
|
||||
? _expandedAppBarHeight
|
||||
: _nameOnlyAppBarHeight;
|
||||
// A app bar mantém sempre a mesma altura e mostra sempre os dois
|
||||
// gauges — vazios (sem número, sem rótulo) quando ainda não há
|
||||
// resultado, para o utilizador já perceber que aquele espaço é para
|
||||
// o resultado do quiz mesmo antes de o fazer.
|
||||
const double expandedHeight = _expandedAppBarHeight;
|
||||
|
||||
return Scaffold(
|
||||
body: NestedScrollView(
|
||||
@@ -385,7 +386,7 @@ class _LoggedHomeScreenState extends State<LoggedHomeScreen>
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: kToolbarHeight + 34,
|
||||
top: kToolbarHeight + 50,
|
||||
child: Center(
|
||||
child: Text(
|
||||
(_selectedChildName ?? '').trim(),
|
||||
@@ -397,54 +398,35 @@ class _LoggedHomeScreenState extends State<LoggedHomeScreen>
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
else if ((_selectedChildName ?? '').trim().isNotEmpty)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: kToolbarHeight,
|
||||
bottom: 0,
|
||||
child: Center(
|
||||
child: Text(
|
||||
_selectedChildName!.trim(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w800,
|
||||
color: Colors.white.withValues(alpha: 0.92),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
//posição da app bar relativamente ao nome
|
||||
if (hasScore)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: kToolbarHeight + 60,
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_RiskArcGauge(
|
||||
// Usa sempre o máximo atual do quiz (não
|
||||
// o que foi gravado na última avaliação)
|
||||
// para não mostrar um denominador antigo
|
||||
// quando o número de perguntas muda.
|
||||
value: result.signs,
|
||||
max: kSignsMax,
|
||||
label: 'Sinais',
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
_RiskArcGauge(
|
||||
value: result.factors,
|
||||
max: kFactorsMax,
|
||||
label: 'Fatores de risco',
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: kToolbarHeight + 96,
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_RiskArcGauge(
|
||||
// Usa sempre o máximo atual do quiz (não
|
||||
// o que foi gravado na última avaliação)
|
||||
// para não mostrar um denominador antigo
|
||||
// quando o número de perguntas muda.
|
||||
value: hasScore ? result.signs : null,
|
||||
max: hasScore ? kSignsMax : null,
|
||||
label: 'Sinais de má\noclusão',
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
_RiskArcGauge(
|
||||
value: hasScore ? result.factors : null,
|
||||
max: hasScore ? kFactorsMax : null,
|
||||
label: 'Fatores de risco',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -587,19 +569,23 @@ class _LoggedHomeScreenState extends State<LoggedHomeScreen>
|
||||
}
|
||||
|
||||
class _RiskArcGauge extends StatelessWidget {
|
||||
const _RiskArcGauge({
|
||||
required this.value,
|
||||
required this.max,
|
||||
required this.label,
|
||||
});
|
||||
const _RiskArcGauge({required this.value, required this.max, this.label});
|
||||
|
||||
final int value;
|
||||
final int max;
|
||||
final String label;
|
||||
/// Quando [value]/[max] são nulos (sem criança selecionada, ou criança
|
||||
/// ainda sem quiz feito), o gauge mostra-se vazio — só o anel em branco,
|
||||
/// sem número nem rótulo — em vez de desaparecer, para o espaço já
|
||||
/// indicar onde o resultado vai aparecer assim que existir.
|
||||
final int? value;
|
||||
final int? max;
|
||||
final String? label;
|
||||
|
||||
bool get _isEmpty => value == null || max == null;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final progress = max > 0 ? (value / max).clamp(0, 1).toDouble() : 0.0;
|
||||
final progress = _isEmpty || max! <= 0
|
||||
? 0.0
|
||||
: (value! / max!).clamp(0, 1).toDouble();
|
||||
|
||||
return TweenAnimationBuilder<double>(
|
||||
duration: const Duration(milliseconds: 700),
|
||||
@@ -621,38 +607,40 @@ class _RiskArcGauge extends StatelessWidget {
|
||||
painter: _RiskArcGaugePainter(progress: animatedProgress),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 38,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'$value/$max',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w900,
|
||||
height: 1,
|
||||
if (!_isEmpty) ...[
|
||||
Positioned(
|
||||
top: 38,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'$value/$max',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w900,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 68,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Text(
|
||||
label,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.85),
|
||||
fontSize: 10.5,
|
||||
fontWeight: FontWeight.w700,
|
||||
height: 1.15,
|
||||
letterSpacing: 0.1,
|
||||
Positioned(
|
||||
top: 68,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Text(
|
||||
label ?? '',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.85),
|
||||
fontSize: 10.5,
|
||||
fontWeight: FontWeight.w700,
|
||||
height: 1.15,
|
||||
letterSpacing: 0.1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -1350,7 +1338,7 @@ class _HeroQuizCard extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
'28 perguntas rápidas · menos de 3 minutos',
|
||||
'29 perguntas rápidas · menos de 3 minutos',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.92),
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
Reference in New Issue
Block a user