Spargerea machetei în rânduri și coloane în Flutter

Dacă ați citit despre Flutter chiar și timp de 5 minute, trebuie să vă împiedicați cu Widgets. Și cel mai popular fapt „În Flutter, aproape totul este un widget”.

Da, totul.

Definesc widget-urile ca componente sau blocuri care definesc interfața de utilizator. AppBar este un widget, textul de pe el este un widget, stilul pe care îl aplici textului este un widget, chiar și alinierea textului ar putea fi numită widget. În Flutter, orice este o vizualizare sau contribuie la o proprietate a vizualizării este un widget.

Pot continua și despre widgeturi, dar pentru a simplifica, aici este o listă recomandată de widget-uri pe care trebuie să le știți pentru a construi o aplicație în Flutter. Pentru referință rapidă, consultați mai jos.

Concentrarea pe rânduri și coloane

În Flutter, puteți împărți aproape 90% din design-urile în rânduri și coloane. Ocazional, va trebui să utilizați alte widget-uri, cum ar fi Stack, Grid etc, dar de la nivelul de bază, veți avea nevoie de rânduri și coloane într-un bloc UI sau altul.

Deci Rândurile și Coloanele sunt ...

Când există elemente așezate unul lângă altul, sau la stânga / la dreapta oricărui alt element, aveți nevoie de Rânduri.

Când există elemente așezate una după alta, sau vertical sus / jos la alt element, aveți nevoie de Coloane.

Destul de bază, nu?

În scopul acestui articol, ar trebui să știți și următoarele:
Containere: Dacă provineți dintr-un fundal de dezvoltare web sau aveți cunoștințe de bază despre HTML, containerele vor suna destul de familiar pentru div.
Stive: Dacă există vizualizări care se suprapun altor vizualizări, utilizați Stive.

Să construim ceva UI

E timpul să vă aruncați în cod și să construiți câteva componente de layout destul de populare și să vedeți cum se încadrează rândurile și coloanele aici. Pentru primul design, vom reproduce elementul din lista ecranului Chats WhatsApp. Ceva similar cu imaginea de mai jos.

Defalcarea aspectului # 1

Deci câte elemente sau vizualizări vedem? Poză de profil. Nume de utilizator. Ultimul mesaj al utilizatorului. Ora ultimului mesaj. Și numărul de mesaje necitite.

Permiteți să înfășurați toate acestea într-un recipient și să aveți trei secțiuni pentru copii: leftSection, middleSection și rightSection, una după alta pe orizontală.

leftSection va conține poza de profil.
middleSection va avea lastMessage sub userName.
rightSection va avea unreadMessageCount sub timpStamp.

Bine. A fost greu?
Poate la început, dar odată ce obțineți blocajul de rânduri și coloane, puteți să descărcați în mod natural machete în cap.

Timpul de a coda

Spre deosebire de majoritatea tutoriale de nivel începător, voi încerca întotdeauna să descompun codul meu în diferite clase și widgets. Acesta face codul super citibil.

main.dart

void main () => runApp (nou MyApp ());

clasa MyApp extinde StatelessWidget {
  // Acest widget este rădăcina aplicației dvs.
  @trece peste
  Construire widget (context BuildContext) {
    returnați MaterialApp (
      acasă: nou ChatItemScreen (), // apelarea chat_screen_item.dart
    );
  }
}

Sfat pentru începător: nu uitați să importați clasele pe care le veți utiliza. De exemplu, main.dart va importa chat_screen_item.dart care are clasa noastră ChatItemScreen.

chat_item_screen.dart

clasa ChatItemScreen extinde StatelessWidget {
  @trece peste
  Construire widget (context BuildContext) {
    înapoi nou Scaffold (
      appBar: nou AppBar (
        title: text nou („articol de chat”),
        backgroundColor: Colors.lightGreen,
      ),
      corp: nou ChatItem (), // apelarea chat_item.dart
    );
  }
}

Asta a fost doar pentru a vă începe, astfel încât să nu vă împiedicați cu pașii de bază de pornire. Acum trecem la codul principal. Clasa noastră ChatItem va returna un widget Container care are un copil Row. Acest copil Row va avea trei copii noi widgetSection, middleSection și rightSection pe care îl vom construi în curând.

chat_item.dart

clasa ChatItem extinde StatelessWidget {

  final leftSection = new Container ();
  final middleSection = nou Container ();
  final rightSection = nou Container ();

  @trece peste
  Construire widget (context BuildContext) {
    înapoi nou Scaffold (
    corp: Container nou (
      copil: Rând nou (
        copii:  [
          leftSection,
          middleSection,
          rightSection
        ],
      ),
    ),
  );

  }

}

Secțiunea din stânga

În secțiunea din stânga, avem nevoie de un CircleAvatar și avem și un mic widget frumos pentru asta.

final stangaSectiune = nou Container (
  copil: nou CircleAvatar (
    backgroundImage: NetworkImage nou (url),
    backgroundColor: Colors.lightGreen,
    raza: 24,0,
  ),
);

Secția de mijloc

Acum, în cadrul conținutului middleSection, creăm o coloană cu două widget-uri text care vor conține conținutul userName și lastMessage.

final middleSection = nou Container (
  copil: coloana nouă (
    copii:  [
      Text nou („Nume”),
      nou text („Bună ce?”),
    ],
  ),
);

Face treaba de a plasa widgeturi una după alta, dar arată foarte urât. E timpul să adăugați ceva de înfrumusețare.

final middleSection = nou Extins (
  copil: Container nou (
    padding: new EdgeInsets.only (stânga: 8.0),
    copil: coloana nouă (
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      copii:  [
        Text nou („Nume”,
          stil: nou TextStyle (
              culoare: Colors.black,
              fontWeight: FontWeight.w600,
              fontSize: 16.0,
          ),),
        Text nou („Bună whatsp?”, stil:
          TextStyle nou (culoare: Colors.grey),),
      ],
    ),
  ),
);
  • Extins: Deoarece această secțiune dorește tot spațiul disponibil disponibil, învelim întregul container în acest widget Extins. Fără aceasta, aspectul va arăta astfel -
  • Căptușeală: mai mult spațiu pentru a respira, vai.
  • TextStyle: Oferă stilul textului, cum ar fi culorile, fontSize, etc. La fel de mult ca CSS, la naiba.
  • Acum pot explica crossAxisAlignment și mainAxisAlignment, dar nu o pot explica mai bine decât acest videoclip. Asa ca v-as sugera sa invatati de la cei mai buni. (Consultați de la 2:00 la 7:30 pentru a obține o referință rapidă la subiectul la care ne aflăm)

Secțiunea dreapta

Aproape am terminat. Trebuie doar să construiți o altă coloană din două widget-uri. De această dată, widget-urile pentru copii vor fi un Textwidget pentru timestamp și un alt mic CircleAvatar pentru număr.

final rightSection = nou Container (
  copil: coloana nouă (
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    copii:  [
      Text nou („9:50”,
          stil: nou TextStyle (
            culoare: Colors.lightGreen,
          fontSize: 12.0),),
      nou CircleAvatar (
        backgroundColor: Colors.lightGreen,
        raza: 10,0,
        copil: nou Text („2”,
        stil: nou TextStyle (culoare: Colors.white,
        fontSize: 12.0),),
      )
    ],
  ),
);

Acum executa acest lucru frumos. Și este gata.

Vom împărți o altă structură doar pentru a ne asigura că obțineți blocajul?

Defalcarea aspectului # 2

Card de colecții Zomato

Avem așadar această simplă dispunere de card care are o coloană cu câteva widget-uri text care se suprapun unei imagini de fundal. Hmm .. ai spus că s-a suprapus? Deci asta înseamnă că folosim Stive aici?

DA, îl obțineți.

Așadar, în loc de secțiunea din stânga, mijloc sau dreapta, să împărțim acest aspect în backgroundImage și onTopContent.

@trece peste
Construire widget (context BuildContext) {

  returnare nou Container (
    capitonare: nou EdgeInsets.all (8.0),
    inaltime: 250,0,
    copil: nou Stack (
      copii:  [
        imagine de fundal,
        onTopContent
      ],
    ),
  );
}

Imagine de fundal

Acum imaginea de fundal va avea doar un Container cu o imagine de fundal și un filtru de culoare pentru a întuneca fundalul.

background finalImage = new Container (
    decorare: nou BoxDecoration (
      imagine: new DecorationImage (
        colorFilter: new ColorFilter.mode (
            Colors.black.withOpacity (0.6),
            BlendMode.luminosity),
        imagine: NetworkImage nou (url),
        se potrivesc: BoxFit.cover,
      ),
    ),
);

Pe conținut de top

Tu ce crezi? Rânduri sau coloane?

Ai inteles. Coluuuumns.

final onTopContent = nou Container (
  inaltime: 80,0,
  copil: coloană nouă (mainAxisSize: MainAxisSize.max,
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    crossAxisAlignment: CrossAxisAlignment.start,
    copii:  [
      nou text („În cursul acestei săptămâni”,
      stil: bigHeaderTextStyle),
      text nou („Cele mai populare restaurante din oraș săptămâna aceasta”,
        stil: descTextStyle),
      Container nou (
        inaltime: 2,0,
        latime: 150,0,
        culoare: Colors.redAccent,
      ),
      nou text („30 LOCURI”,
        stil: footerTextStyle),
      // Container nou ()
    ],
  ),
);

Acum nu vă mirați de stilurile pe care le-am folosit. Acestea nu sunt valorile implicite ale Flutter, știu că aveți erori. Toate stilurile pentru cardul zomato sunt definite aici.

Puteți găsi chiar întregul depozit GitHub pentru aceste machete aici.

În viitor, voi explora machete mai complexe pe care le puteți rupe la nivelul rădăcinii. Desigur, veți avea nevoie de mai multe widget-uri pentru machete mai complexe, dar Rândurile și Coloanele vor avea întotdeauna un rol în el undeva, așa că este important să aveți acest lucru în cap.

Citiți celelalte articole ale mele despre Flutter

Flutter-ul este proaspăt, iar acum îl descopăr și eu. Dacă găsiți ceva în neregulă cu codul sau abordarea mea, menționați-l în comentarii, mi-ar plăcea să îmbunătățesc.
Dacă ați învățat chiar și un lucru sau două, bateți mâinile de câte ori puteți să vă arătați sprijinul!
Salut lume, eu sunt Pooja Bhaumik. Un dezvoltator creativ și un designer logic. Mă poți găsi pe Linkedin sau mă urmărești pe GitHub sau mă urmărești pe Twitter? Dacă este prea social pentru tine, aruncă doar un e-mail la pbhaumik26@gmail.com dacă vrei să vorbești cu mine.