Flutter Responsive Tasarım
Tags: flutter, dart, responsive, design
Published: 2022-06-27 22:08:00

## Responsive
Uygulamanın düzeninin mevcut cihazın boyutuna göre uyarlanabilmesi `responsive` bir uygulama olduğu anlamına gelir. Bu durum kullanıcı pencereyi yeniden boyutlandırdığında ya da cihazın yönünü değiştirdiğinde UI'ın yeniden düzenleneceği anlamına gelir. Bu sayede de uygulamanız birden fazla cihazda çalışabilir durumda olur.


**Responsive Tasarım ile Flutter uygulaması oluşturma konusunda iki temel yaklaşım vardır:**

**1. Build fonksiyonunda MediaQuery.of() methodunu kullanmak**

**2. LayoutBuilder sınıfını kullanmak**

**1. MediaQuery.of() methodu**
Sabit yükseklik ve genişlik değerleri kullanmak farklı cihazlarda overflowing (taşma) hatalarına neden olur. Bu nedenle widget'larınızı tasarlarken sabit genişlik ve yükseklik değerleri kullanmaktan kaçınarak oranları (ratios) kullanın. 

ratio:

```
Height in Design / Width in Design = 
Height in Device / Width in Design

Tasarım yüksekliği / Tasarım genişliği = 
Cihaz yüksekliği / Tasarım genişliği

```


**Cihaza duyarlı yükseklik ve genişlik nasıl hesaplanır?**

**MediaQuery** 

Flutter uygulamamızın çalıştığı cihazın yüksekliğini ve genişliğini almak için cihazın boyut bilgisine erişmemizi sağlayan MediaQuery'den faydalanabiliriz.


**Flutter da responsive genişlik değeri hesaplama**

```
final MediaQueryData mediaQueryData = MediaQuery.of(context);

final double deviceHeight = mediaQueryData.size.height;

final double deviceWidth = mediaQueryData.size.width;
```


Cihazın genişliğini öğrendikten sonra yan yana iki kart gösterdiğimiz bir uygulamamız varsa ve kartın responsive genişliğini hesaplamak istiyorsak:

```
final double responsiveWidth =
     (deviceWidth / 2) - padding - (spaceBetween / 2); 
```
formülünü kullanabiliriz.

Temel olarak burada genişliği hesaplamak için cihazın toplam genişlik değerini ikiye bölüp padding alanından çıkartıyoruz.

**Flutter da responsive yükseklik değeri hesaplama**

Önceki aşamada elde ettiğimiz responsive  genişlik değerini kullanarak responsive yükseklik değerini aşağıdaki gibi elde edebiliriz.

```
final double responsiveHeight =
    (heightInDesign / widthInDesign) * responsiveWidth;
```

Örnek kod:

```
final MediaQueryData mediaQueryData = MediaQuery.of(context);
final double deviceWidth = mediaQueryData.size.width;

final double heightInDesign = 260;
final double widthInDesign = 170;
final double padding = 18;
final double spaceBetween = 24;

final double responsiveWidth =
    (deviceWidth / 2) - padding - (spaceBetween / 2);

final double responsiveHeight =
    (heightInDesign / widthInDesign) * responsiveWidth;

return SingleChildScrollView(
  child: Padding(
    padding: EdgeInsets.symmetric(
      horizontal: padding,
    ),
    child: Row(
      children: [
        Container(
          height: responsiveHeight,
          width: responsiveWidth,
          color: Colors.grey,
          child: Column(
            children: [
              //card content for text and image
            ],
          ),
        ),
        SizedBox(
          width: spaceBetween,
        ),
        Container(
          height: responsiveHeight,
          width: responsiveWidth,
          color: Colors.grey,
          child: Column(
            children: [
              //card content for text and image
            ],
          ),
        )
      ],
    ),
  ),
);
```

**2. LayoutBuilder Class**

Parent widget'ın boyutuna bağlı olan bir widget ağacı oluşturur.

Parent child'ın boyutunu sınırlandırdığında ve child'ın gerçek boyutuna bağlı olmadığında kullanışlıdır. LayoutBuilder'ın son boyutu child'ın boyutuyla eşleşir.


```
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blueGrey,
      body: LayoutBuilder(
        builder: (context, constraints) {
          return GridView.count(
            crossAxisCount: constraints.maxWidth < 800 ? 1 : 2,
            childAspectRatio: 1.7,
            padding: const EdgeInsets.all(16),
            crossAxisSpacing: 16,
            mainAxisSpacing: 16,
            children: const [
              Card(),
              Card(),
              Card(),
              Card(),
            ],
          );
        }
      ),
    );
  }
}
```

https://www.youtube.com/watch?v=9d0zUBHHY4o&t=4s



örnek kod:

```
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatelessWidget(),
    );
  }
}

class MyStatelessWidget extends StatelessWidget {
  const MyStatelessWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('LayoutBuilder Example')),
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          if (constraints.maxWidth > 600) {
            return _buildWideContainers();
          } else {
            return _buildNormalContainer();
          }
        },
      ),
    );
  }

  Widget _buildNormalContainer() {
    return Center(
      child: Container(
        height: 100.0,
        width: 100.0,
        color: Colors.red,
      ),
    );
  }

  Widget _buildWideContainers() {
    return Center(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Container(
            height: 100.0,
            width: 100.0,
            color: Colors.red,
          ),
          Container(
            height: 100.0,
            width: 100.0,
            color: Colors.yellow,
          ),
        ],
      ),
    );
  }
}

```

Responsive bir kullanıcı arayüzü oluşturmak için diğer faydalı widget'lar ve sınıflar:

AspectRatio
CustomSingleChildLayout
CustomMultiChildLayout
FittedBox
FractionallySizedBox
LayoutBuilder
MediaQuery
MediaQueryData
OrientationBuilder



Resources:
https://api.flutter.dev/flutter/widgets/MediaQuery/of.html
https://docs.flutter.dev/development/ui/layout/adaptive-responsive
https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html
https://stacksecrets.com/flutter/learn-to-make-responsive-design-in-flutter