[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"technologies":3,"\u002Fopen-source\u002Fflutter-adaptive-layout":167},[4,10,15,21,26,32,38,43,48,53,58,63,68,73,77,82,87,92,97,103,108,113,118,123,128,133,138,143,147,152,157,162],{"title":5,"description":6,"slug":7,"category":8,"icon":9},"Android","Todas las apps que entregamos llegan a Android: APIs de plataforma, ejecución en segundo plano, permisos y los requisitos de tienda que traen consigo.","android","framework","logos:android-icon",{"title":11,"description":12,"slug":13,"category":8,"icon":14},"Angular","El framework de frontend en el que trabajamos cuando un producto ya es Angular: una estructura con todo incluido que encaja en apps grandes y de vida larga.","angular","logos:angular-icon",{"title":16,"description":17,"slug":18,"category":19,"icon":20},"Dart","El lenguaje en el que está escrita cada app Flutter que entregamos: null safety robusto, pattern matching de verdad y un compilador que apunta a nativo y a la web.","dart","language","logos:dart",{"title":22,"description":23,"slug":24,"category":8,"icon":25},"Django","El framework de Python que usamos cuando un producto necesita administración, autenticación y un modelo de datos real desde el primer día.","django","logos:django-icon",{"title":27,"description":28,"slug":29,"category":30,"icon":31},"Docker","Cada servicio que construimos se publica como contenedor, así que lo que corre en un portátil, en CI y en producción es un solo artefacto y no tres.","docker","infrastructure","logos:docker-icon",{"title":33,"description":34,"slug":35,"category":36,"icon":37},"Fastlane","La automatización de releases móviles: firma, builds y subidas a las tiendas desde CI, no desde el portátil de un ingeniero el día del lanzamiento.","fastlane","tools","logos:fastlane",{"title":39,"description":40,"slug":41,"category":8,"icon":42},"Flutter","Nuestro stack móvil principal desde 2018: una base de código Dart que llega a iOS, Android, web y escritorio sin un equipo por plataforma.","flutter","logos:flutter",{"title":44,"description":45,"slug":46,"category":36,"icon":47},"Git","Todos los proyectos que tocamos viven en Git: pull requests revisadas, CI en cada rama y un historial que sigue teniendo sentido meses después.","git","logos:git-icon",{"title":49,"description":50,"slug":51,"category":19,"icon":52},"Go","Nuestro lenguaje de backend para APIs en tiempo real y servicios bajo carga: binarios pequeños, compilaciones rápidas y concurrencia que sigue siendo legible.","go","logos:gopher",{"title":54,"description":55,"slug":56,"category":30,"icon":57},"Google Cloud","La nube donde corren nuestras cargas de producción: Kubernetes gestionado, almacenamiento y red, sin servidores hechos a mano que nadie quiere mantener.","gcp","logos:google-cloud",{"title":59,"description":60,"slug":61,"category":36,"icon":62},"Gradle","El sistema de build por el que pasa cada release de Android: product flavours, configuraciones de firma y el cableado de dependencias bajo una app Flutter.","gradle","logos:gradle",{"title":64,"description":65,"slug":66,"category":30,"icon":67},"Helm","Cómo empaquetamos un despliegue de Kubernetes: servicio, configuración, secretos e ingress como una unidad versionada que se puede promover y revertir.","helm","logos:helm",{"title":69,"description":70,"slug":71,"category":19,"icon":72},"Kotlin","A lo que recurrimos cuando una app Flutter necesita Android de verdad por debajo: platform channels, trabajo en segundo plano e integraciones con SDK nativos.","kotlin","logos:kotlin-icon",{"title":74,"description":75,"slug":76,"category":8,"icon":72},"Kotlin Multiplatform","Compartir la lógica de negocio entre iOS y Android mientras cada plataforma conserva su UI nativa: la alternativa cuando Flutter no encaja.","kmp",{"title":78,"description":79,"slug":80,"category":30,"icon":81},"Kubernetes","Cómo ejecutamos servicios en producción: despliegues con Helm, rollouts reversibles y escalado que no necesita a nadie a las 3 de la mañana.","kubernetes","logos:kubernetes",{"title":83,"description":84,"slug":85,"category":30,"icon":86},"NATS","Mensajería ligera entre servicios: publicación\u002Fsuscripción y petición\u002Frespuesta sin el peso operativo de un clúster de broker completo.","nats","logos:nats-icon",{"title":88,"description":89,"slug":90,"category":8,"icon":91},"Nuxt","Vue con renderizado en servidor, enrutado y SEO resueltos: así hacemos sitios y apps web que deben ser rápidas e indexables en la primera carga.","nuxt","logos:nuxt-icon",{"title":93,"description":94,"slug":95,"category":19,"icon":96},"PHP","Donde trabajamos con un backend PHP ya existente: extenderlo, integrarse con él y construir los clientes móviles y web a los que tiene que servir.","php","logos:php",{"title":98,"description":99,"slug":100,"category":101,"icon":102},"PostgreSQL","Nuestra base de datos por defecto, salvo que un producto dé una razón concreta para no usarla: del diseño del esquema al ajuste de índices.","postgres","database","logos:postgresql",{"title":104,"description":105,"slug":106,"category":19,"icon":107},"Python","Nuestro lenguaje para backends, trabajo con datos e integraciones de IA, incluidos los bindings de Python que publicamos para nuestras propias herramientas en Rust.","python","logos:python",{"title":109,"description":110,"slug":111,"category":8,"icon":112},"React","La librería de frontend en la que trabajamos cuando un producto ya es React: componentes, hooks y el ecosistema que ha crecido a su alrededor.","react","logos:react",{"title":114,"description":115,"slug":116,"category":101,"icon":117},"Redis","Donde ponemos los datos que tienen que ser rápidos y se pueden reconstruir: cachés, sesiones, límites de tasa y las colas tras las rutas lentas de un producto.","redis","logos:redis",{"title":119,"description":120,"slug":121,"category":19,"icon":122},"Ruby","El lenguaje de nuestra automatización de releases móviles: lanes de Fastlane, acciones a medida y el pegamento de CI que sube builds a las tiendas.","ruby","logos:ruby",{"title":124,"description":125,"slug":126,"category":19,"icon":127},"Rust","A donde vamos cuando importan tanto el rendimiento como la corrección: renderizado de documentos, herramientas de CLI y servicios que tienen que ser rápidos y predecibles.","rust","simple-icons:rust",{"title":129,"description":130,"slug":131,"category":101,"icon":132},"SQLite","La base de datos que viaja dentro de la app: cachés locales, almacenamiento offline-first y todo lo que tiene que seguir funcionando sin red.","sqlite","logos:sqlite",{"title":134,"description":135,"slug":136,"category":8,"icon":137},"Strapi","Un CMS headless para cuando los editores necesitan ser dueños del contenido: una administración de verdad y una API limpia, sin construirlas desde cero.","strapi","logos:strapi-icon",{"title":139,"description":140,"slug":141,"category":19,"icon":142},"Swift","A lo que recurrimos cuando una app Flutter necesita iOS de verdad por debajo: platform channels, integraciones con SDK nativos, widgets y App Clips.","swift","logos:swift",{"title":144,"description":145,"slug":146,"category":8,"icon":142},"SwiftUI","El framework de UI de Apple, donde construimos las superficies nativas que una app Flutter no puede tener: widgets, App Clips y extensiones.","swiftui",{"title":148,"description":149,"slug":150,"category":8,"icon":151},"Tailwind CSS","Cómo damos estilo a cada frontend que construimos: clases de utilidad y design tokens en lugar de una hoja de estilos que solo crece y nunca se borra.","tailwind","logos:tailwindcss-icon",{"title":153,"description":154,"slug":155,"category":19,"icon":156},"TypeScript","Lo predeterminado para todo lo que escribimos para el navegador y para servicios Node: tipos que detectan errores de integración antes de llegar a una revisión.","typescript","logos:typescript-icon",{"title":158,"description":159,"slug":160,"category":8,"icon":161},"Vue","Nuestro framework de frontend para paneles de administración, cuadros de mando y apps web que deben seguir siendo mantenibles durante años.","vue","logos:vue",{"title":163,"description":164,"slug":165,"category":36,"icon":166},"Whisper","El modelo de reconocimiento de voz de código abierto de OpenAI: el motor de transcripción detrás de la entrada por voz, que funciona como servicio de backend y también en el propio dispositivo.","whisper","simple-icons:openai",{"id":168,"title":169,"body":170,"description":1003,"extension":1004,"links":1005,"meta":1009,"metaDescription":1010,"metaTitle":1011,"navigation":714,"ogDescription":1012,"path":1013,"repository":1014,"seo":1018,"slug":1017,"stem":1019,"technologies":1020,"updated":1021,"__hash__":1022,"stats":1023},"open_source_es\u002Fopen-source\u002Fflutter-adaptive-layout.md","Flutter Adaptive Layout",{"type":171,"value":172,"toc":990},"minimark",[173,178,182,198,201,219,223,244,417,420,428,434,438,503,507,514,595,605,609,614,623,627,630,634,647,651,654,658,661,683,690,693,798,807,966,972,982,986],[174,175,177],"h2",{"id":176},"el-problema","El problema",[179,180,181],"p",{},"Una app Flutter que se publica en móviles, tabletas y escritorio necesita algo más que una columna flexible. Una pantalla que se lee bien con 390 píxeles lógicos de ancho pide una tarjeta centrada a 700 y una barra lateral a 1200. Flutter da las medidas, pero no una estructura donde aplicarlas.",[179,183,184,185,189,190,193,194,197],{},"Así que las comprobaciones se dispersan. Aquí un ",[186,187,188],"code",{},"MediaQuery.of(context).size.width > 600",", allí un ",[186,191,192],{},"LayoutBuilder",", y tres widgets más abajo un ternario dentro de un ",[186,195,196],{},"Padding",". Cada una parece razonable por separado; juntas forman una política de diseño que no está escrita en ningún sitio.",[179,199,200],{},"Los problemas más comunes son:",[202,203,204,208,213,216],"ul",{},[205,206,207],"li",{},"Valores de breakpoint duplicados en decenas de widgets, que van divergiendo a medida que cambia el diseño",[205,209,210,212],{},[186,211,192],{}," devolviendo las restricciones del padre cuando lo que hacía falta era el dispositivo",[205,214,215],{},"Diseños que saltan a la variante de tableta en cuanto se gira el móvil a horizontal",[205,217,218],{},"Árboles de widgets donde la lógica adaptativa es imposible de ver sin leer cada hijo",[174,220,222],{"id":221},"cómo-lo-resuelve-flutter_adaptive_layout","Cómo lo resuelve flutter_adaptive_layout",[179,224,225,228,229,232,233,236,237,240,241,243],{},[186,226,227],{},"AdaptiveLayout"," recibe un builder por tamaño de pantalla y un ",[186,230,231],{},"child",". Mide el dispositivo con ",[186,234,235],{},"MediaQuery",", lo traduce a un ",[186,238,239],{},"ScreenSize"," y construye solo la variante que corresponde, con el ",[186,242,231],{}," creado una sola vez y entregado al builder elegido.",[245,246,250],"pre",{"className":247,"code":248,"language":18,"meta":249,"style":249},"language-dart shiki shiki-themes material-theme-lighter github-light github-dark","AdaptiveLayout(\n  smallBuilder: (context, child) => child!,\n  mediumBuilder: (context, child) => Center(child: child),\n  largeBuilder: (context, child) => Row(\n    children: [const Sidebar(), Expanded(child: child!)],\n  ),\n  child: const MyHomePage(),\n)\n","",[186,251,252,264,296,325,346,385,393,411],{"__ignoreMap":249},[253,254,257,260],"span",{"class":255,"line":256},"line",1,[253,258,227],{"class":259},"sZMiF",[253,261,263],{"class":262},"su5hD","(\n",[253,265,267,270,274,277,281,284,287,290,293],{"class":255,"line":266},2,[253,268,269],{"class":262},"  smallBuilder",[253,271,273],{"class":272},"smGrS",":",[253,275,276],{"class":262}," (context",[253,278,280],{"class":279},"sP7_E",",",[253,282,283],{"class":262}," child) ",[253,285,286],{"class":272},"=>",[253,288,289],{"class":262}," child",[253,291,292],{"class":272},"!",[253,294,295],{"class":279},",\n",[253,297,299,302,304,306,308,310,312,315,318,320,323],{"class":255,"line":298},3,[253,300,301],{"class":262},"  mediumBuilder",[253,303,273],{"class":272},[253,305,276],{"class":262},[253,307,280],{"class":279},[253,309,283],{"class":262},[253,311,286],{"class":272},[253,313,314],{"class":259}," Center",[253,316,317],{"class":262},"(child",[253,319,273],{"class":272},[253,321,322],{"class":262}," child)",[253,324,295],{"class":279},[253,326,328,331,333,335,337,339,341,344],{"class":255,"line":327},4,[253,329,330],{"class":262},"  largeBuilder",[253,332,273],{"class":272},[253,334,276],{"class":262},[253,336,280],{"class":279},[253,338,283],{"class":262},[253,340,286],{"class":272},[253,342,343],{"class":259}," Row",[253,345,263],{"class":262},[253,347,349,352,354,357,361,364,367,369,372,374,376,378,380,383],{"class":255,"line":348},5,[253,350,351],{"class":262},"    children",[253,353,273],{"class":272},[253,355,356],{"class":262}," [",[253,358,360],{"class":359},"sbsja","const",[253,362,363],{"class":259}," Sidebar",[253,365,366],{"class":262},"()",[253,368,280],{"class":279},[253,370,371],{"class":259}," Expanded",[253,373,317],{"class":262},[253,375,273],{"class":272},[253,377,289],{"class":262},[253,379,292],{"class":272},[253,381,382],{"class":262},")]",[253,384,295],{"class":279},[253,386,388,391],{"class":255,"line":387},6,[253,389,390],{"class":262},"  )",[253,392,295],{"class":279},[253,394,396,399,401,404,407,409],{"class":255,"line":395},7,[253,397,398],{"class":262},"  child",[253,400,273],{"class":272},[253,402,403],{"class":359}," const",[253,405,406],{"class":259}," MyHomePage",[253,408,366],{"class":262},[253,410,295],{"class":279},[253,412,414],{"class":255,"line":413},8,[253,415,416],{"class":262},")\n",[179,418,419],{},"La decisión adaptativa vive ahora en un único widget, en la raíz del subárbol que gobierna, escrita como tres disposiciones en lugar de una cadena de condiciones.",[179,421,422],{},[423,424],"img",{"alt":425,"src":426,"style":427},"La app de ejemplo en pantalla pequeña, sobre un iPhone 14","\u002Fopen-source\u002Fflutter-adaptive-layout\u002Fiphone_14.png","max-height: 500px; height: auto; width: auto;",[179,429,430],{},[423,431],{"alt":432,"src":433},"La misma app en un iPad Pro de 12,9 pulgadas, donde largeBuilder coloca el contenido en una tarjeta más ancha","\u002Fopen-source\u002Fflutter-adaptive-layout\u002Fipad_12_inch.png",[174,435,437],{"id":436},"qué-ofrece","Qué ofrece",[202,439,440,462,468,474,484,494],{},[205,441,442,446,447,450,451,454,455,458,459,461],{},[443,444,445],"strong",{},"Disposiciones por tamaño de pantalla",": ",[186,448,449],{},"smallBuilder",", ",[186,452,453],{},"mediumBuilder"," y ",[186,456,457],{},"largeBuilder",", todos opcionales; si falta uno se dibuja el ",[186,460,231],{},", así que puedes describir solo los tamaños que te importan",[205,463,464,467],{},[443,465,466],{},"Breakpoints bajo tu control",": 400 y 600 píxeles lógicos por defecto, redefinibles por widget o para toda la app",[205,469,470,473],{},[443,471,472],{},"El child se construye una vez",": al cambiar de disposición el contenido se envuelve, no se reconstruye desde cero",[205,475,476,479,480,483],{},[443,477,478],{},"Estable ante la rotación",": la clasificación lee ",[186,481,482],{},"MediaQuery.of(context).size.shortestSide",", así que un móvil sigue siendo pantalla pequeña en horizontal",[205,485,486,489,490,493],{},[443,487,488],{},"Lógica de clasificación conectable",": implementa ",[186,491,492],{},"ScreenSizeQualifier"," para clasificar por ancho, plataforma, estado de la bisagra o como lo haga tu sistema de diseño",[205,495,496,499,500,502],{},[443,497,498],{},"Sin dependencias",": Flutter puro sobre ",[186,501,235],{},", funciona en iOS, Android, web, macOS, Windows y Linux",[174,504,506],{"id":505},"cómo-se-decide-el-tamaño-de-pantalla","Cómo se decide el tamaño de pantalla",[179,508,509,510,513],{},"El ",[186,511,512],{},"BreakpointsQualifier"," por defecto compara el lado más corto con dos breakpoints, de forma inclusiva: un valor igual al breakpoint pertenece a la categoría menor.",[515,516,517,536],"table",{},[518,519,520],"thead",{},[521,522,523,527,530,533],"tr",{},[524,525,526],"th",{},"Tamaño de pantalla",[524,528,529],{},"Condición",[524,531,532],{},"Rango por defecto",[524,534,535],{},"Dispositivo típico",[537,538,539,558,576],"tbody",{},[521,540,541,547,552,555],{},[542,543,544],"td",{},[186,545,546],{},"ScreenSize.small",[542,548,549],{},[186,550,551],{},"shortestSide \u003C= smallBreakpoint",[542,553,554],{},"0–400 píxeles lógicos",[542,556,557],{},"Móviles",[521,559,560,565,570,573],{},[542,561,562],{},[186,563,564],{},"ScreenSize.medium",[542,566,567],{},[186,568,569],{},"shortestSide \u003C= mediumBreakpoint",[542,571,572],{},"401–600 píxeles lógicos",[542,574,575],{},"Tabletas pequeñas",[521,577,578,583,589,592],{},[542,579,580],{},[186,581,582],{},"ScreenSize.large",[542,584,585,586],{},"por encima de ",[186,587,588],{},"mediumBreakpoint",[542,590,591],{},"601+ píxeles lógicos",[542,593,594],{},"Tabletas grandes, escritorio",[179,596,597,598,600,601,604],{},"Los breakpoints se resuelven en un orden fijo y gana el primer valor definido: los argumentos de ",[186,599,512],{},", después el ",[186,602,603],{},"BreakpointsSetting"," ancestro más cercano y, por último, los 400 y 600 integrados.",[174,606,608],{"id":607},"casos-de-uso-reales","Casos de uso reales",[610,611,613],"h3",{"id":612},"del-móvil-a-la-tableta","Del móvil a la tableta",[179,615,616,617,619,620,622],{},"Una app que empezó en móviles puede conservar todas sus pantallas y añadir un ",[186,618,457],{}," donde una disposición ancha compense. Las pantallas sin builder para ese tamaño dibujan el ",[186,621,231],{}," tal cual, así que la migración va pantalla a pantalla en vez de toda de golpe.",[610,624,626],{"id":625},"navegación-maestro-detalle","Navegación maestro-detalle",[179,628,629],{},"Una lista que en el móvil abre el detalle como una ruta nueva puede mostrar lista y detalle lado a lado en una tableta. Las dos variantes se declaran juntas en un mismo widget, de modo que la diferencia se revisa en el propio diff.",[610,631,633],{"id":632},"sistemas-de-diseño-con-sus-propios-breakpoints","Sistemas de diseño con sus propios breakpoints",[179,635,636,637,640,641,643,644,646],{},"Envuelve ",[186,638,639],{},"MaterialApp"," en ",[186,642,603],{}," una vez y todos los ",[186,645,227],{}," del árbol tomarán los números del sistema de diseño. Cambiarlos más adelante es editar una línea, no buscar por todo el proyecto.",[610,648,650],{"id":649},"ventanas-en-web-y-escritorio","Ventanas en web y escritorio",[179,652,653],{},"En web y escritorio se mide el tamaño de la ventana, así que la disposición responde mientras el usuario la redimensiona: el mismo código que atiende a una tableta atiende a un navegador redimensionado.",[174,655,657],{"id":656},"cómo-empezar","Cómo empezar",[179,659,660],{},"Instala el paquete:",[245,662,666],{"className":663,"code":664,"language":665,"meta":249,"style":249},"language-shell shiki shiki-themes material-theme-lighter github-light github-dark","flutter pub add flutter_adaptive_layout\n","shell",[186,667,668],{"__ignoreMap":249},[253,669,670,673,677,680],{"class":255,"line":256},[253,671,41],{"class":672},"sbgvK",[253,674,676],{"class":675},"s_sjI"," pub",[253,678,679],{"class":675}," add",[253,681,682],{"class":675}," flutter_adaptive_layout\n",[179,684,685,686,689],{},"Requiere Dart ",[186,687,688],{},">=2.18.5 \u003C4.0.0"," y Flutter 1.17+.",[179,691,692],{},"Impórtalo y envuelve el widget cuya disposición deba adaptarse:",[245,694,696],{"className":247,"code":695,"language":18,"meta":249,"style":249},"import 'package:flutter_adaptive_layout\u002Fflutter_adaptive_layout.dart';\n\nAdaptiveLayout(\n  largeBuilder: (context, child) => Center(\n    child: SizedBox(width: 600, child: child),\n  ),\n  child: const ArticleView(), \u002F\u002F en pantallas pequeñas y medianas, tal cual\n)\n",[186,697,698,710,716,722,740,769,775,794],{"__ignoreMap":249},[253,699,700,704,707],{"class":255,"line":256},[253,701,703],{"class":702},"sw1J6","import",[253,705,706],{"class":675}," 'package:flutter_adaptive_layout\u002Fflutter_adaptive_layout.dart'",[253,708,709],{"class":279},";\n",[253,711,712],{"class":255,"line":266},[253,713,715],{"emptyLinePlaceholder":714},true,"\n",[253,717,718,720],{"class":255,"line":298},[253,719,227],{"class":259},[253,721,263],{"class":262},[253,723,724,726,728,730,732,734,736,738],{"class":255,"line":327},[253,725,330],{"class":262},[253,727,273],{"class":272},[253,729,276],{"class":262},[253,731,280],{"class":279},[253,733,283],{"class":262},[253,735,286],{"class":272},[253,737,314],{"class":259},[253,739,263],{"class":262},[253,741,742,745,747,750,753,755,759,761,763,765,767],{"class":255,"line":348},[253,743,744],{"class":262},"    child",[253,746,273],{"class":272},[253,748,749],{"class":259}," SizedBox",[253,751,752],{"class":262},"(width",[253,754,273],{"class":272},[253,756,758],{"class":757},"srdBf"," 600",[253,760,280],{"class":279},[253,762,289],{"class":262},[253,764,273],{"class":272},[253,766,322],{"class":262},[253,768,295],{"class":279},[253,770,771,773],{"class":255,"line":387},[253,772,390],{"class":262},[253,774,295],{"class":279},[253,776,777,779,781,783,786,788,790],{"class":255,"line":395},[253,778,398],{"class":262},[253,780,273],{"class":272},[253,782,403],{"class":359},[253,784,785],{"class":259}," ArticleView",[253,787,366],{"class":262},[253,789,280],{"class":279},[253,791,793],{"class":792},"sutJx"," \u002F\u002F en pantallas pequeñas y medianas, tal cual\n",[253,795,796],{"class":255,"line":413},[253,797,416],{"class":262},[179,799,800,801,803,804,273],{},"Para clasificar las pantallas de otra forma, implementa ",[186,802,492],{}," y pásalo como ",[186,805,806],{},"qualifier",[245,808,810],{"className":247,"code":809,"language":18,"meta":249,"style":249},"class WidthQualifier extends ScreenSizeQualifier {\n  @override\n  ScreenSize qualify(BuildContext context) {\n    final width = MediaQuery.of(context).size.width;\n    if (width \u003C 600) return ScreenSize.small;\n    if (width \u003C 1024) return ScreenSize.medium;\n    return ScreenSize.large;\n  }\n}\n",[186,811,812,829,834,852,887,917,941,955,960],{"__ignoreMap":249},[253,813,814,817,820,823,826],{"class":255,"line":256},[253,815,816],{"class":272},"class",[253,818,819],{"class":259}," WidthQualifier",[253,821,822],{"class":272}," extends",[253,824,825],{"class":259}," ScreenSizeQualifier",[253,827,828],{"class":262}," {\n",[253,830,831],{"class":255,"line":266},[253,832,833],{"class":359},"  @override\n",[253,835,836,839,843,846,849],{"class":255,"line":298},[253,837,838],{"class":259},"  ScreenSize",[253,840,842],{"class":841},"sGLFI"," qualify",[253,844,845],{"class":262},"(",[253,847,848],{"class":259},"BuildContext",[253,850,851],{"class":262}," context) {\n",[253,853,854,857,860,863,866,869,872,875,877,880,882,885],{"class":255,"line":327},[253,855,856],{"class":359},"    final",[253,858,859],{"class":262}," width ",[253,861,862],{"class":272},"=",[253,864,865],{"class":259}," MediaQuery",[253,867,868],{"class":279},".",[253,870,871],{"class":841},"of",[253,873,874],{"class":262},"(context)",[253,876,868],{"class":279},[253,878,879],{"class":262},"size",[253,881,868],{"class":279},[253,883,884],{"class":262},"width",[253,886,709],{"class":279},[253,888,889,893,896,899,901,904,907,910,912,915],{"class":255,"line":348},[253,890,892],{"class":891},"sVHd0","    if",[253,894,895],{"class":262}," (width ",[253,897,898],{"class":272},"\u003C",[253,900,758],{"class":757},[253,902,903],{"class":262},") ",[253,905,906],{"class":891},"return",[253,908,909],{"class":259}," ScreenSize",[253,911,868],{"class":279},[253,913,914],{"class":262},"small",[253,916,709],{"class":279},[253,918,919,921,923,925,928,930,932,934,936,939],{"class":255,"line":387},[253,920,892],{"class":891},[253,922,895],{"class":262},[253,924,898],{"class":272},[253,926,927],{"class":757}," 1024",[253,929,903],{"class":262},[253,931,906],{"class":891},[253,933,909],{"class":259},[253,935,868],{"class":279},[253,937,938],{"class":262},"medium",[253,940,709],{"class":279},[253,942,943,946,948,950,953],{"class":255,"line":395},[253,944,945],{"class":891},"    return",[253,947,909],{"class":259},[253,949,868],{"class":279},[253,951,952],{"class":262},"large",[253,954,709],{"class":279},[253,956,957],{"class":255,"line":413},[253,958,959],{"class":262},"  }\n",[253,961,963],{"class":255,"line":962},9,[253,964,965],{"class":262},"}\n",[179,967,968,971],{},[186,969,970],{},"qualify"," se ejecuta en cada build, así que debe ser barato y libre de efectos secundarios.",[179,973,974,975,868],{},"Hay una app completa y ejecutable en el ",[976,977,981],"a",{"href":978,"rel":979},"https:\u002F\u002Fgithub.com\u002Fnerdy-pro\u002Fflutter-adaptive-layout\u002Ftree\u002Fmain\u002Fexample",[980],"nofollow","directorio example",[983,984],"questions",{":items":985},"[{\"title\":\"¿En qué se diferencia de LayoutBuilder?\",\"text\":\"LayoutBuilder informa de las restricciones que le pasa el widget padre, que pueden ser mucho menores que la pantalla. AdaptiveLayout clasifica el dispositivo o la ventana mediante MediaQuery, así que un widget en lo profundo del árbol sigue sabiendo que se ejecuta en una tableta. Usa LayoutBuilder para encajar en el espacio disponible; usa AdaptiveLayout para elegir una disposición según el dispositivo.\"},{\"title\":\"¿Cambia la disposición al girar el dispositivo?\",\"text\":\"No. La clasificación usa MediaQuery.of(context).size.shortestSide, que es igual en vertical y en horizontal, así que un móvil sigue siendo ScreenSize.small al girarlo. Si quieres disposiciones sensibles a la orientación, implementa un ScreenSizeQualifier propio que lea size.width.\"},{\"title\":\"¿Hay que proporcionar los tres builders?\",\"text\":\"No. Cualquier builder puede omitirse y para ese tamaño de pantalla se usa el child. Si no hay ni builder correspondiente ni child, se lanza un UnimplementedError.\"},{\"title\":\"¿Cómo se cambian los breakpoints por defecto?\",\"text\":\"Pasa BreakpointsQualifier(smallBreakpoint: ..., mediumBreakpoint: ...) a un AdaptiveLayout concreto, o envuelve la app en BreakpointsSetting para cambiarlos en todas partes. Los valores del constructor tienen prioridad sobre BreakpointsSetting, y este sobre los valores por defecto de 400 y 600.\"},{\"title\":\"¿Funciona en web y escritorio?\",\"text\":\"Sí. Solo depende de MediaQuery, así que funciona en todos los destinos de Flutter. En web y escritorio se mide la ventana, de modo que la disposición responde al redimensionarla.\"}]",[987,988,989],"style",{},"html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}",{"title":249,"searchDepth":266,"depth":266,"links":991},[992,993,994,995,996,1002],{"id":176,"depth":266,"text":177},{"id":221,"depth":266,"text":222},{"id":436,"depth":266,"text":437},{"id":505,"depth":266,"text":506},{"id":607,"depth":266,"text":608,"children":997},[998,999,1000,1001],{"id":612,"depth":298,"text":613},{"id":625,"depth":298,"text":626},{"id":632,"depth":298,"text":633},{"id":649,"depth":298,"text":650},{"id":656,"depth":266,"text":657},"Un paquete de Flutter que construye una disposición distinta para pantallas pequeñas, medianas y grandes, con breakpoints configurables y sin más dependencia que MediaQuery.","md",[1006],{"type":1007,"url":1008},"pub_dev","https:\u002F\u002Fpub.dev\u002Fpackages\u002Fflutter_adaptive_layout",{},"Paquete de Flutter que dibuja una disposición distinta en móviles, tabletas y escritorio. Un builder por tamaño de pantalla y breakpoints propios.","Diseño adaptativo en Flutter según el tamaño de pantalla","Un builder por tamaño de pantalla en lugar de comprobaciones de ancho repartidas por el árbol de widgets. Un paquete Flutter pequeño para interfaces adaptativas.","\u002Fopen-source\u002Fflutter-adaptive-layout",{"type":1015,"company":1016,"name":1017},"github","nerdy-pro","flutter-adaptive-layout",{"title":169,"description":1003},"open-source\u002Fflutter-adaptive-layout",[41,18],"2026-08-15","qKauzeSj1UR79cWfPGCC9Xzz_treBqKpjls-Wd1zoRk",{"forks":1024,"stars":256,"contributors":1025,"last_release":1031,"issues":1024,"has_contribution_guide":1032,"license":1033,"last_updated":1034,"watchers":256},0,[1026],{"login":1027,"profile_url":1028,"avatar_url":1029,"contributions":1030},"thenixan","https:\u002F\u002Fgithub.com\u002Fthenixan","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F3602098?v=4",26,"v1.1.0",false,"MIT","2026-08-13T19:18:10Z"]