Skip to main content

duo_fold 0.1.0 copy "duo_fold: ^0.1.0" to clipboard
duo_fold: ^0.1.0 copied to clipboard

Fold-aware layout for Apple's iPhone Duo in Flutter: pose derivation, split panes, and fold-confined sheets and dialogs, built on package:foldable.

example/main.dart

// Minimal demo: pick a pose, see the layout model decide. No Riverpod
// here and no hardware needed: the fold states are built by hand from
// the geometry Sensecast measured on the Duo simulator. In a real app,
// the states come from duoFoldProvider (see README.md).

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

void main() => runApp(const DuoFoldDemoApp());

class DuoFoldDemoApp extends StatelessWidget {
  const DuoFoldDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'duo_fold demo',
      theme: ThemeData(colorSchemeSeed: Colors.teal),
      home: const DuoFoldDemoPage(),
    );
  }
}

class DuoFoldDemoPage extends StatefulWidget {
  const DuoFoldDemoPage({super.key});

  @override
  State<DuoFoldDemoPage> createState() => _DuoFoldDemoPageState();
}

class _DuoFoldDemoPageState extends State<DuoFoldDemoPage> {
  DuoPose _pose = DuoPose.book;
  bool _glanceEnabled = true;
  bool _bookSplitEnabled = true;

  DuoFoldState get _fold {
    switch (_pose) {
      case DuoPose.book:
        return const DuoFoldState(
          isDuo: true,
          hingeStatus: DuoHingeStatus.partiallyOpen,
          hingeAngleDeg: 90,
          divisionRegion: Rect.fromLTWH(455.5, 0, 40, 669),
        );
      case DuoPose.onTable:
        return const DuoFoldState(
          isDuo: true,
          hingeStatus: DuoHingeStatus.partiallyOpen,
          hingeAngleDeg: 165,
          divisionRegion: Rect.fromLTWH(0, 455.5, 669, 40),
        );
      case DuoPose.propped:
        return const DuoFoldState(
          isDuo: true,
          hingeStatus: DuoHingeStatus.partiallyOpen,
          hingeAngleDeg: 90,
          divisionRegion: Rect.fromLTWH(0, 455.5, 669, 40),
        );
      case DuoPose.flat:
        return const DuoFoldState(
          isDuo: true,
          hingeStatus: DuoHingeStatus.fullyOpen,
          hingeAngleDeg: 180,
          divisionRegion: Rect.fromLTWH(455.5, 0, 40, 669),
        );
      case DuoPose.closed:
        return const DuoFoldState(
          isDuo: true,
          hingeStatus: DuoHingeStatus.closed,
          hingeAngleDeg: 0,
        );
      case DuoPose.unsupported:
        return const DuoFoldState.unsupported();
    }
  }

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.sizeOf(context);
    final mode = FoldLayout.modeFor(
      _fold,
      width: size.width,
      glanceEnabled: _glanceEnabled,
      bookSplitEnabled: _bookSplitEnabled,
    );
    return Scaffold(
      appBar: AppBar(title: const Text('duo_fold demo')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(12),
            child: Wrap(
              spacing: 8,
              children: DuoPose.values.map((pose) {
                return ChoiceChip(
                  label: Text(pose.name),
                  selected: _pose == pose,
                  onSelected: (_) => setState(() => _pose = pose),
                );
              }).toList(),
            ),
          ),
          SwitchListTile(
            title: const Text('Glance enabled'),
            value: _glanceEnabled,
            onChanged: (v) => setState(() => _glanceEnabled = v),
          ),
          SwitchListTile(
            title: const Text('Book split enabled'),
            value: _bookSplitEnabled,
            onChanged: (v) => setState(() => _bookSplitEnabled = v),
          ),
          Padding(
            padding: const EdgeInsets.all(12),
            child: Text(
              'pose: ${_fold.pose.name}  |  mode: ${mode.name}  |  '
              'division: ${_fold.divisionRegion ?? "none"}',
            ),
          ),
          Expanded(
            child: FoldSplitView(
              fold: _fold,
              mode: mode,
              primary: Container(
                color: Colors.teal.shade100,
                alignment: Alignment.center,
                child: const Text('Primary pane'),
              ),
              secondary: Container(
                color: Colors.orange.shade100,
                alignment: Alignment.center,
                child: const Text('Secondary pane'),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
1
likes
0
points
69
downloads

Publisher

unverified uploader

Weekly Downloads

Fold-aware layout for Apple's iPhone Duo in Flutter: pose derivation, split panes, and fold-confined sheets and dialogs, built on package:foldable.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, flutter_riverpod, foldable, shared_preferences

More

Packages that depend on duo_fold