패키지, 저장소 및 앱 카테고리 검색

패키지 상세v1.0.1

responsive_scaffold_nullsafe

모바일에서는 목록을 표시하고 세부 정보로 이동하며, 태블릿에서는 목록과 선택된 항목을 표시합니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
128
좋아요
23
Pub 점수
120

패키지 설치

flutter pub add responsive_scaffold_nullsafe

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

ResponsiveScaffoldNullSafe는 화면 크기에 따라 자동으로 조정되는 반응형 UI 레이아웃을 만들기 위해 설계된 Flutter 패키지입니다. 모바일 기기에서는 목록을 표시하고 푸시를 통해 상세 보기로 이동하지만, 태블릿에서는 목록과 선택된 항목을 옆에 두고 표시합니다. null 안전성을 갖추고 있어 Android, iOS, Web, macOS, Windows, Linux 플랫폼에서 반응형 디자인을 간소화합니다. 사용자 경험을 향상시키기 위해 커스텀 로직 없이 다양한 형태의 장치에 최적화된 레이아웃을 제공합니다.

사용 사례

  • 반응형 목록-세부 정보 인터페이스 구축
  • 모바일 및 태블릿 화면을 위한 UI 적응
  • 일관된 레이아웃으로 다중 플랫폼 앱 만들기
  • 반응형 앱에서 탐색 간소화
  • 확장 가능한 대시보드 레이아웃 설계

주요 기능

  • 기기 크기에 따라 자동 레이아웃 적응
  • 태블릿에서 목록 및 상세 표시를 지원
  • 널 안전한 구현
  • 크로스 플랫폼 호환성
  • 내장형 탐색 처리
  • 기존 Flutter 프로젝트와의 간편한 통합

적합한 대상

  • 반응형 Flutter 앱을 개발하는 개발자
  • 여러 기기 유형을 대상으로 하는 팀
  • 목록-세부 정보 패턴이 필요한 프로젝트
  • 태블릿 최적화 레이아웃이 필요한 앱
  • 재사용 가능한 컴포넌트를 찾는 사용자 인터페이스 중심 개발자

고려 사항

  • Flutter 2.5 이상이 필요합니다
  • 리스트-세부 정보 사용 사례에 가장 적합
  • 복잡한 레이아웃에 맞게 사용자 정의가 필요할 수 있습니다
  • 수평/수직 분할 패턴으로 제한
  • 리스트 기반 UI가 아닌 경우에 적합하지 않음

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Null-Safe Version of Responsive Scaffold

responsive_scaffold_nullsafe

View the online demo here!

On mobile it shows a list and pushes to details and on tablet it shows the List and the selected item.

Online Demo: https://fluttercommunity.github.io/responsive_scaffold/

Getting Started

3 Column Layout

example

Responsive Layout

Follows Material Design Layout Docs.

md-layout

Here is a demo on various sizes.

image image image image image image

Example
import 'package:flutter/material.dart';
import 'package:responsive_scaffold/responsive_scaffold.dart';

class LayoutExample extends StatelessWidget {
  const LayoutExample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ResponsiveScaffold(
      title: const Text('Responsive Layout Example'),
      drawer: ListView(
        children: const <Widget>[
          ListTile(
            leading: Icon(Icons.settings),
            title: Text('Settings Page'),
          ),
          ListTile(
            leading: Icon(Icons.info),
            title: Text('Info Page'),
          ),
          ListTile(
            leading: Icon(Icons.library_books),
            title: Text('Library Page'),
          ),
          ListTile(
            leading: Icon(Icons.help),
            title: Text('Help Page'),
          ),
        ],
      ),
      endIcon: Icons.filter_list,
      endDrawer: ListView(
        children: <Widget>[
          ListTile(
            leading: const Icon(Icons.filter_list),
            title: const Text('Filter List'),
            subtitle: const Text('Hide and show items'),
            trailing: Switch(
              value: true,
              onChanged: (val) {},
            ),
          ),
          const ListTile(
            leading: Icon(Icons.image_aspect_ratio),
            title: Text('Size Settings'),
            subtitle: Text('Change size of images'),
          ),
          ListTile(
            title: Slider(
              value: 0.5,
              onChanged: (val) {},
            ),
          ),
          ListTile(
            leading: const Icon(Icons.sort_by_alpha),
            title: const Text('Sort List'),
            subtitle: const Text('Change layout behavior'),
            trailing: Switch(
              value: false,
              onChanged: (val) {},
            ),
          ),
        ],
      ),
      trailing: IconButton(
        icon: const Icon(Icons.search),
        onPressed: () {},
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Close'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: Theme.of(context).accentColor,
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
    );
  }
}

Responsive List
  • You can use this in two modes ResponsiveListScaffold and ResponsiveListScaffold.builder.
  • On Mobile the ListView will push to the details screen

tablet push mobile

  • On Tablet it will show a Master Detail View.
  • You can add additional Slivers to the Scrollview and the AppBar is optional.
Example
import 'package:flutter/material.dart';
import 'package:responsive_scaffold/responsive_scaffold.dart';

class ListExample extends StatefulWidget {
  const ListExample({Key? key}) : super(key: key);

  @override
  _ListExampleState createState() => _ListExampleState();
}

class _ListExampleState extends State<ListExample> {
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  late List<String> _items;

  @override
  void initState() {
    _items = List.generate(20, (int index) => "test_$index");
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return ResponsiveListScaffold.builder(
      scaffoldKey: _scaffoldKey,
      detailBuilder: (BuildContext context, int? index, bool tablet) {
        final i = _items[index!];
        return DetailsScreen(
          body: ExampleDetailsScreen(
            items: _items,
            row: i,
            tablet: tablet,
            onDelete: () {
              setState(() {
                _items.removeAt(index);
              });
              if (!tablet) Navigator.of(context).pop();
            },
            onChanged: (String value) {
              setState(() {
                _items[index] = value;
              });
            },
          ),
        );
      },
      nullItems: const Center(child: CircularProgressIndicator()),
      emptyItems: const Center(child: Text("No Items Found")),
      slivers: const <Widget>[
        SliverAppBar(
          title: Text("App Bar"),
        ),
      ],
      itemCount: _items.length,
      itemBuilder: (BuildContext context, int index) {
        final i = _items[index];
        return ListTile(
          leading: Text(i),
        );
      },
      bottomNavigationBar: BottomAppBar(
        elevation: 0.0,
        child: IconButton(
          icon: const Icon(Icons.share),
          onPressed: () {},
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text("Snackbar!"),
            ),
          );
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

class ExampleDetailsScreen extends StatelessWidget {
  const ExampleDetailsScreen({
    Key? key,
    required List<String> items,
    required this.row,
    required this.tablet,
    required this.onDelete,
    required this.onChanged,
  })   : _items = items,
        super(key: key);

  final List<String> _items;
  final String row;
  final bool tablet;
  final VoidCallback onDelete;
  final ValueChanged<String> onChanged;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0.0,
        automaticallyImplyLeading: !tablet,
        title: const Text("Details"),
        actions: [
          IconButton(
            icon: const Icon(Icons.share),
            onPressed: () {
              onChanged("$row ${DateTime.now().toString()}");
            },
          ),
          IconButton(
            icon: const Icon(Icons.delete),
            onPressed: onDelete,
          ),
        ],
      ),
      bottomNavigationBar: BottomAppBar(
        elevation: 0.0,
        child: IconButton(
          icon: const Icon(Icons.share),
          onPressed: () {},
        ),
      ),
      body: Center(
        child: Text("Item: $row"),
      ),
    );
  }
}

카테고리

의존성

의존성 목록 1 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.