Öğeleri ekran genişliği / yüksekliğinin yüzdesine göre boyutlandırma


167

Bir öğeyi ekran boyutuna (genişlik / yükseklik) göre boyutlandırmanın basit (LayoutBuilder olmayan) bir yolu var mı? Örneğin: CardView genişliğini ekran genişliğinin% 65'i olarak nasıl ayarlayabilirim?

buildYöntemin içinde yapılamaz (açıkçası), bu nedenle sonradan inşa edilene kadar ertelenmesi gerekir. Böyle bir mantık koymak için tercih edilen bir yer var mı?


Sadece söylüyorum, bu genellikle iyi bir uygulama IMO değil, bu web tasarımı meselesi. En boy oranınız neredeyse her zaman aynı olduğundan (tabletler hariç), uygulamalarda boyutları tanımlamak için genellikle cihaz piksellerini ve widget'larınızı eklemek için Dolgular'ı kullanmanız gerekir.
leodriesch

10
Bir 1.5 yıl sonra, görünüşe göre bu o kadar da kötü bir fikir değil. Her ay daha tuhaf ve tuhaf en boy oranına sahip yeni telefonlar çıkıyor.
Farid

Yanıtlar:


184

FractionallySizedBoxayrıca faydalı olabilir. Ayrıca ekran genişliğini doğrudan dışarıdan okuyabilir ve buna MediaQuery.of(context).sizegöre boyutlu bir kutu oluşturabilirsiniz.

MediaQuery.of(context).size.width * 0.65

Düzenin ne olduğuna bakılmaksızın gerçekten ekranın bir parçası olarak boyutlandırmak istiyorsanız.


233

Bu, bahsedilen çözümlerden birkaçının uygulanmasını gösteren tamamlayıcı bir cevaptır.

KesirliSizeKutu

Tek bir widget'ınız varsa, FractionallySizedBoxdoldurulacak kullanılabilir alanın bir yüzdesini belirtmek için bir widget kullanabilirsiniz . Burada yeşil Container, mevcut genişliğin% 70'ini ve mevcut yüksekliğin% 30'unu dolduracak şekilde ayarlanmıştır.

KesirliSizeKutu
Widget myWidget() {
  return FractionallySizedBox(
    widthFactor: 0.7,
    heightFactor: 0.3,
    child: Container(
      color: Colors.green,
    ),
  );
}

Genişletilmiş

ExpandedEklendi bir eklendi bir sütunda ise üst üste olan ya da dikey yatay olarak ise, mevcut alanı doldurmak için izin verir. flexÖzelliği, onlara ağırlık vermek için birden çok widget ile kullanabilirsiniz . Burada yeşil Container, genişliğin% 70'ini ve sarı Container, genişliğin% 30'unu kaplar.

Genişletilmiş

Dikey yapmak istiyorum, o zaman sadece değiştirmek Rowile Column.

Widget myWidget() {
  return Row(
    children: <Widget>[
      Expanded(
        flex: 7,
        child: Container(
          color: Colors.green,
        ),
      ),
      Expanded(
        flex: 3,
        child: Container(
          color: Colors.yellow,
        ),
      ),
    ],
  );
}

Ek kod

İşte main.dartreferans için kod.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("FractionallySizedBox"),
        ),
        body: myWidget(),
      ),
    );
  }
}

// replace with example code above
Widget myWidget() {
  return ...
}

121

Bu biraz daha net olabilir:

double width = MediaQuery.of(context).size.width;

double yourWidth = width * 0.65;

Umarım bu sorununuzu çözmüştür.


16

Toplamı istediğiniz yüzdelere ulaşan esnek değerlere sahip Esnek veya Genişletilmiş alt öğeler içeren bir Sütun / Satır oluşturabilirsiniz .

AspectRatio widget'ını da yararlı bulabilirsiniz .


12

Bunu yapmanın birçok yolu var.

1. MediaQuery'yi kullanma: Uygulama çubuğu, araç çubuğu dahil olmak üzere cihazınızın tam ekranına döner

 Container(
        width: MediaQuery.of(context).size.width * 0.50,
        height: MediaQuery.of(context).size.height*0.50, 
        color: Colors.blueAccent[400],
 )

görüntü açıklamasını buraya girin


2. Genişletilmiş Kullanımı: Genişliği / yüksekliği oran olarak ayarlayabilirsiniz

 Container(
        height: MediaQuery.of(context).size.height * 0.50,
        child: Row(
          children: <Widget>[
            Expanded(
              flex: 70,
              child: Container(
                color: Colors.lightBlue[400],
              ),
            ),
            Expanded(
              flex: 30,
              child: Container(
                color: Colors.deepPurple[800],
              ),
            )
          ],
        ),
    )

görüntü açıklamasını buraya girin



3. Diğer gibi esnek ve AspectRatio ve FractionallySizedBox


10

Önce ekranın boyutunu alın.

Size size = MediaQuery.of(context).size;

Bundan sonra , ekran genişliğinin% 50'sini elde etmek için widthonu alıp çarpabilirsiniz 0.5.

double width50 = size.width * 0.5;

Ancak height, kullandığımızda varsayılan olarak genellikle sorun ortaya çıkar

double screenHeight = size.height;

Aldığımız yükseklik, StatusBar+ notch+ AppBaryüksekliği içeren global yüksekliktir. Bu nedenle, cihazın sol yüksekliğini elde etmek için, paddingyüksekliği ( StatusBar+ notch) ve AppBaryüksekliği toplam yükseklikten çıkarmamız gerekiyor. İşte bunu nasıl yapıyoruz.

double abovePadding = MediaQuery.of(context).padding.top;
double appBarHeight = appBar.preferredSize.height;
double leftHeight = screenHeight - abovePadding - appBarHeight;

Şimdi ekranımızın% 50 yüksekliğini elde etmek için aşağıdakileri kullanabiliriz.

double height50 = leftHeight * 0.5

1
Bu benim hayatımı kurtardı. Yine de, (abovePadding tarafından kullanılan) bağlamın appBar'dan biri olması gerektiğini belirtmeliyim.
Doktor


7

MediaQuery'yi widget'ınızın mevcut bağlamıyla kullanabilir ve bundan double width = MediaQuery.of(context).size.width double height = MediaQuery.of(context).size.height sonra bunun gibi genişlik veya yükseklik elde edebilir, istediğiniz yüzde ile çarpabilirsiniz.


4

AppBar'ı ve dolguyu hariç tutan yüksekliği elde etmek için kullanabileceğiniz kısıtlamalar verecek LayoutBuilder Widget'ı kullanın. Sonra bir SizedBox kullanın ve LayoutBuilder'daki kısıtlamaları kullanarak genişliği ve yüksekliği sağlayın

return LayoutBuilder(builder: (context2, constraints) {
  return Column(
    children: <Widget>[
      SizedBox(
        width: constraints.maxWidth,
        height: constraints.maxHeight,
        ...

3

GridView kullanıyorsanız Ian Hickson'ın çözümü gibi bir şey kullanabilirsiniz.

crossAxisCount: MediaQuery.of(context).size.width <= 400.0 ? 3 : MediaQuery.of(context).size.width >= 1000.0 ? 5 : 4
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.