Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

docs.flutter.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.

Learn more

Don't miss ourDecember livestream, with updates on Flutter and live Q&A!

Flutter for Jetpack Compose developers

Learn how to apply Jetpack Compose developer knowledge when building Flutter apps.

Note

Flutter is a framework for building cross-platform applications that uses the Dart programming language.

Your Jetpack Compose knowledge and experience are highly valuable when building with Flutter.

Tip

This document can be used as a reference by jumping around and finding questions that are most relevant to your needs. This guide embeds sample code. By using the "Open in DartPad" button that appears on hover or focus, you can open and run some of the examples on DartPad.

Overview

#

Flutter and Jetpack Compose code describe how the UI looks and works. Developers call this type of code adeclarative framework.

While there are key differences especially when it comes to interacting with legacy Android code, there are many commonalities between the two frameworks.

Composables vs. Widgets

#

Jetpack Compose represents UI components ascomposable functions, later noted in this document ascomposables. Composables can be altered or decorated through the use ofModifier objects.

kotlin
Text("Hello, World!",modifier:Modifier.padding(10.dp))Text("Hello, World!",modifier=Modifier.padding(10.dp))

Flutter represents UI components aswidgets.

Both composables and widgets only exist until they need to change. These languages call this propertyimmutability. Jetpack Compose modifies UI component properties using an optionalmodifier property backed by aModifier object. By contrast, Flutter widgets configure their properties directly through constructor parameters.

dart
Padding(// <-- This is a Widgetpadding:EdgeInsets.all(10.0),// <-- a parameter to Paddingchild:Text("Hello, World!"),// <-- This is also a Widget);

To compose layouts, both Jetpack Compose and Flutter nest UI components within one another. Jetpack Compose nestsComposables while Flutter nestsWidgets.

Layout process

#

Jetpack Compose and Flutter handle layout in similar ways. Both of them lay out the UI in a single pass and parent elements provide layout constraints down to their children. More specifically,

  1. The parent measures itself and its children recursively providing any constraints from the parent to the child.
  2. The children try to size themselves using the above methods and provide their own children both their constraints and any that might apply from their ancestor nodes.
  3. Upon encountering a leaf node (a node with no children), the size and properties are determined based on the provided constraints and the element is placed in the UI.
  4. With all the children sized and placed, the root nodes can determine their measurement, size, and placement.

In both Jetpack Compose and Flutter, the parent component can override or constrain the child's desired size. The widget cannot have any size it wants. It also cannotusually know or decide its position on screen as its parent makes that decision.

To force a child widget to render at a specific size, the parent must set tight constraints. A constraint becomes tight when its constraint's minimum size value equals its maximum size value.

To learn how constraints work in Flutter, visitUnderstanding constraints.

Design system

#

Because Flutter targets multiple platforms, your app doesn't need to conform to any design system. While this guide featuresMaterial widgets, your Flutter app can use many different design systems:

  • Custom Material widgets
  • Community built widgets
  • Your own custom widgets

If you're looking for a great reference app that features a custom design system, check outWonderous.

UI basics

#

This section covers the basics of UI development in Flutter and how it compares to Jetpack Compose. This includes how to start developing your app, display static text, create buttons, react to on-press events, display lists, grids, and more.

Getting started

#

ForCompose apps, your main entry point will beActivity or one of its descendants, generallyComponentActivity.

kotlin
classMainActivity:ComponentActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)enableEdgeToEdge()setContent{SampleTheme{Scaffold(modifier=Modifier.fillMaxSize()){innerPadding->Greeting(name="Android",modifier=Modifier.padding(innerPadding))}}}}}@ComposablefunGreeting(name:String,modifier:Modifier=Modifier){Text(text="Hello$name!",modifier=modifier)}

To start yourFlutter app, pass an instance of your app to therunApp function.

dart
voidmain(){runApp(constMyApp());}

App is a widget. It'sbuild method describes the part of the user interface it represents. It's common to begin your app with aWidgetApp class, likeMaterialApp.

dart
classMyAppextendsStatelessWidget{constMyApp({super.key});@overrideWidgetbuild(BuildContextcontext){returnconstMaterialApp(home:HomePage(),);}}

The widget used in theHomePage might begin with theScaffold class.Scaffold implements a basic layout structure for an app.

dart
classHomePageextendsStatelessWidget{constHomePage({super.key});@overrideWidgetbuild(BuildContextcontext){returnconstScaffold(body:Center(child:Text('Hello, World!',),),);}}

Note how Flutter uses theCenter widget.

Compose has a number of defaults from its ancestor Android Views. Unless otherwise specified, most components "wrap" their size to content meaning they only take up as much space as needed when rendered. That's not always the case with Flutter.

To center the text, wrap it in aCenter widget. To learn about different widgets and their default behaviors, check out theWidget catalog.

Adding Buttons

#

InCompose, you use theButton composable or one of its variants to create a button.Button is an alias forFilledTonalButton when using a Material theme.

kotlin
Button(onClick={}){Text("Do something")}

To achieve the same result inFlutter, use theFilledButton class:

dart
FilledButton(onPressed:(){// This closure is called when your button is tapped.},constText('Do something'),),

Flutter gives you access to a variety of buttons with pre-defined styles.

Aligning components horizontally or vertically

#

Jetpack Compose and Flutter handle horizontal and vertical collections of items similarly.

The following Compose snippet adds a globe image and text in bothRow andColumn containers with centering of the items:

kotlin
Row(horizontalArrangement=Arrangement.Center){Image(Icons.Default.Public,contentDescription="")Text("Hello, world!")}Column(verticalArrangement=Arrangement.Center){Image(Icons.Default.Public,contentDescription="")Text("Hello, world!")}

Flutter usesRow andColumn as well but there are some slight differences for specifying child widgets and alignment. The following is equivalent to the Compose example.

dart
Row(mainAxisAlignment:MainAxisAlignment.center,children:[Icon(Icons.public),Text('Hello, world!'),],),Column(mainAxisAlignment:MainAxisAlignment.center,children:[Icon(MaterialIcons.globe),Text('Hello, world!'),],)

Row andColumn require aList<Widget> in thechildren parameter. ThemainAxisAlignment property tells Flutter how to position children with extra space.MainAxisAlignment.center positions children in the center of the main axis. ForRow, the main axis is the horizontal axis, inversely forColumn, the main axis is the vertical axis.

::: note Whereas Flutter'sRow andColumn haveMainAxisAlignment andCrossAxisAlignment to control how items are placed, the properties that control placement in Jetpack Compose are one vertical and horizontal property from the following:verticalArrangement,verticalAlignment,horizontalAlignment, andhorizontalArrangement. The trick to determine which is theMainAxis is to look for the property that ends inarrangement. TheCrossAxis will be the property that ends inalignment. :::

Displaying a list view

#

InCompose, you have a couple ways to create a list based on the size of the list you need to display. For a small number of items that can all be displayed at once, you can iterate over a collection inside aColumn orRow.

For a list with a large number of items,LazyList has better performance. It only lays out the components that will be visible versus all of them.

kotlin
dataclassPerson(valname:String)valpeople=arrayOf(Person(name="Person 1"),Person(name="Person 2"),Person(name="Person 3"))@ComposablefunListDemo(people:List<Person>){Column{people.forEach{Text(it.name)}}}@ComposablefunListDemo2(people:List<Person>){LazyColumn{items(people){person->Text(person.name)}}}

To lazily build a list in Flutter, ....

dart
classPerson{Stringname;Person(this.name);}varitems=[Person('Person 1'),Person('Person 2'),Person('Person 3'),];classHomePageextendsStatelessWidget{constHomePage({super.key});@overrideWidgetbuild(BuildContextcontext){returnScaffold(body:ListView.builder(itemCount:items.length,itemBuilder:(context,index){returnListTile(title:Text(items[index].name),);},),);}}

Flutter has some conventions for lists:

  • TheListView widget has a builder method. This works like theitem closure inside a ComposeLazyList.

  • TheitemCount parameter of theListView sets how many items theListView displays.

  • TheitemBuilder has an index parameter that will be between zero and one less than itemCount.

The previous example returned aListTile widget for each item. TheListTile widget includes properties likeheight andfont-size. These properties help build a list. However, Flutter allows you to return almost any widget that represents your data.

Displaying a grid

#

Constructing a grid inCompose is similar to a LazyList (LazyColumn orLazyRow). You can use the sameitems closure. There are properties on each grid type to specify how to arrange the items, whether or not to use adaptive or fixed layout, amongst others.

kotlin
valwidgets=arrayOf("Row 1",Icons.Filled.ArrowDownward,Icons.Filled.ArrowUpward,"Row 2",Icons.Filled.ArrowDownward,Icons.Filled.ArrowUpward)LazyVerticalGrid(columns=GridCells.Fixed(3),contentPadding=PaddingValues(8.dp)){items(widgets){i->if(iisString){Text(i)}else{Image(iasImageVector,"")}}}

To display grids inFlutter, use theGridView widget. This widget has various constructors. Each constructor has a similar goal, but uses different input parameters. The following example uses the.builder() initializer:

dart
constwidgets=[Text('Row 1'),Icon(Icons.arrow_downward),Icon(Icons.arrow_upward),Text('Row 2'),Icon(Icons.arrow_downward),Icon(Icons.arrow_upward),];classHomePageextendsStatelessWidget{constHomePage({super.key});@overrideWidgetbuild(BuildContextcontext){returnScaffold(body:GridView.builder(gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:3,mainAxisExtent:40,),itemCount:widgets.length,itemBuilder:(context,index)=>widgets[index],),);}}

TheSliverGridDelegateWithFixedCrossAxisCount delegate determines various parameters that the grid uses to lay out its components. This includescrossAxisCount that dictates the number of items displayed on each row.

Jetpack Compose'sLazyHorizontalGrid,LazyVerticalGrid, and Flutter'sGridView are somewhat similar.GridView uses a delegate to decide how the grid should lay out its components. Therows,columns, and other associated properties onLazyHorizontalGrid \LazyVerticalGrid serve the same purpose.

Creating a scroll view

#

LazyColumn andLazyRow inJetpack Compose have built-in support for scrolling.

To create a scrolling view,Flutter usesSingleChildScrollView. In the following example, the functionmockPerson mocks instances of thePerson class to create the customPersonView widget.

dart
SingleChildScrollView(child:Column(children:mockPersons.map((person)=>PersonView(person:person,),).toList(),),),

Responsive and adaptive design

#

Adaptive Design inCompose is a complex topic with many viable solutions:

  • Using a custom layout
  • UsingWindowSizeClass alone
  • UsingBoxWithConstraints to control what is shown based on available space
  • Using the Material 3 adaptive library that usesWindowSizeClass along with specialized composable layouts for common layouts

For that reason, you are encouraged to look into theFlutter options directly and see what fits your requirements versus attempting to find something that is a one to one translation.

To create relative views inFlutter, you can use one of two options:

  • Get theBoxConstraints object in theLayoutBuilder class.
  • Use theMediaQuery.of() in your build functions to get the size and orientation of your current app.

To learn more, check outCreating responsive and adaptive apps.

Managing state

#

Compose stores state with theremember API and descendants of theMutableState interface.

kotlin
Scaffold(content={padding->var_counter=remember{mutableIntStateOf(0)}Column(horizontalAlignment=Alignment.CenterHorizontally,verticalArrangement=Arrangement.Center,modifier=Modifier.fillMaxSize().padding(padding)){Text(_counter.value.toString())Spacer(modifier=Modifier.height(16.dp))FilledIconButton(onClick={->_counter.intValue+=1}){Text("+")}}})

Flutter manages local state using aStatefulWidget. Implement a stateful widget with the following two classes:

  • a subclass ofStatefulWidget
  • a subclass ofState

TheState object stores the widget's state. To change a widget's state, callsetState() from theState subclass to tell the framework to redraw the widget.

The following example shows a part of a counter app:

dart
classMyHomePageextendsStatefulWidget{constMyHomePage({super.key});@overrideState<MyHomePage>createState()=>_MyHomePageState();}class_MyHomePageStateextendsState<MyHomePage>{int_counter=0;@overrideWidgetbuild(BuildContextcontext){returnScaffold(body:Center(child:Column(mainAxisAlignment:MainAxisAlignment.center,children:[Text('$_counter'),TextButton(onPressed:()=>setState((){_counter++;}),child:constText('+'),),],),),);}}

To learn more ways to manage state, check outState management.

Drawing on the Screen

#

InCompose, you use theCanvas composable to draw shapes, images, and text to the screen.

Flutter has an API based on theCanvas class, with two classes that help you draw:

  1. CustomPaint that requires a painter:

    dart
    CustomPaint(painter:SignaturePainter(_points),size:Size.infinite,),
  2. CustomPainter that implements your algorithm to draw to the canvas.

    dart
    classSignaturePainterextendsCustomPainter{SignaturePainter(this.points);finalList<Offset?>points;@overridevoidpaint(Canvascanvas,Sizesize){finalPaintpaint=Paint()..color=Colors.black..strokeCap=StrokeCap.round..strokeWidth=5;for(inti=0;i<points.length-1;i++){if(points[i]!=null&&points[i+1]!=null){canvas.drawLine(points[i]!,points[i+1]!,paint);}}}@overrideboolshouldRepaint(SignaturePainteroldDelegate)=>oldDelegate.points!=points;}

Themes, styles, and media

#

You can style Flutter apps with little effort. Styling includes switching between light and dark themes, changing the design of your text and UI components, and more. This section covers how to style your apps.

Using dark mode

#

InCompose, you can control light and dark at any arbitrary level by wrapping a component with aTheme composable.

InFlutter, you can control light and dark mode at the app-level. To control the brightness mode, use thetheme property of theApp class:

dart
constMaterialApp(theme:ThemeData(brightness:Brightness.dark,),home:HomePage(),);

Styling text

#

InCompose, you use the properties onText for one or two attributes or construct aTextStyle object to set many at once.

kotlin
Text("Hello, world!",color=Color.Green,fontWeight=FontWeight.Bold,fontSize=30.sp)
kotlin
Text("Hello, world!",style=TextStyle(color=Color.Green,fontSize=30.sp,fontWeight=FontWeight.Bold),)

To style text inFlutter, add aTextStyle widget as the value of thestyle parameter of theText widget.

dart
Text('Hello, world!',style:TextStyle(fontSize:30,fontWeight:FontWeight.bold,color:Colors.blue,),),

Styling buttons

#

InCompose, you modify the colors of a button using thecolors property. If left unmodified, they use the defaults from the current theme.

kotlin
Button(onClick={},colors=ButtonDefaults.buttonColors().copy(containerColor=Color.Yellow,contentColor=Color.Blue,)){Text("Do something",fontSize=30.sp,fontWeight=FontWeight.Bold)}

To style button widgets inFlutter, you similarly set the style of its child, or modify properties on the button itself.

dart
FilledButton(onPressed:(){},style:FilledButton.styleFrom(backgroundColor:Colors.amberAccent),child:constText('Do something',style:TextStyle(color:Colors.blue,fontSize:30,fontWeight:FontWeight.bold,)))

Bundling assets for use in Flutter

#

There is commonly a need to bundle resources for use in your application. They can be animations, vector graphics, images, fonts, or other general files.

Unlike native Android apps that expect a set directory structure under/res/<qualifier>/ where the qualifier could be indicating the type of file, a specific orientation, or android version, Flutter doesn't require a specific location as long as the referenced files are listed in thepubspec.yaml file. Below is an excerpt from apubspec.yaml referencing several images and a font file.

yaml
flutter:assets:-assets/my_icon.png-assets/background.pngfonts:-family:FiraSansfonts:-asset:fonts/FiraSans-Regular.ttf

Using fonts

#

InCompose, you have two options for using fonts in your app. You can use a runtime service I to retrieve themGoogle Fonts. Alternatively, they may be bundled in resource files.

Flutter has similar methods to use fonts, let's discuss them both inline.

Using bundled fonts

#

The following are roughly equivalent Compose and Flutter code for using a font file in the/res/ orfonts directory as listed above.

kotlin
// Font files bundled with appvalfiraSansFamily=FontFamily(Font(R.font.firasans_regular,FontWeight.Normal),// ...)// UsageText(text="Compose",fontFamily=firaSansFamily,fontWeight=FontWeight.Normal)
dart
Text('Flutter',style:TextStyle(fontSize:40,fontFamily:'FiraSans',),),

Using a font provider (Google Fonts)

#

One point of difference is using fonts from a font provider like Google Fonts. InCompose, the instantiation is done inline with the same approximate code to reference a local file.

After instantiating a provider that references the special strings for the font service, you would use the sameFontFamily declaration.

kotlin
// Font files bundled with appvalprovider=GoogleFont.Provider(providerAuthority="com.google.android.gms.fonts",providerPackage="com.google.android.gms",certificates=R.array.com_google_android_gms_fonts_certs)valfiraSansFamily=FontFamily(Font(googleFont=GoogleFont("FiraSans"),fontProvider=provider,))// UsageText(text="Compose",fontFamily=firaSansFamily,fontWeight=FontWeight.Light)

For Flutter, this is provided by thegoogle_fonts plugin using the name of the font.

dart
import'package:google_fonts/google_fonts.dart';//...Text('Flutter',style:GoogleFonts.firaSans(),// or//style: GoogleFonts.getFont('FiraSans')),

Using images

#

InCompose, typically image files to the drawable directory in resources/res/drawable and one usesImage composable to display the images. Assets are referenced by using the resource locator in the style ofR.drawable.<file name> without the file extension.

InFlutter, the resource location is a listed inpubspec.yaml as shown in the snippet below.

yaml
flutter:assets:-images/Blueberries.jpg

After adding your image, you can display it using theImage widget's.asset() constructor. This constructor:

To review a complete example, check out theImage docs.

Was this page's content helpful?

Unless stated otherwise, the documentation on this site reflects Flutter 3.38.1. Page last updated on 2025-11-21.View source orreport an issue.


[8]ページ先頭

©2009-2025 Movatter.jp