---
title: 'Flutter'
description: 'Use TwicPics Flutter Widget to get images and videos integration best practices out-of-the-box.'
category: 'components'
position: 2
---

# Flutter

<illustration src="github/components-flutter/main/resources/flutter-cover.png" width="1906" height="764" alt="TwicPics Flutter Widgets"></illustration>

<docs-page-description :description="description"></docs-page-description>

`TwicPics Flutter Widget` is available as a [Flutter Package](https://pub.dev/packages/twicpics_components).

## Installation

Add the `twicpics_components` package to your `Flutter` project by running:

```bash
flutter pub add twicpics_components
```

## Setup

### Install TwicPics in your Flutter project

<doc-alert type="info">You will need a TwicPics domain to initialize the package. <a href="https://account.twicpics.com/signup" target="_blank">Create an account for free</a> to get your domain.</doc-alert>

```dart
// main.dart

import 'package:twicpics_components/twicpics_components.dart';

void main() {
  install(
    domain: "https://<your-domain>.twic.pics/",
  );
  runApp(...);
}
```

For an exhaustive list of options, see [Setup Options](#setup-options).

### Setup Options

| Option | Description | Type | Default |
| :- | :- | :- | :- |
| `cacheCleanOnStartUp` | Clears the cache when the application starts. | `boolean` | `false` |
| `cacheStalePeriod` | Defines the duration of validity of a cached asset. | `Duration` | `Duration( days: 7)` |
| `cacheMaxNrOfObjects` | Defines how large the cache is allowed to be. | `Integer` | `200` |
| `debug` | Activate logs from the cache manager. | `boolean` | `false` |
| `domain` | This is your very own [TwicPics domain](https://www.twicpics.com/docs/essentials/domain-configuration). Providing it is **mandatory**. | `String` | |
| `maxDPR` | [TwicPics](https://www.twicpics.com/) will take the "Device Pixel Ratio" (`DPR`) of the current device into consideration when determining the sizes of images to load. By default, it will not take a `DPR` greater than `2` into consideration. If the `DPR` of the device is higher than `2`, [TwicPics](https://www.twicpics.com/) will assume it to be `2`. Using `maxDPR`, you can lower this limit down to `1` or be more permissive (for instance by setting it to `3` or `4`). | `Number`  | `2` |
| `path` | Path to prepend to all src attributes. For instance, if path is `"some/folder"` then a src attribute set to `"image.jpg"` will be expanded into `"some/folder/image.jpg"` | `String` | |
| `step`   | To avoid requesting too may variants of the same image, [TwicPics](https://www.twicpics.com/) will round the width of images to the closest multiple of step. The height will then be computed in order to respect the original aspect ratio. | `Integer` | `50` |

## Usage

`TwicImg` and `TwicVideo` come as `Flutter Widgets` and are used as [such](https://docs.flutter.dev/ui/widgets-intro).

### Basic usage

```dart
// my_widget.dart

import 'package:twicpics_components/twicpics_components.dart';

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    return TwicImg(
      src: 'path/to/my/image',
    );
  }
}
```

### Bulk loading

When embedding `TwicImg` or `TwicVideo` in a lazily loading-compatible tree, it is recommended to disable lazy-loading feature:

```dart
// grid_sample.dart

class GridSample extends StatelessWidget {
  const GridSample({super.key});
  @override
  Widget build(BuildContext context) {
    return GridView.count(
      primary: false,
      crossAxisCount: 3,
      children: [
        TwicImg(
          src: 'path/to/my/image',
          eager: true,
        ),
        TwicVideo(
          src: 'path/to/my/video',
          eager: true,
        ),
        // ...
      ]
    );
}
```

### Choose your focus

You can control the crop function by using the `focus` property.

Read more about [focus](https://www.twicpics.com/docs/reference/transformations#focus).

#### Set the focus point to coordinates

```dart
// my_widget.dart

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    return TwicImg(
      src: 'path/to/my/image',
      focus: '30px40p', // this will set the focus point coordinates using relative lengths
    );
  }
}
```

```dart
// my_widget.dart

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    return TwicImg(
      src: 'path/to/my/image',
      focus: '345x678', // this will set the focus point coordinates using absolute lengths
    );
  }
}
```

#### Set the focus automagically

```dart
// my_widget.dart

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    return TwicImg(
      src: 'path/to/my/image',
      focus: 'auto', // the focus point will be chosen automagically for you
    );
  }
}
```

<doc-alert type="warning">
Note that <code>auto</code> is not implemented for videos yet and is only available for <code>TwicImg</code>. 
</doc-alert>

### Working with ratio="none"

Allows to display both image or video with a __free height__ while respecting its __natural aspect-ratio__.

#### Hero image

An image that occupies all available space:

```dart
// my_widget.dart

import 'package:flutter/material.dart';
import 'package:twicpics_components/twicpics_components.dart';

class HeroSample extends StatelessWidget {
  const HeroSample({super.key});
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: TwicImg(
        src: 'path/to/my/image.jpg',
          ratio: 'none',
        ),
    );
  }
}
```

#### Hero video

An video that occupies all available space:

```dart
// my_widget.dart

import 'package:flutter/material.dart';
import 'package:twicpics_components/twicpics_components.dart';

class HeroSample extends StatelessWidget {
  const HeroSample({super.key});
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: TwicVideo(
        src: 'path/to/my/video.jpg',
          ratio: 'none',
        ),
    );
  }
}
```

#### Hero banner

You can specify the height of your image (or video) while respecting its __natural aspect-ratio__ and optimizing your Cumulative Layout Shift (CLS) metric.

```dart
// my_widget.dart

import 'package:flutter/material.dart';
import 'package:twicpics_components/twicpics_components.dart';

class HeroBanner extends StatelessWidget {
  const HeroBanner({super.key});
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 200,
      child: TwicImg(
        src: 'path/to/my/image.jpg',
        ratio: 'none',
      ),
    );
  }
}
```

### Reframe your image

You can **reframe** your image on the **main subject(s)** it contains.

In **cover** `mode`, the resulting image will respect `ratio` while maximizing the area occupied by the main subject(s).

In **contain** `mode`, the image will be cropped as close as possible to the main subject(s).

To activate automatic cropping, simply add the `refit` property to your widget call.

Read more about [refit](https://www.twicpics.com/docs/reference/transformations#refit).

```dart
// my_widget.dart

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    return TwicImg(
      anchor: TwicPosition.right, // will align main subject(s) with the right border
      src: 'path/to/my/image',
      mode: TwicMode.cover, // will maximize the area occupied by the main subject(s) in a squared area
      refit: '10p', // will add a 10% padding around the main subject(s)
    );
  }
}
```

```dart
// my_widget.dart

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});
  @override
  Widget build(BuildContext context) {
    return TwicImg(
      src: 'path/to/my/image',
      mode: TwicMode.contain, // will crop the image as close as possible to main subject(s)
      refit: true, // default refit without any padding
    );
  }
}
```

<doc-alert type="warning">
Note that <code>refit</code> is not implemented for videos yet and is only available for <code>TwicImg</code>.
</doc-alert>

### Working with Row Widget

When using [Row Widget](https://api.flutter.dev/flutter/widgets/Row-class.html) you have to **constrain available width** for `TwicImg` as in:

```dart
import 'package:flutter/material.dart';
import 'package:twicpics_components/twicpics_components.dart';

class RowSample extends StatelessWidget {
  const RowSample({super.key});
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        SizedBox(
          width: 100, //fixed width
          child: TwicImg(
            src:'path/to/my/image',
          ),
        ),
        Expanded( // makes child fills the available space
          child: TwicVideo(
            src:'path/to/my/video',
          ),
        ),
      ],
    );
  }
}
```

## Widget Properties

### TwicImg

```dart
TwicImg( 
  { 
      Key? key,
      TwicPosition? anchor,
      bool? eager,
      String? focus,
      String? intrinsic,
      TwicMode? mode,
      TwicPlaceholder? placeholder,
      TwicPosition? position,
      String? preTransform,
      <String? | double?> ratio,
      <String? | bool?> refit,
      required String src,
      int? step,
      Duration? transitionDuration,
  } 
)
```

| Attribute | Description | Type | Default |
| :- | :- | :- | :- |
| `key` | Keeps widget state when parent tree rebuilds. | [Key](https://api.flutter.dev/flutter/widgets/Widget/key.html) | |
| `anchor` | Positions the image in both `TwicMode.contain` and `TwicMode.cover` mode. `position` and `focus` take precedence in `TwicMode.contain` and `TwicMode.cover` mode respectively. Please note that `anchor` is applied **after** an eventual `preTransform`. | [TwicPosition](#twicposition-enum) | |
| `eager` | Load the image as soon as the widget is mounted. This effectively means disabling lazy loading for this image. Recommended when `TwicImg` is placed within a parent that natively handles lazy-loading. | `boolean` | `false` |
| `focus` | Sets the focus point in `TwicMode.cover` mode. `focus` takes precedence over `anchor` when both are provided. See the [TwicPics focus attribute documentation](https://www.twicpics.com/docs/reference/native-attributes#data-twic-focus) for more information. Only use this attribute if you need a specific focus point or if you want to leverage smart cropping with `focus="auto"`: if you only need border-based positionning ([TwicPosition](#twicposition-enum) values), use `anchor` instead.  | `String` | |
| `intrinsic` | Dimensions in pixels of the **original** image, formatted `<width>x<height>` (eg. 1920x1080). It prevents image upscaling and limits the number of generated variants. If using `preTransform`, you should specify the intrinsic dimensions of the **resulting** image. Using incorrect values can lead to display issues, see the [intrinsic attribute documentation](https://www.twicpics.com/docs/reference/native-attributes#data-twic-intrinsic). `String`  | |
| `mode` | Determines if the image fills the area and is cropped accordingly (`TwicMode.cover`) or if the image will sit inside the area with no cropping (`TwicMode.contain`). | [TwicMode](#twicmode-enum) | `TwicMode.cover` |
| `placeholder` | Displays a low quality version before the final image is actually loaded. | [TwicPlaceholder](#twicplaceholder-enum) | `TwicPlaceholder.preview` |
 `position` | Positions the image in `TwicMode.contain` mode. `position` takes precedence over `anchor` when both are provided. Only use this property if you need precise positionning: if you only need border-based positionning ([TwicPosition](#twicposition-enum) values), use `anchor` instead. | [TwicPosition](#twicposition-enum) | `TwicPosition.center` |
| `preTransform` | A slash-separated list of [TwicPics API transformations](https://www.twicpics.com/docs/reference/transformations) to be performed before resizing the image (see the [TwicPics Manipulation documentation](https://www.twicpics.com/docs/reference/transformations)). Note that `anchor` and `focus` are applied **after** `preTransform`: if you need to specify a specific focus point for your `preTransform` then it needs to be part of the expression (like `preTransform="focus=auto/crop=50px50p"` for instance). Be aware that using this option can lead to unexpected results so use with caution! | `String` | |
| `ratio` | A unitless `width/height` or `width:height` value pair (as in `4/3` or `4:3`) that defines the aspect ratio of the display area. If `height` is not specified, it is assumed to be `1`. A square area will be created by default. When set to `none`, ratio is determined based on width and height as computed by the Flutter following the parent size definitions. You are responsible for properly sizing the component when `ratio="none"`. | `String or number` | `1` |
| `refit` | Reframes the image to maximize the area occupied by the main object(s) while respecting `ratio` in `cover` mode. Crops the image as close as possible to the main object(s) in `contain` mode. Can be `true`, `false` or a list of comma-separated [length](https://www.twicpics.com/docs/reference/parameters#length) defining padding. See the [TwicPics refit documentation](https://www.twicpics.com/docs/reference/transformations#refit) for more information.| `boolean or String` | `false` |
| `src` | Mandatory path to the image. | `String` | |
| `step` | See the [TwicPics step attribute documentation](https://www.twicpics.com/docs/reference/native-attributes#data-twic-step) for more information. | `int` |  |
| `transitionDuration` | Duration of the transition effect between placeholder and the final image. | `Duration` | `Duration( milliseconds: 400 )` |

### TwicVideo

```dart
TwicVideo( 
  { 
      Key? key,
      TwicPosition? anchor,
      <String? | double?> duration,
      bool? eager,
      String? focus,
      <String? | double?> from,
      String? intrinsic,
      TwicMode? mode,
      <String? | double?> posterFrom,
      TwicPlaceholder? placeholder,
      TwicPosition? position,
      String? preTransform,
      <String? | double?> posterFrom,
      <String? | double?> ratio,
      required String src,
      <String? | double?> to,
      int? step,
      Duration? transitionDuration,
  } 
)
```

| Attribute | Description | Type | Default |
| :- | :- | :- | :- |
| `key` | Keeps widget state when parent tree rebuilds. | [Key](https://api.flutter.dev/flutter/widgets/Widget/key.html) | |
| `anchor` | Positions the video in both `TwicMode.contain` and `TwicMode.cover` mode. `position` and `focus` take precedence in `TwicMode.contain` and `TwicMode.cover` mode respectively. Please note that `anchor` is applied **after** an eventual `preTransform`. | [TwicPosition](#twicposition-enum) | |
| `duration` | Limits the duration of the video. `duration` is expressed in seconds and must be a positive number. `duration` will not move the starting point of the video: to do so, you'll have to use the `from` property. See [duration documentation](https://www.twicpics.com/docs/reference/transformations#duration). | `String or number` | |
| `eager` | Load the video as soon as the widget is mounted. This effectively means disabling lazy loading for this video. Recommended when `TwicVideo` is placed within a parent that natively handles lazy-loading. | `boolean` | `false` |
| `focus` | Sets the focus point in `TwicMode.cover` mode. `focus` takes precedence over `anchor` when both are provided. See the [TwicPics focus attribute documentation](https://www.twicpics.com/docs/reference/native-attributes#data-twic-focus) for more information. Only use this attribute if you need a specific focus point: if you only need border-based positionning ([TwicPosition](#twicposition-enum) values), use `anchor` instead.  | `String` | |
| `from` | Moves the starting point of the video. `from` is expressed in seconds and must be a positive number. `from` will not move the end point of the video: to do so, you'll have to use the `duration` or `to` properties. See from documentation. See [from documentation](https://www.twicpics.com/docs/reference/transformations#from). | `String or number` | |
| `intrinsic` | Dimensions in pixels of the **original** video, formatted `<width>x<height>` (eg. 1920x1080). It prevents video upscaling and limits the number of generated variants. If using `preTransform`, you should specify the intrinsic dimensions of the **resulting** video. Using incorrect values can lead to display issues, see the [intrinsic attribute documentation](https://www.twicpics.com/docs/reference/native-attributes#data-twic-intrinsic). `String`  | |
| `mode` | Determines if the video fills the area and is cropped accordingly (`TwicMode.cover`) or if the video will sit inside the area with no cropping (`TwicMode.contain`). | [TwicMode](#twicmode-enum) | `TwicMode.cover` |
| `placeholder` | Displays a low quality version before the final video is actually loaded. | [TwicPlaceholder](#twicplaceholder-enum) | `TwicPlaceholder.preview` |
 `position` | Positions the video in `TwicMode.contain` mode. `position` takes precedence over `anchor` when both are provided. Only use this property if you need precise positionning: if you only need border-based positionning ([TwicPosition](#twicposition-enum) values), use `anchor` instead. | [TwicPosition](#twicposition-enum) | `TwicPosition.center` |
| `posterFrom` | Determines which frame of the source video should be used as a poster / preview. `posterFrom` is expressed in seconds and must be a positive number. By default `posterFrom` is equal to 0, meaning the very first frame of the video is used. `posterFrom` will not modify the video in any way: to do so, you'll have to use the `duration`, `from` or `to` properties. | `String or number` | |
| `preTransform` | A slash-separated list of [TwicPics API transformations](https://www.twicpics.com/docs/reference/transformations) to be performed before resizing the video (see the [TwicPics Manipulation documentation](https://www.twicpics.com/docs/reference/transformations)). Note that `anchor` and `focus` are applied **after** `preTransform`: if you need to specify a specific focus point for your `preTransform` then it needs to be part of the expression (like `preTransform="focus=20px30p/crop=50px50p"` for instance). Be aware that using this option can lead to unexpected results so use with caution! | `String` | |
| `ratio` | A unitless `width/height` or `width:height` value pair (as in `4/3` or `4:3`) that defines the aspect ratio of the display area. If `height` is not specified, it is assumed to be `1`. A square area will be created by default. When set to `none`, ratio is determined based on width and height as computed by the Flutter following the parent size definitions. You are responsible for properly sizing the component when `ratio="none"`. | `String or number` | `1` |
| `src` | Mandatory path to the video. | `String` | |
| `step` | See the [TwicPics step attribute documentation](https://www.twicpics.com/docs/reference/native-attributes#data-twic-step) for more information. | `int` |  |
| `to` | Moves the end point of the video. `to` is expressed in seconds and must be a positive number. `to` will not move the starting point of the video: to do so, you'll have to use the `from` property. See [to documentation](https://www.twicpics.com/docs/reference/transformations#to). | `String or number` | |
| `transitionDuration` | Duration of the transition effect between placeholder and the video or its poster. | `Duration` | `Duration( milliseconds: 400 )` |

### TwicMode enum

Defines how assets should be resized to fit its container.

| Value | Description |
| :- | :- |
| `contain` | resize asset so that it completely fits inside the target area while conserving the original aspect ratio. |
| `cover` | resize asset so that it completely fills the target area while conserving the original aspect ratio. |

### TwicPosition enum

Defines a position within the parent container.

| Value | Description |
| :- | :- |
| `bottom` | The center point along the bottom edge. |
| `bottomLeft` | The bottom left corner. |
| `bottomRight` | The bottom right corner. |
| `center` | The center point, both horizontally and vertically. |
| `left` | The center point along the left edge. |
| `right` | The center point along the right edge. |
| `top` | The center point along the top edge. |
| `topLeft` | The top left corner. |
| `topRight` | The top right corner. |

### TwicPlaceholder enum

Defines placeholder characteristics.

| Value | Description |
| :- | :- |
| `preview` | displays a **blurry preview** of requested asset. |
| `maincolor` | fills container with a solid color containing the **most important** color in the requested asset. |
| `meancolor` | fills container with a solid color containing the **mean color** in the requested asset. |
| `none` | displays an empty container. |

## Feedback and support

TwicPics Flutter Widgets are open-source on GitHub. For features requests and bugs, [open an issue](https://github.com/TwicPics/components-flutter/issues). The TwicPics team also remains available for support via the live chat (at the bottom right.)
