Flutter Responsive Layout

date 27 Apr 2021
date Lev Yasin
date 24
date Mobile App
Flutter Responsive Layout

Flutter, sebagai kerangka kerja pengembangan aplikasi lintas platform, mendukung perangkat dengan ukuran layar yang sangat bervariasi : Flutter dapat berjalan di perangkat sekecil jam tangan pintar hingga perangkat seperti TV besar. Selalu menjadi tantangan untuk menyesuaikan aplikasi Anda dengan berbagai ukuran layar dan kepadatan piksel menggunakan basis kode yang sama.

Tidak ada aturan tegas untuk mendesain tata letak responsif di Flutter. Pada artikel ini, kita akan menunjukkan kepada Anda beberapa pendekatan yang dapat Anda ikuti saat mendesain tata letak seperti itu.

Sebelum melanjutkan ke membangun tata letak responsif di Flutter, kita ingin menjelaskan cara Android dan iOS menangani tata letak untuk ukuran layar yang berbeda secara native.

Seperti yang kita katakan sebelumnya, kita akan membahas konsep penting yang diperlukan untuk mengembangkan tata letak responsif , dan kemudian, itu adalah pilihan Anda bagaimana tepatnya Anda ingin menerapkannya di aplikasi Anda.

1. MediaQuery

Anda dapat menggunakan MediaQuery untuk mengambil ukuran (lebar / tinggi) dan orientasi (potret / lanskap) layar.

Contohnya adalah sebagai berikut:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    Orientation orientation = MediaQuery.of(context).orientation;

    return Scaffold(
      body: Container(
        color: CustomColors.android,
        child: Center(
          child: Text(
            'View\n\n' +
                '[MediaQuery width]: ${screenSize.width.toStringAsFixed(2)}\n\n' +
                '[MediaQuery orientation]: $orientation',
            style: TextStyle(color: Colors.white, fontSize: 18),
          ),
        ),
      ),
    );
  }
}

2. LayoutBuilder

Dengan menggunakan kelas LayoutBuilder , Anda bisa mendapatkan objek BoxConstraints , yang dapat digunakan untuk menentukan maxWidth dan maxHeight widget.

INGAT: Perbedaan utama antara MediaQuerydan LayoutBuilderadalah bahwa MediaQuery menggunakan konteks layar lengkap dan bukan hanya ukuran widget tertentu Anda, sedangkan LayoutBuilder dapat menentukan lebar dan tinggi maksimum widget tertentu.

Contoh yang mendemonstrasikan hal ini adalah sebagai berikut:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;

    return Scaffold(
      body: Row(
        children: [
          Expanded(
            flex: 2,
            child: LayoutBuilder(
              builder: (context, constraints) => Container(
                color: CustomColors.android,
                child: Center(
                  child: Text(
                    'View 1\n\n' +
                        '[MediaQuery]:\n ${screenSize.width.toStringAsFixed(2)}\n\n' +
                        '[LayoutBuilder]:\n${constraints.maxWidth.toStringAsFixed(2)}',
                    style: TextStyle(color: Colors.white, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            flex: 3,
            child: LayoutBuilder(
              builder: (context, constraints) => Container(
                color: Colors.white,
                child: Center(
                  child: Text(
                    'View 2\n\n' +
                        '[MediaQuery]:\n ${screenSize.width.toStringAsFixed(2)}\n\n' +
                        '[LayoutBuilder]:\n${constraints.maxWidth.toStringAsFixed(2)}',
                    style: TextStyle(color: CustomColors.android, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

3. OrientationBuilder

Untuk menentukan orientasi widget saat ini, Anda dapat menggunakan kelas OrientationBuilder .

INGAT: Ini berbeda dari orientasi perangkat yang dapat Anda ambil dengan menggunakan MediaQuery.

Contoh yang mendemonstrasikan hal ini adalah sebagai berikut:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Orientation deviceOrientation = MediaQuery.of(context).orientation;

    return Scaffold(
      body: Column(
        children: [
          Expanded(
            flex: 2,
            child: Container(
              color: CustomColors.android,
              child: OrientationBuilder(
                builder: (context, orientation) => Center(
                  child: Text(
                    'View 1\n\n' +
                        '[MediaQuery orientation]:\n$deviceOrientation\n\n' +
                        '[OrientationBuilder]:\n$orientation',
                    style: TextStyle(color: Colors.white, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            flex: 3,
            child: OrientationBuilder(
              builder: (context, orientation) => Container(
                color: Colors.white,
                child: Center(
                  child: Text(
                    'View 2\n\n' +
                        '[MediaQuery orientation]:\n$deviceOrientation\n\n' +
                        '[OrientationBuilder]:\n$orientation',
                    style: TextStyle(color: CustomColors.android, fontSize: 18),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

4. Expanded and Flexible

Widget yang sangat berguna di dalam a Columnatau a Roware Expandeddan Flexible. The Expanded widget memperluas anak dari Row, Column, atau Flex sehingga anak mengisi ruang yang tersedia, sedangkan Fleksibel tidak perlu harus mengisi seluruh ruang yang tersedia.

Contoh yang menunjukkan berbagai kombinasi Expandeddan Flexibleadalah sebagai berikut:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Column(
          children: [
            Row(
              children: [
                ExpandedWidget(),
                FlexibleWidget(),
              ],
            ),
            Row(
              children: [
                ExpandedWidget(),
                ExpandedWidget(),
              ],
            ),
            Row(
              children: [
                FlexibleWidget(),
                FlexibleWidget(),
              ],
            ),
            Row(
              children: [
                FlexibleWidget(),
                ExpandedWidget(),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class ExpandedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        decoration: BoxDecoration(
          color: CustomColors.android,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Text(
            'Expanded',
            style: TextStyle(color: Colors.white, fontSize: 24),
          ),
        ),
      ),
    );
  }
}

class FlexibleWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Flexible(
      child: Container(
        decoration: BoxDecoration(
          color: CustomColors.androidAccent,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Text(
            'Flexible',
            style: TextStyle(color: CustomColors.android, fontSize: 24),
          ),
        ),
      ),
    );
  }
}

5. FractionallySizedBox

The FractionallySizedBox widget membantu untuk ukuran anak untuk sebagian kecil dari total ruang yang tersedia. Ini sangat berguna di dalam Expandedatau Flexiblewidget.

Contohnya adalah sebagai berikut:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 0.4),
              ],
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 0.6),
              ],
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 0.8),
              ],
            ),
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                FractionallySizedWidget(widthFactor: 1.0),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class FractionallySizedWidget extends StatelessWidget {
  final double widthFactor;
  FractionallySizedWidget({@required this.widthFactor});

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: FractionallySizedBox(
        alignment: Alignment.centerLeft,
        widthFactor: widthFactor,
        child: Container(
          decoration: BoxDecoration(
            color: CustomColors.android,
            border: Border.all(color: Colors.white),
          ),
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Text(
              '${widthFactor * 100}%',
              style: TextStyle(color: Colors.white, fontSize: 24),
            ),
          ),
        ),
      ),
    );
  }
}

6. AspectRatio

Anda dapat menggunakan widget AspectRatio untuk mengukur anak dengan rasio aspek tertentu. Widget ini pertama-tama mencoba lebar terbesar yang diizinkan oleh batasan tata letak, lalu memutuskan tingginya dengan menerapkan rasio aspek yang diberikan ke lebarnya.

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: Column(
          children: [
            AspectRatioWidget(ratio: '16 / 9'),
            AspectRatioWidget(ratio: '3 / 2'),
          ],
        ),
      ),
    );
  }
}

class AspectRatioWidget extends StatelessWidget {
  final String ratio;

  AspectRatioWidget({@required this.ratio});

  @override
  Widget build(BuildContext context) {
    return AspectRatio(
      aspectRatio: Fraction.fromString(ratio).toDouble(),
      child: Container(
        decoration: BoxDecoration(
          color: CustomColors.android,
          border: Border.all(color: Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Center(
            child: Text(
              'AspectRatio - $ratio',
              style: TextStyle(color: Colors.white, fontSize: 24),
            ),
          ),
        ),
      ),
    );
  }
}

Kami telah mempelajari sebagian besar konsep penting yang diperlukan untuk membuat tata letak responsif di Flutter, kecuali satu.

Mari pelajari konsep terakhir sambil membuat contoh aplikasi responsif.

 

lev_yasin.png

Lev Yasin

Instruktur Web Programming Mataweb

Sangat tertarik dengan dunia Pemrograman Web & Mobile, saat ini fokus pada bagian Backend Web Developer, menggunakan PHP sebagai bahasa pemrograman utama, biasanya saya menggunakan Laravel.

Artikel Terkait

Halo, ada yang bisa kami bantu?