Programmare applicazioni mobili con flutter

Pubblicità
Ho fatto così:
JavaScript:
class PagInformazioniApplicazione extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final List<dynamic> _listapronta = [];
    _listapronta.insertAll(0, listaInformazioni);
    _listapronta.insert(0, Text(applicazione['nome']));
    _listapronta.insert(1, Image(image: AssetImage('immagini/logo-flutter.png')));
    _listapronta.insert(2, SizedBox(height: 15.0));

    return Scaffold(
      appBar: AppBar(
        title: Text(testi['paginfoapptit']),
        elevation: Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0,
      ),
      body: Container(
        decoration: lineaGrigiaSuperiore(context),
        child: ListView.separated(
          separatorBuilder: (_, i) => (i <= 2 ? SizedBox(height: 1.0) : Divider(height: 1.0)),
          itemBuilder: (_, i) => _listapronta[i],
          itemCount: _listapronta.length,
        ),
      ),
    );
  }
}
Alla fine ce l'ho fatta! :rock:

Ora sto sperimentando l'oggetto drawer, ma nelle proprietà dell'oggetto non trovo un modo per dargli un po' di grafica personalizzata, come il colore di sfondo o la larghezza.

Come posso fare?

Grazie
 
Ora sto sperimentando l'oggetto drawer, ma nelle proprietà dell'oggetto non trovo un modo per dargli un po' di grafica personalizzata, come il colore di sfondo o la larghezza.

Come posso fare?

Eh un momento. Colore di sfondo. Il material design ha delle regole precise. Sennò si scazza tutto.

Poi Drawer non è un oggetto grafico, ma una struttura organizzativa. Pertanto non ha proprietà grafiche. Il colore lo puoi settare per il child di un Drawer. Per esempio un Container e modifichi la relativa proprietà colore.

Ma non si fa così secondo le regole del material design. S'impostano invece i parametri del tema dell'applicazione ( proprietà theme della classe MaterialApp ). E lo sfondo del drawer si adatterà al relativo colore specificato nel tema.

Quello che t'interessa è questo https://api.flutter.dev/flutter/material/ThemeData-class.html

E' importante rispettare le regole. Per esempio settare il primo figlio del Container come DrawerHeader, che è quel titolone che appare in cima ad un Drawer. E pure quello è progettato per pescare i suoi colori e altri attribuiti grafici, dal tema di sistema.
 
Un po' l'ho ridefinito il tema dell'app con copyWith() sostituendo qualche valore del tema predefinito chiaro. Ho anche cambiato il font generale dell'app, e vedo che funziona. Per il colore di sfondo vedo dal tema.
Invece per la larghezza? Vorrei restringerlo un po' se possibile.

Grazie
 
Perfetto.

Ora vorrei lasciare per un momento i widget per passare a cose più complesse.

Ci sono alcune cose da salvare nella memoria del telefono in cui viene eseguita l'applicazione, ad esempio alcune impostazioni, o altre informazioni riguardanti l'ultima apertura dell'app. Questi in ambito web sono i cookie.

Come posso fare nell'app queste cose?

Grazie
 
Mi sono dilettato con la combinazione key-value, almeno per salvare qualche impostazione.

Ho provato a farlo sull'emulatore con questo codice
main.dart
JavaScript:
// un bel po' di import ci sono qui

void main() {
  runApp(ApplicazioneMia());
}

class ApplicazioneMia extends StatefulWidget {
  @override
  _ApplicazioneMiaState createState() => _ApplicazioneMiaState();
}

class _ApplicazioneMiaState extends State<ApplicazioneMia> {
  @override
  void initState() {
    super.initState();
    caricaImpostazioni();
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
        localizationsDelegates: [
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
        ],
        supportedLocales: [
          const Locale.fromSubtags(languageCode: 'it'),
        ],
        title: testi['titolo'],
        theme: temaGeneraleAndroid(),
        home: PagIniziale(),
        routes: <String, WidgetBuilder>{
          '/impostazioni': (BuildContext context) => PagImpostazioni(),
          // altre routes
        },
      );
}
variabili.dart
JavaScript:
SharedPreferences impostazioniSalvate;

void caricaImpostazioni() async {
  impostazioniSalvate = await SharedPreferences.getInstance();
}
impostazioni.dart
JavaScript:
class PagImpostazioni extends StatefulWidget {
  @override
  _PagImpostazioniState createState() => _PagImpostazioniState();
}

class _PagImpostazioniState extends State<PagImpostazioni> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(testi['menula-impo']),
        elevation: Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0,
      ),
      body: Container(
        decoration: lineaGrigiaSuperiore(context),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            ListTile(
              title: Text('Prima impostazione'),
              subtitle: Text(
                  'Hai premuto ${(impostazioniSalvate.getInt('voltepremuto') ?? 0)} volte'),
              trailing: Icon(Icons.keyboard_arrow_right),
              onTap: () {
                setState(() {
                  impostazioniSalvate.setInt(
                      'voltepremuto', (impostazioniSalvate.getInt('voltepremuto') ?? 0) + 1);
                });
              },
            ),
          ],
        ),
      ),
      //resizeToAvoidBottomInset: false,
    );
  }
}
E fin qui tutto funziona bene, almeno nell'emulatore, sul cell non ho provato.

Ma se provo a mettere il contenuto di quella variabile salvata nella pagina iniziale dell'app, mi dà schermata rossa di errore, e nella console tutto questo papiro:
Codice:
I/flutter ( 3856): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 3856): The following NoSuchMethodError was thrown building PagIniziale(dirty, dependencies:
I/flutter ( 3856): [_LocalizationsScope-[GlobalKey#cc548], _InheritedTheme], state: _PagInizialeState#84465):
I/flutter ( 3856): The method 'getInt' was called on null.
I/flutter ( 3856): Receiver: null
I/flutter ( 3856): Tried calling: getInt("voltepremuto")
I/flutter ( 3856):
I/flutter ( 3856): The relevant error-causing widget was:
I/flutter ( 3856):   PagIniziale file:///home/mic/progetti-applicazioni/miaapp/lib/main.dart:40:15
I/flutter ( 3856):
I/flutter ( 3856): When the exception was thrown, this was the stack:
I/flutter ( 3856): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
I/flutter ( 3856): #1      _PagInizialeState.build (package:applicazione/pagine/iniziale.dart:35:48)
I/flutter ( 3856): #2      StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
I/flutter ( 3856): #3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
I/flutter ( 3856): #4      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4675:11)
I/flutter ( 3856): #5      Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
I/flutter ( 3856): #6      ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4481:5)
I/flutter ( 3856): #7      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4666:11)
I/flutter ( 3856): #8      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4476:5)
I/flutter ( 3856): ...     Normal element mounting (115 frames)
I/flutter ( 3856): #123    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 3856): #124    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 3856): ...     Normal element mounting (255 frames)
I/flutter ( 3856): #379    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 3856): #380    Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18)
I/flutter ( 3856): #381    RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1148:16)
I/flutter ( 3856): #382    RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1119:5)
I/flutter ( 3856): #383    RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1061:17)
I/flutter ( 3856): #384    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2607:19)
I/flutter ( 3856): #385    RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1060:13)
I/flutter ( 3856): #386    WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:941:7)
I/flutter ( 3856): #387    WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:922:7)
I/flutter ( 3856): (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
I/flutter ( 3856):
I/flutter ( 3856): ════════════════════════════════════════════════════════════════════════════════════════════════════
D/EGL_emulation( 3856): eglMakeCurrent: 0x9f3055a0: ver 2 0 (tinfo 0x9f303710)

Da quello che ho capito, crea la pagina iniziale ancor prima di leggere la variabile dalla memoria salvata sul dispositivo. Invece a me serve prima leggere le impostazioni, e poi preparare la pagina iniziale. Sono disposto a mettere uno splash.

Come posso rimediare?

Grazie
 
Mi sono scordato di postare anche il file iniziale.dart
JavaScript:
class PagIniziale extends StatefulWidget {
  @override
  _PagInizialeState createState() => _PagInizialeState();
}

class _PagInizialeState extends State<PagIniziale> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(testi['titolo']),
        elevation: Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0,
      ),
      drawer: MenuLaterale(),
      body: Container(
        decoration: lineaGrigiaSuperiore(context),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Center(
              child: Text(
                'Premuto ${(impostazioniSalvate.getInt('voltepremuto') ?? 0)} volte',//
                style: TextStyle(fontSize: 36.0),
              ),
            ),
          ],
        ),
      ),
      //resizeToAvoidBottomInset: false,
    );
  }
}

Se metto ${(impostazioniSalvate.getInt('voltepremuto') in pagina iniziale, ricevo l'errore che ho riportato, altrimenti tutto funziona bene. Ma a me serve farlo.
 
Allora l'unica possibilità è che la variabili non venga inizializzata prima dell'uso. Essendo un'inizializzazione asincrona, è possibile che accada.

Potresti cominciare col trasformarla in sincrona. Oppure rivedere la struttura del programma e passare impostazioniSalvate al costruttore di PagIniziale.
 
Allora l'unica possibilità è che la variabili non venga inizializzata prima dell'uso. Essendo un'inizializzazione asincrona, è possibile che accada.
Infatti ora che ho leggermente cambiato la pagina iniziale, la schermata rossa di errore dura meno di mezzo secondo per poi apparire la schermata che ho programmato io. Comunque nella console viene mostrato l'elenco che ho postato prima.
Potresti cominciare col trasformarla in sincrona. Oppure rivedere la struttura del programma e passare impostazioniSalvate al costruttore di PagIniziale.
Magari trasformarla in sincrona, ma non nella pagina iniziale. Lì devo contenere alcune impostazioni riguardanti l'intera app, quindi mi serve già pronta prima di aprire qualsiasi pagina.
Vorrei (se possibile) creare un'altra route di attesa (con un'immagine o qualcosa leggera) che viene aperta quando apro l'app, per poi andare alla pagina iniziale quanto la variabile è pronta. Devo usare initialRoute di material?
Vorrei fare questa procedura come viene fatta anche dai professionisti che sviluppano app come quelle di fb o whatsapp.

Cosa mi consigli?

Grazie
 
Prima di leggermi la documentazione, voglio anticipare una cosa che ho in programma di fare, che riguarda anche l'inizializzazione delle impostazioni.
Ribadisco che l'app la voglio compilare solo per android e ios, le altre piattaforme non mi interessano.

Subito dopo aver risolto il problema della variabile impostazioni, voglio creare tutto quello che riguarda le notifiche. Quindi si tratta di mostrare notifiche sul dispositivo se sul server (dove risiederanno php e mysql) viene disposto di farlo. Vorrei evitare di usare servizi esterni tipo firebase, ma controllando periodicamente se dal server arriva qualcosa di nuovo, mostrare la notifica, anche ad applicazione chiusa. Un po' come whatsapp.

Quindi, come deduco, mi serve inizializzare l'app e le variabili appena viene acceso il telefono, esattamente come fa whatsapp. E ora non so se devo fare lo splash screen o altro.

Cosa mi consigli?

Grazie
 
Pubblicità
Pubblicità
Indietro
Top