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 SwiftUI Developers

Learn how to apply SwiftUI developer knowledge when building Flutter apps.

SwiftUI developers who want to write mobile apps using Flutter should review this guide. It explains how to apply existing SwiftUI knowledge to Flutter.

Note

Flutter is a framework for building cross-platform applications that uses the Dart programming language. To understand some differences between programming with Dart and programming with Swift, seeLearning Dart as a Swift Developer andFlutter concurrency for Swift developers.

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

Flutter also makes a number of adaptations to app behavior when running on iOS and macOS. To learn how, seePlatform adaptations.

Tip

This document can be used as a cookbook 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

#

As an introduction, watch the following video. It outlines how Flutter works on iOS and how to use Flutter to build iOS apps.

Watch on YouTube in a new tab: "Flutter for iOS developers"

Flutter and SwiftUI code describes how the UI looks and works. Developers call this type of code adeclarative framework.

Views vs. Widgets

#

SwiftUI represents UI components asviews. You configure views usingmodifiers.

swift
Text("Hello, World!")// <-- This is a View.padding(10)// <-- This is a modifier of that View

Flutter represents UI components aswidgets.

Both views and widgets only exist until they need to be changed. These languages call this propertyimmutability. SwiftUI represents a UI component property as a View modifier. By contrast, Flutter uses widgets for both UI components and their properties.

dart
Padding(// <-- This is a Widgetpadding:EdgeInsets.all(10.0),// <-- So is thischild:Text("Hello, World!"),// <-- This, too)));

To compose layouts, both SwiftUI and Flutter nest UI components within one another. SwiftUI nests Views while Flutter nests Widgets.

Layout process

#

SwiftUI lays out views using the following process:

  1. The parent view proposes a size to its child view.
  2. All subsequent child views:
    • propose a size totheir child's view
    • ask that child what size it wants
  3. Each parent view renders its child view at the returned size.

Flutter differs somewhat with its process:

  1. The parent widget passes constraints down to its children. Constraints include minimum and maximum values for height and width.

  2. The child tries to decide its size. It repeats the same process with its own list of children:

    • It informs its child of the child's constraints.
    • It asks its child what size it wishes to be.
  3. The parent lays out the child.

    • If the requested size fits in the constraints, the parent uses that size.
    • If the requested size doesn't fit in the constraints, the parent limits the height, width, or both to fit in its constraints.

Flutter differs from SwiftUI because the parent component can override the child's desired size. The widget cannot have any size it wants. It also cannot 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.

InSwiftUI, views might expand to the available space or limit their size to that of its content.Flutter widgets behave in similar manner.

However, in Flutter parent widgets can offer unbounded constraints. Unbounded constraints set their maximum values to infinity.

dart
UnboundedBox(child:Container(width:double.infinity,height:double.infinity,color:red),)

If the child expands and it has unbounded constraints, Flutter returns an overflow warning:

dart
UnconstrainedBox(child:Container(color:red,width:4000,height:50),)
When parents pass unbounded constraints to children, and the children are expanding, then there is an overflow warning.

To learn how constraints work in Flutter, seeUnderstanding constraints.

Design system

#

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

  • Custom Material widgets
  • Community built widgets
  • Your own custom widgets
  • Cupertino widgets that follow Apple's Human Interface Guidelines

Watch on YouTube in a new tab: "Flutter's cupertino library for iOS developers"

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 SwiftUI. 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

#

InSwiftUI, you useApp to start your app.

swift
@mainstructMyApp:App{varbody:someScene{WindowGroup{HomePage()}}}

Another common SwiftUI practice places the app body within astruct that conforms to theView protocol as follows:

swift
structHomePage:View{varbody:someView{Text("Hello, World!")}}

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

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

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

dart
classMyAppextendsStatelessWidget{constMyApp({super.key});@overrideWidgetbuild(BuildContextcontext){// Returns a CupertinoApp that, by default,// has the look and feel of an iOS app.returnconstCupertinoApp(home:HomePage());}}

The widget used inHomePage 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. SwiftUI renders a view's contents in its center by default. That's not always the case with Flutter.Scaffold doesn't render itsbody widget at the center of the screen. To center the text, wrap it in aCenter widget. To learn about different widgets and their default behaviors, check out theWidget catalog.

Adding Buttons

#

InSwiftUI, you use theButton struct to create a button.

swift
Button("Do something"){// this closure gets called when your// button is tapped}

To achieve the same result inFlutter, use theCupertinoButton class:

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

Flutter gives you access to a variety of buttons with predefined styles. TheCupertinoButton class comes from the Cupertino library. Widgets in the Cupertino library use Apple's design system.

Aligning components horizontally

#

InSwiftUI, stack views play a big part in designing your layouts. Two separate structures allow you to create stacks:

  1. HStack for horizontal stack views

  2. VStack for vertical stack views

The following SwiftUI view adds a globe image and text to a horizontal stack view:

swift
HStack{Image(systemName:"globe")Text("Hello, world!")}

Flutter usesRow rather thanHStack:

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

TheRow widget requires 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.

Aligning components vertically

#

The following examples build on those in the previous section.

InSwiftUI, you useVStack to arrange the components into a vertical pillar.

swift
VStack{Image(systemName:"globe")Text("Hello, world!")}

Flutter uses the same Dart code from the previous example, except it swapsColumn forRow:

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

Displaying a list view

#

InSwiftUI, you use theList base component to display sequences of items. To display a sequence of model objects, make sure that the user can identify your model objects. To make an object identifiable, use theIdentifiable protocol.

swift
structPerson:Identifiable{varname:String}varpersons=[Person(name:"Person 1"),Person(name:"Person 2"),Person(name:"Person 3"),]structListWithPersons:View{letpersons:[Person]varbody:someView{List{ForEach(persons){personinText(person.name)}}}}

This resembles howFlutter prefers to build its list widgets. Flutter doesn't need the list items to be identifiable. You set the number of items to display then build a widget for each item.

dart
classPerson{Stringname;Person(this.name);}finalList<Person>items=[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 caveats for lists:

  • TheListView widget has a builder method. This works like theForEach within SwiftUI'sList struct.

  • 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

#

When constructing non-conditional grids inSwiftUI, you useGrid withGridRow.

swift
Grid{GridRow{Text("Row 1")Image(systemName:"square.and.arrow.down")Image(systemName:"square.and.arrow.up")}GridRow{Text("Row 2")Image(systemName:"square.and.arrow.down")Image(systemName:"square.and.arrow.up")}}

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(CupertinoIcons.arrow_down_square),Icon(CupertinoIcons.arrow_up_square),Text('Row 2'),Icon(CupertinoIcons.arrow_down_square),Icon(CupertinoIcons.arrow_up_square),];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.

How SwiftUI'sGrid and Flutter'sGridView differ in thatGrid requiresGridRow.GridView uses the delegate to decide how the grid should lay out its components.

Creating a scroll view

#

InSwiftUI, you useScrollView to create custom scrolling components. The following example displays a series ofPersonView instances in a scrollable fashion.

swift
ScrollView{VStack(alignment:.leading){ForEach(persons){personinPersonView(person:person)}}}

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

#

InSwiftUI, you useGeometryReader to create relative view sizes.

For example, you could:

  • Multiplygeometry.size.width by some factor to set thewidth.
  • UseGeometryReader as a breakpoint to change the design of your app.

You can also see if the size class has.regular or.compact usinghorizontalSizeClass.

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

#

InSwiftUI, you use the@State property wrapper to represent the internal state of a SwiftUI view.

swift
structContentView:View{@Stateprivatevarcounter=0;varbody:someView{VStack{Button("+"){counter+=1}Text(String(counter))}}}

SwiftUI also includes several options for more complex state management such as theObservableObject protocol.

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.

Animations

#

Two main types of UI animations exist.

  • Implicit that animated from a current value to a new target.
  • Explicit that animates when asked.

Implicit Animation

#

SwiftUI and Flutter take a similar approach to animation. In both frameworks, you specify parameters likeduration, andcurve.

InSwiftUI, you use theanimate() modifier to handle implicit animation.

swift
Button("Tap me!"){angle+=45}.rotationEffect(.degrees(angle)).animation(.easeIn(duration:1))

Flutter includes widgets for implicit animation. This simplifies animating common widgets. Flutter names these widgets with the following format:AnimatedFoo.

For example: To rotate a button, use theAnimatedRotation class. This animates theTransform.rotate widget.

dart
AnimatedRotation(duration:constDuration(seconds:1),turns:turns,curve:Curves.easeIn,TextButton(onPressed:(){setState((){turns+=.125;});},constText('Tap me!'),),),

Flutter allows you to create custom implicit animations. To compose a new animated widget, use theTweenAnimationBuilder.

Explicit Animation

#

For explicit animations,SwiftUI uses thewithAnimation() function.

Flutter includes explicitly animated widgets with names formatted likeFooTransition. One example would be theRotationTransition class.

Flutter also allows you to create a custom explicit animation usingAnimatedWidget orAnimatedBuilder.

To learn more about animations in Flutter, seeAnimations overview.

Drawing on the Screen

#

InSwiftUI, you useCoreGraphics to draw lines and shapes 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;}

Navigation

#

This section explains how to navigate between pages of an app, the push and pop mechanism, and more.

Navigating between pages

#

Developers build iOS and macOS apps with different pages callednavigation routes.

InSwiftUI, theNavigationStack represents this stack of pages.

The following example creates an app that displays a list of persons. To display a person's details in a new navigation link, tap on that person.

swift
NavigationStack(path:$path){List{ForEach(persons){personinNavigationLink(person.name,value:person)}}.navigationDestination(for:Person.self){personinPersonView(person:person)}}

If you have a smallFlutter app without complex linking, useNavigator with named routes. After defining your navigation routes, call your navigation routes using their names.

  1. Name each route in the class passed to therunApp() function. The following example usesApp:

    dart
    // Defines the route name as a constant// so that it's reusable.constdetailsPageRouteName='/details';classAppextendsStatelessWidget{constApp({super.key});@overrideWidgetbuild(BuildContextcontext){returnCupertinoApp(home:constHomePage(),// The [routes] property defines the available named routes// and the widgets to build when navigating to those routes.routes:{detailsPageRouteName:(context)=>constDetailsPage()},);}}

    The following sample generates a list of persons usingmockPersons(). Tapping a person pushes the person's detail page to theNavigator usingpushNamed().

    dart
    ListView.builder(itemCount:mockPersons.length,itemBuilder:(context,index){finalperson=mockPersons.elementAt(index);finalage='${person.age} years old';returnListTile(title:Text(person.name),subtitle:Text(age),trailing:constIcon(Icons.arrow_forward_ios),onTap:(){// When a [ListTile] that represents a person is// tapped, push the detailsPageRouteName route// to the Navigator and pass the person's instance// to the route.Navigator.of(context,).pushNamed(detailsPageRouteName,arguments:person);},);},),
  2. Define theDetailsPage widget that displays the details of each person. In Flutter, you can pass arguments into the widget when navigating to the new route. Extract the arguments usingModalRoute.of():

    dart
    classDetailsPageextendsStatelessWidget{constDetailsPage({super.key});@overrideWidgetbuild(BuildContextcontext){// Read the person instance from the arguments.finalPersonperson=ModalRoute.of(context)?.settings.argumentsasPerson;// Extract the age.finalage='${person.age} years old';returnScaffold(// Display name and age.body:Column(children:[Text(person.name),Text(age)]),);}}

To create more advanced navigation and routing requirements, use a routing package such asgo_router.

To learn more, check outNavigation and routing.

Manually pop back

#

InSwiftUI, you use thedismiss environment value to pop-back to the previous screen.

swift
Button("Pop back"){dismiss()}

InFlutter, use thepop() function of theNavigator class:

dart
TextButton(onPressed:(){// This code allows the// view to pop back to its presenter.Navigator.of(context).pop();},child:constText('Pop back'),),

Navigating to another app

#

InSwiftUI, you use theopenURL environment variable to open a URL to another application.

swift
@Environment(\.openURL)privatevaropenUrl// View code goes hereButton("Open website"){openUrl(URL(string:"https://google.com")!)}

InFlutter, use theurl_launcher plugin.

dart
CupertinoButton(onPressed:()async{awaitlaunchUrl(Uri.parse('https://google.com'));},constText('Open website'),),

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

#

InSwiftUI, you call thepreferredColorScheme() function on aView to use dark mode.

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

dart
constCupertinoApp(theme:CupertinoThemeData(brightness:Brightness.dark),home:HomePage(),);

Styling text

#

InSwiftUI, you use modifier functions to style text. For example, to change the font of aText string, use thefont() modifier:

swift
Text("Hello, world!").font(.system(size:30,weight:.heavy)).foregroundColor(.yellow)

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:CupertinoColors.systemYellow,),),

Styling buttons

#

InSwiftUI, you use modifier functions to style buttons.

swift
Button("Do something"){// do something when button is tapped}.font(.system(size:30,weight:.bold)).background(Color.yellow).foregroundColor(Color.blue)}

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

In the following example:

  • Thecolor property ofCupertinoButton sets itscolor.
  • Thecolor property of the childText widget sets the button text color.
dart
child:CupertinoButton(color:CupertinoColors.systemYellow,onPressed:(){},padding:constEdgeInsets.all(16),child:constText('Do something',style:TextStyle(color:CupertinoColors.systemBlue,fontSize:30,fontWeight:FontWeight.bold,),),),

Using custom fonts

#

InSwiftUI, you can use a custom font in your app in two steps. First, add the font file to your SwiftUI project. After adding the file, use the.font() modifier to apply it to your UI components.

swift
Text("Hello").font(Font.custom("BungeeSpice-Regular",size:40))

InFlutter, you control your resources with a file namedpubspec.yaml. This file is platform agnostic. To add a custom font to your project, follow these steps:

  1. Create a folder calledfonts in the project's root directory. This optional step helps to organize your fonts.

  2. Add your.ttf,.otf, or.ttc font file into thefonts folder.

  3. Open thepubspec.yaml file within the project.

  4. Find theflutter section.

  5. Add your custom font(s) under thefonts section.

    yaml
    flutter:fonts:-family:BungeeSpicefonts:-asset:fonts/BungeeSpice-Regular.ttf

After you add the font to your project, you can use it as in the following example:

dart
Text('Cupertino',style:TextStyle(fontSize:40,fontFamily:'BungeeSpice'),),
Note

Bundling images in apps

#

InSwiftUI, you first add the image files toAssets.xcassets, then use theImage view to display the images.

To add images inFlutter, follow a method similar to how you added custom fonts.

  1. Add animages folder to the root directory.

  2. Add this asset to thepubspec.yaml file.

    yaml
    flutter:assets:-images/Blueberries.jpg

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

  1. Instantiates the given image using the provided path.
  2. Reads the image from the assets bundled with your app.
  3. Displays the image on the screen.

To review a complete example, check out theImage docs.

Bundling videos in apps

#

InSwiftUI, you bundle a local video file with your app in two steps. First, you import theAVKit framework, then you instantiate aVideoPlayer view.

InFlutter, add thevideo_player plugin to your project. This plugin allows you to create a video player that works on Android, iOS, and on the web from the same codebase.

  1. Add the plugin to your app and add the video file to your project.
  2. Add the asset to yourpubspec.yaml file.
  3. Use theVideoPlayerController class to load and play your video file.

To review a complete walkthrough, check out thevideo_player example.

Was this page's content helpful?

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


[8]ページ先頭

©2009-2025 Movatter.jp