Как создать SliverAppBar с пользовательской панелью приложений и изображением в Flutter?

#flutter #dart

Вопрос:

Я хочу создать приложение, в котором я использую SliverAppBar с моей пользовательской панелью, но я также хочу сделать это с фоновым изображением.

Изображение результата

img_result

После прокрутки результат должен быть

img_result_after_scroll

Но сейчас я не знаю, как это сделать. Пожалуйста, помогите мне.

Мой код:

 CustomScrollView(
    slivers: <Widget>[
      SliverAppBar(
        pinned: true,
        expandedHeight: MediaQuery.of(context).size.height * 0.4,
        flexibleSpace: FlexibleSpaceBar(
            background: Image.network(
          "image url",
          fit: BoxFit.cover,
        )),
      ),
      SliverList(
        // Use a delegate to build items as they're scrolled on screen.
        delegate: SliverChildListDelegate([
          Container() // some content
        ]),
      ),
    ],
  )
 

Комментарии:

1. чтобы изменить цвет при прокрутке с помощью scrollcontroller, перейдите по этой ссылке gist.github.com/ianldgs/794884d8837b83fd9c64e06d9b90af4e

Ответ №1:

Пожалуйста,проверьте это,дайте мне знать, работает ли это для вас, также, чтобы изменить цвет, вам нужно прослушать прокрутку, а затем изменить пользовательский цвет

PS: Чтобы использовать пользовательское изображение FlutterLogo , замените его своим изображением

 import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
              pinned: true,
              leading: Icon(Icons.arrow_back),
              expandedHeight: 160.0,
              flexibleSpace: const FlexibleSpaceBar(
                background: FlutterLogo(),
              ),
              actions: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: CircleAvatar(
                    radius: 28.0,
                    backgroundImage: NetworkImage(
                        'https://images.unsplash.com/photo-1547721064-da6cfb341d50'),
                  ),
                )
              ]),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  color: index.isOdd ? Colors.white : Colors.black12,
                  height: 100.0,
                  child: Center(
                    child: Text('$index', textScaleFactor: 5),
                  ),
                );
              },
              childCount: 20,
            ),
          ),
        ],
      ),
    );
  }
}
 

Комментарии:

1. Также существует простой обходной путь для изменения цвета background color SliverAppBar и использования CachedNetworkImage в фоновом режиме в пространстве FlexibleSpace. Но если у вас есть только этот дизайн, вы можете использовать это,в противном случае вы используете ScrollController, Проблема в том, что он будет отображать цвет панели приложений как зеленый, если для загрузки изображения требуется время, он будет отображаться зеленым до тех пор, пока изображение не загрузится, поэтому вам нужно использовать cacheimge pacakge, с помощью pacakage вы можете показывать индикатор прогресса до тех пор, пока изображение не загрузится в виджет@Slava

2. У меня проблема, я использовал пользовательскую панель приложений, потому что я мог бы изменить заполнение в панели приложений, но теперь я не могу, как это исправить? Когда я изменяю заполнение действий, оно изменяет их высоту на небольшое значение

3. можете ли вы показать код и скриншот… ? для этого попробуйте удалить отступы из действий, если это не сработает @Слава

Ответ №2:

Вы должны обратиться к приведенному ниже коду :

 import 'package:flutter/material.dart';

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

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

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

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  bool _pinned = true;
  bool _snap = false;
  bool _floating = false;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: _pinned,
            snap: _snap,
            floating: _floating,
            expandedHeight: 160.0,
            flexibleSpace: const FlexibleSpaceBar(
              title: Text('SliverAppBar'),
              background: FlutterLogo(),
            ),
          ),
         
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  color: index.isOdd ? Colors.white : Colors.black12,
                  height: 100.0,
                  child: Center(
                    child: Text('$index', textScaleFactor: 5),
                  ),
                );
              },
              childCount: 20,
            ),
          ),
        ],
      ),
      bottomNavigationBar: BottomAppBar(
        child: Padding(
          padding: const EdgeInsets.all(8),
          child: OverflowBar(
         //   alignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Row(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const Text('pinned'),
                  Switch(
                    onChanged: (bool val) {
                      setState(() {
                        _pinned = val;
                      });
                    },
                    value: _pinned,
                  ),
                ],
              ),
              Row(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const Text('snap'),
                  Switch(
                    onChanged: (bool val) {
                      setState(() {
                        _snap = val;
                        // Snapping only applies when the app bar is floating.
                        _floating = _floating || _snap;
                      });
                    },
                    value: _snap,
                  ),
                ],
              ),
              Row(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const Text('floating'),
                  Switch(
                    onChanged: (bool val) {
                      setState(() {
                        _floating = val;
                        _snap = _snap amp;amp; _floating;
                      });
                    },
                    value: _floating,
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}
 

Комментарии:

1. Но этот код не содержит пользовательской панели, я хочу изменить панель flutter sliverapp на мое пользовательское решение (второе изображение)

Ответ №3:

Просто, например:

 import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  var scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: DefaultTabController(
      length: 2,
      child: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return [
            SliverAppBar(
              expandedHeight: 200.0,
              floating: true,
              pinned: true,
              snap: true,
              actionsIconTheme: IconThemeData(opacity: 0.0),
              flexibleSpace: Stack(
                children: <Widget>[
                  Positioned.fill(
                    child: Image.network(
                      "https://content.presspage.com/uploads/2658/c800_logo-stackoverflow-square.jpg?98978",
                      fit: BoxFit.cover,
                    ),
                  ),
                ],
              ),
            ),
            SliverPadding(
              padding: EdgeInsets.all(16.0),
              sliver: SliverList(
                delegate: SliverChildListDelegate([
                  TabBar(
                    labelColor: Colors.black87,
                    unselectedLabelColor: Colors.grey,
                    tabs: [
                      Tab(icon: Icon(Icons.info), text: "Tab 1"),
                      Tab(
                        icon: Icon(Icons.lightbulb_outline),
                        text: "Tab 2",
                      ),
                    ],
                  ),
                ]),
              ),
            ),
          ];
        },
        body: Container(
          height: 700,
          color: Colors.blue,
        ),
      ),
    ));
  }
}
 

Комментарии:

1. Это выглядит нормально, однако я хочу использовать панель приложений, которую я показал вам на втором изображении

2. @Слава, используйте гибкое пространство со строкой, содержащей значок, цвет фона (Контейнер с родительским элементом строки) и Контейнер с изображением и рамкой 😀

3. Но фоновое изображение видно при прокрутке, не так ли?

4. Я точно не знаю, друг, сделай тест; это лучший вариант