MediaQuery — обект във Flutter, предоставящ информация за текущата медийна среда: размер на екрана, ориентация на устройството, плътност на пикселите, системни отстъпи и размер на шрифта. MediaQueryData — контейнер за всички тези метрики, достъпен чрез MediaQuery.of(context). Според официалната документация на Flutter (2026), MediaQuery е основата на адаптивния дизайн: чрез него се определя дали да се показва мобилно или таблетно оформление, изчисляват се отстъпите за safe area и се избират размерите на елементите спрямо екрана.
Основни точки
MediaQuery — е уиджет и клас във Flutter, който предоставя данни за медийната среда на приложението. MediaQuery обвива цялото приложение в коренния уиджет MaterialApp или CupertinoApp и всеки дъщерен уиджет може да получи достъп до тези данни чрез MediaQuery.of(context).
Когато Flutter стартира приложението, той създава екземпляр на MediaQueryData, съдържащ всички метрики на текущото устройство. Тези данни се актуализират автоматично при промени: завъртане на устройството, промяна на размера на прозореца (на десктоп), поява на клавиатура или промяна на системните настройки за достъпност. MediaQuery възстановява поддървото на уиджетите при всяка промяна на данни, осигурявайки реактивна адаптация на интерфейса.
MediaQueryData включва: size (размер на екрана), devicePixelRatio (плътност на пикселите), textScaleFactor (мащаб на шрифта от системни настройки), viewInsets (област, покрита от клавиатура), viewPadding (системни отстъпи), orientation (ориентация) и platformBrightness (светла или тъмна тема).
Заключение: MediaQuery — централен източник на информация за устройството във Flutter. Достъпът до MediaQuery.of(context) е първата стъпка в изграждането на всеки адаптивен интерфейс.
MediaQueryData съдържа десетки свойства, но най-често използваните са тези, които влияят на изграждането на оформлението. Нека разгледаме ключовите.
MediaQuery.of(context).size връща обект Size с ширина и височина на екрана в логически пиксели (device-independent pixels, dip). Тези стойности не вземат предвид системните отстъпи. За изчисленията на адаптивни оформления, size е основната метрика: на нейна база се определят breakpoints за мобилно, таблетно и десктоп оформление.
ViewPadding — отстъпи, които системата резервира за лентата за състояние, прореза (изрез на екрана), системния навигационен панел и индикатора за начало (на iOS). Без отчитането на тези отстъпи, съдържанието може да се окаже под системните елементи. MediaQuery.of(context).padding връща EdgeInsets, който трябва да се приложи като padding към коренния контейнер на страницата.
ViewInsets — област на екрана, покрита от софтуерната клавиатура. За полета за въвеждане е критично да се следи viewInsets.bottom, за да се повдигне съдържанието над клавиатурата. Flutter обработва това автоматично в scaffold, но за персонализирани оформления трябва да се използва директно MediaQuery.of(context).viewInsets.
Orientation — портретна (portrait) или пейзажна (landscape) ориентация. Определя се чрез сравняване на ширина и височина: ако ширината е по-малка от височината — portrait, иначе — landscape. В производствен код ориентацията се използва за превключване между вертикално и хоризонтално подреждане на елементите.
Заключение: четири ключови свойства — size, viewPadding, viewInsets и orientation — покриват 90% от задачите за адаптивен дизайн. Останалите свойства (textScaleFactor, platformBrightness, devicePixelRatio) се използват за специфични сценарии.
MediaQuery — основата на адаптивния дизайн във Flutter. Чрез него се определят breakpoints, оформлението се променя в зависимост от размера на екрана и отстъпите се коригират за различни устройства.
Типичен сценарий: мобилно приложение трябва да покаже списък с продукти. На телефон (ширина < 600dp) — една колона. На таблет (ширина 600–900dp) — две колони. На десктоп (ширина > 900dp) — три колони. MediaQuery.of(context).size.width позволява динамичен избор на броя колони без отделен екран за всеки форм фактор.
Втори сценарий: отчитане на system gesture insets на съвременните устройства. На iPhone с Dynamic Island или Android с gesture navigation, системните отстъпи заемат част от екрана. MediaQuery.of(context).padding връща правилни стойности за всеки тип устройство, а Scaffold ги прилага автоматично чрез body. За персонализирани уиджети, padding трябва да се предаде изрично от MediaQuery.
Трети сценарий: адаптиране към системните настройки за достъпност. MediaQuery.of(context).textScaleFactor показва колко е увеличил потребителят шрифта в настройките. При textScaleFactor > 1.3 оформлението може да се счупи — дълги текстове излизат извън границите на картите. Адаптивните оформления трябва да вземат предвид това и при необходимост да превключат към по-просто оформление.
Заключение: MediaQuery — не просто източник на метрики, а инструмент за изграждане на наистина адаптивни интерфейси. Използвайте го за breakpoints, safe area и отчитане на достъпността.
Пример 1 демонстрира получаване на размера на екрана и прилагане на breakpoints за избор на брой колони.
int getColumnCount(BuildContext context) {
final width = MediaQuery.of(context).size.width;
if (width > 900) return 3;
if (width > 600) return 2;
return 1;
}
Горният пример показва функция за избор на броя колони на базата на ширината на екрана. Breakpoints 600 и 900 съответстват на общоприетите стандарти на Material Design за телефони, таблети и десктоп.
Пример 2 — използване на MediaQuery с viewPadding за правилно позициониране на съдържанието с отчитане на системните отстъпи.
Widget build(BuildContext context) {
final padding = MediaQuery.of(context).padding;
return Padding(
padding: EdgeInsets.only(
top: padding.top,
left: padding.left,
right: padding.right,
),
child: const MyContent(),
);
}
В този пример padding обвива съдържанието в Padding, използвайки системните отстъпи. top отчита лентата за състояние и прореза, left/right — безопасните зони. bottom не е включен, тъй като Scaffold обикновено сам обработва долната навигация.
Пример 3 — определяне на ориентацията и промяна на подреждането на елементите.
Widget build(BuildContext context) {
final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
return isPortrait
? const Column(
children: [HeaderBanner(), ContentList()],
)
: const Row(
children: [HeaderBanner(), ContentList()],
);
}
В портретен режим елементите са подредени вертикално (Column), в пейзажен — хоризонтално (Row). Този подход осигурява най-доброто използване на пространството при завъртане на устройството.
Заключение: MediaQuery — основният инструмент за изграждане на адаптивни оформления. Винаги вземайте предвид системните отстъпи, breakpoints и ориентацията при разработка на Flutter интерфейси.
Грешка 1: извикване на MediaQuery.of(context) извън контекста, където е зададен MediaQuery. Ако уиджетът се намира над MediaQuery в дървото, извикването води до грешка по време на изпълнение. Решение: винаги извиквайте MediaQuery.of(context) вътре в уиджети, обвити в MaterialApp или CupertinoApp, където MediaQuery е зададен като коренен уиджет.
Грешка 2: забравяне на safe area. Разработчиците използват MediaQuery.size за позициониране на елементи без отчитане на системните отстъпи. На устройства с прорез или gesture navigation, съдържанието попада под лентата за състояние. Решение: извадете MediaQuery.of(context).padding от координатите за позициониране.
Грешка 3: твърда връзка с размерите. Използването на MediaQuery.of(context).size.width за задаване на точни размери на елементи (width: size.width * 0.3) работи само на устройства с един форм фактор. На десктоп или таблет оформлението изглежда неестествено. Решение: използвайте breakpoints в комбинация с Expanded и Flexible за гъвкаво оформление, а не твърди проценти.
Грешка 4: игнориране на textScaleFactor. При увеличение на системния шрифт от потребителя, интерфейсът може да се счупи — текстовете излизат извън границите на контейнерите. Решение: проверявайте MediaQuery.of(context).textScaleFactor и при стойности над 1.3 превключете оформлението на по-проста версия с превъртане.
Заключение: MediaQuery — мощен, но деликатен инструмент. Вземайте предвид системните отстъпи, ориентацията и настройките за достъпност, за да изглежда интерфейсът коректно на всички устройства.
Често задавани въпроси
MediaQuery.size — общ размер на екрана или прозореца на приложението в логически пиксели. MediaQuery.viewInsets — област, покрита от системната клавиатура. За изчисляване на достъпното пространство без клавиатура: size.height - viewInsets.bottom.
LayoutBuilder дава размерите на родителския контейнер, а не на целия екран. Използвайте LayoutBuilder, когато размерите на уиджета зависят от наличното пространство в конкретен родител, а MediaQuery — когато са необходими глобални метрики на екрана.
Автоматично. При завъртане на устройството Flutter актуализира MediaQueryData и възстановява поддървото. Свойството orientation се променя и builder-ът на всички абонирани уиджети се извиква с нови данни.
Да. Чрез обвиване на част от уиджетите в MediaQuery с презаписани данни чрез MediaQuery.removePadding, MediaQuery.removeViewInsets или MediaQuery с други Data. Това се прилага за вграждане в iframe или режими за преглед.
За тестове Flutter предоставя setScreenSize и обвивка на MediaQuery в тестовата среда. За уиджет тестове, обвийте тествания компонент в MaterialApp или MediaQuery с тестови данни, за да контролирате размерите на екрана.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също