sliding_up_panel 1.0.2

  • Readme
  • Changelog
  • Example
  • Installing
  • 98

sliding_up_panel #

pub package GitHub Stars Platform

A draggable Flutter widget that makes implementing a SlidingUpPanel much easier! Based on the Material Design bottom sheet component, this widget works on both Android & iOS.

Example Example App Closed Example App Open


Installing #

Add the following to your pubspec.yaml file:

dependencies:
  sliding_up_panel: ^1.0.2

Note that v1.0.0 introduced some breaking changes outlined below.


Simple Usage #

There are two ways which the SlidingUpPanel can easily be added to your project.

  1. Using the SlidingUpPanel as the root widget for the body (recommended).
  2. Nesting the SlidingUpPanel

This method is recommended as it allows for the least interference with the behavior of other UI elements. For example:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("SlidingUpPanelExample"),
    ),
    body: SlidingUpPanel(
      panel: Center(
        child: Text("This is the sliding Widget"),
      ),
      body: Center(
        child: Text("This is the Widget behind the sliding panel"),
      ),
    ),
  );
}

Nesting the SlidingUpPanel

This method isn't recommended but can still be used. Only use this to avoid refactoring large chunks of code or to implement custom scrolling behavior. For example, the SlidingUpPanel can be nested inside of a Stack (note that there are many other possible implementations that vary on a case-by-case basis).

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("SlidingUpPanelExample"),
    ),
    body: Stack(
      children: <Widget>[
        Center(child: Text("This is the Widget behind the sliding panel"),),

        SlidingUpPanel(
          panel: Center(child: Text("This is the sliding Widget"),),
        )
      ],
    )
  );
}

Screenshots

Both methods produce the same result:

Panel Closed Panel Midway Panel Open




Custom Usage #

There are several options that allow for more control:

PropertiesDescription
panelThe Widget that slides into view. When the panel is collapsed and if collapsed is null, then top portion of this Widget will be displayed; otherwise, collapsed will be displayed overtop of this Widget.
panelBuilder [beta]NOTE: This feature is still in beta and may have some problems. Please open an issue on GitHub if you encounter something unexpected.

Provides a ScrollController to attach to a scrollable object in the panel that links the panel position with the scroll position. Useful for implementing an infinite scroll behavior. If panel and panelBuilder are both non-null, panel will be used.
collapsedThe Widget displayed overtop the panel when collapsed. This fades out as the panel is opened.
bodyThe Widget that lies underneath the sliding panel. This Widget automatically sizes itself to fill the screen.
headerOptional persistent widget that floats above the panel and attaches to the top of the panel. Content at the top of the panel will be covered by this widget. Add padding to the top of the panel to avoid coverage.
footerOptional persistent widget that floats above the panel and attaches to the bottom of the panel. Content at the bottom of the panel will be covered by this widget. Add padding to the bottom of the panel to avoid coverage.
minHeightThe height of the sliding panel when fully collapsed.
maxHeightThe height of the sliding panel when fully open.
snapPoint [beta]NOTE: This feature is still in beta and may have some problems. Please open an issue on GitHub if you encounter something unexpected.

A point between minHeight and maxHeight that the panel snaps to while animating. A fast swipe on the panel will disregard this point and go directly to the open/close position. This value is represented as a percentage of the total animation distance (maxHeight - minHeight), so it must be between 0.0 and 1.0, exclusive.
borderA border to draw around the sliding panel sheet.
borderRadiusIf non-null, the corners of the sliding panel sheet are rounded by this.
boxShadowA list of shadows cast behind the sliding panel sheet.
colorThe color to fill the background of the sliding panel sheet.
paddingThe amount to inset the children of the sliding panel sheet.
marginEmpty space surrounding the sliding panel sheet.
renderPanelSheetSet to false to not to render the sheet the panel sits upon. This means that only body, collapsed, and the panel Widgets will be rendered. Set this to false if you want to achieve a floating effect or want more customization over how the sliding panel looks like.
panelSnappingSet to false to disable the panel from snapping open or closed.
backdropEnabledIf non-null, shows a darkening shadow over the body as the panel slides open.
backdropColorShows a darkening shadow of this Color over the body as the panel slides open.
backdropOpacityThe opacity of the backdrop when the panel is fully open. This value can range from 0.0 to 1.0 where 0.0 is completely transparent and 1.0 is completely opaque.
backdropTapClosesPanelFlag that indicates whether or not tapping the backdrop closes the panel. Defaults to true.
controllerIf non-null, this can be used to control the state of the panel.
onPanelSlideIf non-null, this callback is called as the panel slides around with the current position of the panel. The position is a double between 0.0 and 1.0 where 0.0 is fully collapsed and 1.0 is fully open.
onPanelOpenedIf non-null, this callback is called when the panel is fully opened.
onPanelClosedIf non-null, this callback is called when the panel is fully collapsed.
parallaxEnabledIf non-null and true, the SlidingUpPanel exhibits a parallax effect as the panel slides up. Essentially, the body slides up as the panel slides up.
parallaxOffsetAllows for specifying the extent of the parallax effect in terms of the percentage the panel has slid up/down. Recommended values are within 0.0 and 1.0 where 0.0 is no parallax and 1.0 mimics a one-to-one scrolling effect. Defaults to a 10% parallax.
isDraggableAllows toggling of draggability of the SlidingUpPanel. Set this to false to prevent the user from being able to drag the panel up and down. Defaults to true.
slideDirectionEither SlideDirection.UP or SlideDirection.DOWN. Indicates which way the panel should slide. Defaults to UP. If set to DOWN, the panel attaches itself to the top of the screen and is fully opened when the user swipes down on the panel.
defaultPanelStateThe default state of the panel; either PanelState.OPEN or PanelState.CLOSED. This value defaults to PanelState.CLOSED which indicates that the panel is in the closed position and must be opened. PanelState.OPEN indicates that by default the Panel is open and must be swiped closed by the user.


Darkening the Body as the Panel Opens #

If desired, the body can be darkened as the panel is opened by setting backdropEnabled to true. You can also customize the backdropColor, backdropOpacity, and backdropTapClosesPanel. For example:

@override
Widget build(BuildContext context){
  return Material(
    child: SlidingUpPanel(
      backdropEnabled: true,
      panel: Center(
        child: Text("This is the sliding Widget"),
      ),
      body: Scaffold(
        appBar: AppBar(
          title: Text("SlidingUpPanelExample"),
        ),
        body:  Center(
          child: Text("This is the Widget behind the sliding panel"),
        ),
      ),
    ),
  );
}

Notice how the Scaffold is nested inside of the SlidingUpPanel. This because the backdrop is rendered only over the body of the SlidingUpPanel. As a result, if we want the backdrop to appear over the AppBar, then we must nest the Scaffold this way.

Panel Closed Panel Midway Panel Open



Displaying a Different Child When the Panel is Closed #

By assigning a non-null Widget to the collapsed property, you can add a Widget that displays overtop the panel when collapsed. As the panel is opened, this Widget will fade out to display the panel underneath. For example:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("SlidingUpPanelExample"),
    ),
    body: SlidingUpPanel(
      panel: Center(
        child: Text("This is the sliding Widget"),
      ),
      collapsed: Container(
        color: Colors.blueGrey,
        child: Center(
          child: Text(
            "This is the collapsed Widget",
            style: TextStyle(color: Colors.white),
          ),
        ),
      ),
      body: Center(
        child: Text("This is the Widget behind the sliding panel"),
      ),
    ),
  );
}

Panel Closed Panel Midway Panel Open



Rounding the Borders #

Modern design principles (especially in the Material Design Refresh) emphasize rounded borders. A similar effect can be easily achieved by providing a non-null BorderRadiusGeometry to the borderRadius property. Note that this only curves the border on the underlying panel sheet: any children passed to panel or collapsed must also have their borders curved separately in order to achieve a uniform effect. For example:

@override
Widget build(BuildContext context) {
  BorderRadiusGeometry radius = BorderRadius.only(
    topLeft: Radius.circular(24.0),
    topRight: Radius.circular(24.0),
  );

  return Scaffold(
    appBar: AppBar(
      title: Text("SlidingUpPanelExample"),
    ),
    body: SlidingUpPanel(
      panel: Center(
        child: Text("This is the sliding Widget"),
      ),

      collapsed: Container(
        decoration: BoxDecoration(
          color: Colors.blueGrey,
          borderRadius: radius
        ),
        child: Center(
          child: Text(
            "This is the collapsed Widget",
            style: TextStyle(color: Colors.white),
          ),
        ),
      ),

      body: Center(
        child: Text("This is the Widget behind the sliding panel"),
      ),

      borderRadius: radius,
    ),
  );
}

Panel Closed Panel Midway Panel Open



Creating A Floating Effect #

To create a fully custom effect, the default panel sheet can be completely hidden and only the children rendered (i.e. only body, panel, and collapsed are rendered). To do this, set the renderPanelSheet property to false. For example, to create a floating effect:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("SlidingUpPanelExample"),
    ),
    body: SlidingUpPanel(
      renderPanelSheet: false,
      panel: _floatingPanel(),
      collapsed: _floatingCollapsed(),
      body: Center(
        child: Text("This is the Widget behind the sliding panel"),
      ),
    ),
  );
}

Widget _floatingCollapsed(){
  return Container(
    decoration: BoxDecoration(
      color: Colors.blueGrey,
      borderRadius: BorderRadius.only(topLeft: Radius.circular(24.0), topRight: Radius.circular(24.0)),
    ),
    margin: const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),
    child: Center(
      child: Text(
        "This is the collapsed Widget",
        style: TextStyle(color: Colors.white),
      ),
    ),
  );
}

Widget _floatingPanel(){
  return Container(
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.all(Radius.circular(24.0)),
      boxShadow: [
        BoxShadow(
          blurRadius: 20.0,
          color: Colors.grey,
        ),
      ]
    ),
    margin: const EdgeInsets.all(24.0),
    child: Center(
      child: Text("This is the SlidingUpPanel when open"),
    ),
  );
}

Note that a similar effect can be created by simply adding a margin to the SlidingUpPanel.

Panel Closed Panel Midway Panel Open



Adding Scrollable Elements to the Sliding Panel #

The panel itself can contain Scrollable elements. As of v1.0.0, you can link the scroll position of the Scrollable elements with the position of the sliding up panel by using the panelBuilder. For example:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("SlidingUpPanelExample"),
    ),
    body: SlidingUpPanel(
      panelBuilder: (ScrollController sc) => _scrollingList(sc),
      body: Center(
        child: Text("This is the Widget behind the sliding panel"),
      ),
    ),
  );
}

Widget _scrollingList(ScrollController sc){
  return ListView.builder(
    controller: sc,
    itemCount: 50,
    itemBuilder: (BuildContext context, int i){
      return Container(
        padding: const EdgeInsets.all(12.0),
        child: Text("$i"),
      );
    },
  );
}

Panel Closed Panel Midway Panel Open



Using the PanelController #

At times, it can be useful to manually change the state of the SlidingUpPanel. This can be easily achieved by using a PanelController and attaching it to an instance of the SlidingUpPanel. Note that since the PanelController modifies the state of a SlidingUpPanel, these methods can only be called after the SlidingUpPanel has been rendered.

PropertiesData TypePermissionsDescription
panelPositiondoubleRead / WriteEvaluates to the current panel position (a value between 0.0 and 1.0) where 0.0 is closed and 1.0 is open. Any value assigned to this property must be between 0.0 and 1.0, inclusive.
isAttachedboolReadDetermine if the panelController is attached to an instance of the SlidingUpPanel (this property must be true before any other PanelController functions can be used)
isPanelAnimatingboolReadReturns whether or not the panel is currently animating.
isPanelOpenboolReadReturns whether or not the panel is open.
isPanelClosedboolReadReturns whether or not the panel is collapsed.
isPanelShownboolReadReturns whether or not the panel is shown/hidden.

MethodsReturn TypeDescription
open()Future<void>Opens the sliding panel fully (i.e. to the maxHeight)
close()Future<void>Closes the sliding panel to its collapsed state (i.e. to the minHeight)
hide()Future<void>Hides the sliding panel (i.e. is invisible)
show()Future<void>Shows the sliding panel in its collapsed state (i.e. "un-hide" the sliding panel)
animatePanelToPosition(double value, {Duration duration, Curve curve = Curves.linear})Future<void>Animates the panel position to the value. The value must between 0.0 and 1.0 where 0.0 is fully collapsed and 1.0 is completely open. (optional) duration specifies the time for the animation to complete. (optional) curve specifies the easing behavior of the animation.
animatePanelToSnapPoint(double value, {Duration duration, Curve curve = Curves.linear}) [beta]Future<void>NOTE: This feature is still in beta and may have some problems. Please open an issue on GitHub if you encounter something unexpected.

Animates the panel position to the snap point. Requires that the SlidingUpPanel snapPoint property is not null. (optional) duration specifies the time for the animation to complete. (optional) curve specifies the easing behavior of the animation.
PanelController _pc = new PanelController();

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("SlidingUpPanelExample"),
    ),
    body: SlidingUpPanel(
      controller: _pc,
      panel: Center(
        child: Text("This is the sliding Widget"),
      ),
      body: _body(),
    ),
  );
}

Widget _body(){
  return Container(
    child: Column(
      children: <Widget>[
        RaisedButton(
          child: Text("Open"),
          onPressed: () => _pc.open(),
        ),
        RaisedButton(
          child: Text("Close"),
          onPressed: () => _pc.close(),
        ),
        RaisedButton(
          child: Text("Show"),
          onPressed: () => _pc.show(),
        ),
        RaisedButton(
          child: Text("Hide"),
          onPressed: () => _pc.hide(),
        ),
      ],
    ),
  );
}


Breaking Changes #

v1.0.0 introduced some breaking changes to the PanelController to better adhere to Dart language conventions. The changes are outlined below.

The following PanelController methods now return Future<void> instead of void:

  • close()
  • open()
  • hide()
  • show()
  • animatePanelToPosition(double value)

The following PanelController methods have changed to Dart properties to better reflect Dart language conventions:

  • setPanelPosition() -> panelPosition [as a setter]
  • getPanelPosition() -> panelPosition [as a getter]
  • isPanelAnimating() -> isPanelAnimating
  • isPanelOpen() -> isPanelOpen
  • isPanelClosed() -> isPanelClosed
  • isPanelShown() -> isPanelShown

For example, here's how you would have previously used setPanelPosition() and getPanelPosition() vs. how you would now use the panelPosition property:

// OLD, no longer supported
print(pc.getPanelPosition()); // print a value between 0.0 and 1.0
pc.setPanelPosition(0.5);     // sets the panelPosition to 0.5
// NEW
print(pc.panelPosition); // print a value between 0.0 and 1.0
pc.panelPosition = 0.5;  // sets the panelPosition to 0.5

And here's how you would have previously called isPanelAnimating() vs. how you would now call isPanelAnimating.

panelController.isPanelAnimating(); // OLD, no longer supported
panelController.isPanelAnimating; // NEW

[1.0.2] - [April 13, 2020] #

Features #

  • Addressed issue #71, #103 - Added an optional header widget that floats above the panel and attaches to the top
  • Added an optional footer widget that floats above the panel and attaches to the bottom

Documentation #

  • Updated documentation to reflect new features and fixes

[1.0.1] - [April 2, 2020] #

Fixes #

  • Addressed issue #94: Too much widget rebuild occurring when the user slides the panel. This fix results in huge performance benefits when using the panelChild and panelBuilder properties
  • Addressed issues #102, #111: Fixed issue where tapping on the panel closes it (when using the panelBuilder)
  • Addressed issues #24, #70, #108, #121: Changed backdropTapClosesPanel to use onTap and onVerticalDragEnd so swipes on the backdrop cause the panel to close

Features #

  • Addressed issue #107: Added duration and curve properties to the PanelController's animatePanelToPosition method
  • Addressed issues #12,#77,#86,#100: Added a snapPoint property to allow the panel to snap to a position midway during its slide

Documentation #

  • Updated documentation to reflect new features and fixes
  • Updated copyright year in the LICENSE

[1.0.0] - [January 25, 2020] #

Fixes

  • Addressed issue #69: Used a FadeTransition to handle opacity changes (as per Flutter documentation)
  • Cleaned up PanelController code to make maintenance easier
  • Added clearer assert statements and messages to indicate why calling PanelController methods would fail before attaching the PanelController.

Features

  • Addressed issues #17, #55, #60: Added the ability to link / nested the scroll position of the panel content with the position of the panel (i.e. infinite scrolling).
  • Added the panelBuilder property that's required to implement the nested scrolling as described above.
  • Added an isAttached property to the PanelController to indicate whether or not the PanelController is attached to an instance of the SlidingUpPanel

Breaking Changes

The following PanelController methods now return Future<void> instead of void:

  • close()
  • open()
  • hide()
  • show()
  • animatePanelToPosition(double value)

The following PanelController methods have changed to Dart properties to better reflect Dart language conventions:

  • setPanelPosition() -> panelPosition [as a setter]
  • getPanelPosition() -> panelPosition [as a getter]
  • isPanelAnimating() -> isPanelAnimating
  • isPanelOpen() -> isPanelOpen
  • isPanelClosed() -> isPanelClosed
  • isPanelShown() -> isPanelShown

For example, here's how you would have previously used setPanelPosition() and getPanelPosition() vs. how you would now use the panelPosition property:

// OLD, no longer supported
print(pc.getPanelPosition()); // print a value between 0.0 and 1.0
pc.setPanelPosition(0.5);     // sets the panelPosition to 0.5
// NEW
print(pc.panelPosition); // print a value between 0.0 and 1.0
pc.panelPosition = 0.5;  // sets the panelPosition to 0.5

And here's how you would have previously called isPanelAnimating() vs. how you would now call isPanelAnimating.

panelController.isPanelAnimating(); // OLD, no longer supported
panelController.isPanelAnimating; // NEW

Documentation

  • Updated the documentation to reflect changes
  • Updated example to use nested scrolling



[0.3.6] - [September 25, 2019] #

Fixes

  • Fixed issues #54, #59 where panel listeners would be called before UI was rendered (related to defaultPanelState)

Documentation

  • Updated the documentation to reflect fixes



[0.3.5] - [August 31, 2019] #

Features

  • Added the defaultPanelState property that changes whether the panel is either open or closed by default (PanelState.OPEN or PanelState.CLOSED)

Documentation

  • Updated the documentation to reflect new features



[0.3.4] - [April 16, 2019] #

Features

  • Added the slideDirection property that changes how the panel slides open (either up or down)

Documentation

  • Updated the documentation to reflect new features



[0.3.3] - [April 6, 2019] #

Features

  • Added the isDraggable property that allows/prevents dragging of the panel

Documentation

  • Updated the documentation to reflect new features



[0.3.2] - [April 5, 2019] #

Documentation

  • Fixed problem where images would wrap on pub (instead of displaying on one line)



[0.3.1] - [April 5, 2019] #

Features

  • Configuration options to SlidingUpPanel
    • parallaxEnabled
    • parallaxOffset

Documentation

  • Created a new example app (Maps)
  • Updated documentation to reflect new features



[0.3.0] - April 2, 2019 #

Features

  • Added ability to close the panel when the backdrop is tapped

  • Added callbacks to the SlidingUpPanel

    • onPanelSlide
    • onPanelOpened
    • onPanelClosed
  • Added methods to the PanelController

    • setPanelPosition
    • animatePanelToPosition
    • getPanelPosition
    • isPanelAnimating
    • isPanelOpen
    • isPanelClosed
    • isPanelShown

Bug Fixes

  • Fixed issue where the collapsed widget would accept touch events even when invisible (i.e. even when the panel was fully open)

Documentation

  • Updated documentation to reflect new features
  • Added clarification on PanelController lifecycle
  • Added an explanation about nesting the Scaffold when displaying a backdrop



[0.2.0] - April 1, 2019 #

Added the backdrop feature:

  • Body darkens as the panel opens
  • The backdrop color is customizable
  • The backdrop opacity is also customizable
  • Off by default

Other changes:

  • Removed the README from the example app (pub will display the code on the website now)
  • Specified Dart as the language in the README code snippets



[0.1.2] - March 31, 2019 #

  • Updated documentation to be more comprehensive



[0.1.1] - March 31, 2019 #

  • Added a CHANGELOG file



[0.1.0] - March 31, 2019 #

This is the initial release of the sliding_up_panel package. This includes features such as

  • A sliding up panel that responds to user gestures
  • Customizing the look and feel of the sliding panel
  • Manually controlling the sliding panel via the PanelController

example/lib/main.dart

/*
Name: Akshath Jain
Date: 3/18/2019 - 1/25/2020
Purpose: Example app that implements the package: sliding_up_panel
Copyright: © 2020, Akshath Jain. All rights reserved.
Licensing: More information can be found here: https://github.com/akshathjain/sliding_up_panel/blob/master/LICENSE
*/

import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:sliding_up_panel/sliding_up_panel.dart';
import 'package:flutter/services.dart';

import 'package:flutter_map/flutter_map.dart';
import 'package:latlong/latlong.dart';
import 'package:cached_network_image/cached_network_image.dart';

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

class SlidingUpPanelExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
      systemNavigationBarColor: Colors.grey[200],
      systemNavigationBarIconBrightness: Brightness.dark,
      systemNavigationBarDividerColor: Colors.black,
    ));

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'SlidingUpPanel Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  final double _initFabHeight = 120.0;
  double _fabHeight;
  double _panelHeightOpen;
  double _panelHeightClosed = 95.0;

  @override
  void initState(){
    super.initState();

    _fabHeight = _initFabHeight;
  }

  @override
  Widget build(BuildContext context){
    _panelHeightOpen = MediaQuery.of(context).size.height * .80;

    return Material(
      child: Stack(
        alignment: Alignment.topCenter,
        children: <Widget>[

          SlidingUpPanel(
            maxHeight: _panelHeightOpen,
            minHeight: _panelHeightClosed,
            parallaxEnabled: true,
            parallaxOffset: .5,
            body: _body(),
            panelBuilder: (sc) => _panel(sc),
            borderRadius: BorderRadius.only(topLeft: Radius.circular(18.0), topRight: Radius.circular(18.0)),
            onPanelSlide: (double pos) => setState((){
              _fabHeight = pos * (_panelHeightOpen - _panelHeightClosed) + _initFabHeight;
            }),
          ),

          // the fab
          Positioned(
            right: 20.0,
            bottom: _fabHeight,
            child: FloatingActionButton(
              child: Icon(
                Icons.gps_fixed,
                color: Theme.of(context).primaryColor,
              ),
              onPressed: (){},
              backgroundColor: Colors.white,
            ),
          ),

          Positioned(
            top: 0,
            child: ClipRRect(
              child: BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
                child: Container(
                  width: MediaQuery.of(context).size.width,
                  height: MediaQuery.of(context).padding.top,
                  color: Colors.transparent,
                )
              )
            )
          ),

          //the SlidingUpPanel Title
          Positioned(
            top: 52.0,
            child: Container(
              padding: const EdgeInsets.fromLTRB(24.0, 18.0, 24.0, 18.0),
              child: Text(
                "SlidingUpPanel Example",
                style: TextStyle(
                  fontWeight: FontWeight.w500
                ),
              ),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(24.0),
                boxShadow: [BoxShadow(
                  color: Color.fromRGBO(0, 0, 0, .25),
                  blurRadius: 16.0
                )],
              ),
            ),
          ),


        ],
      ),
    );
  }

  Widget _panel(ScrollController sc){
    return MediaQuery.removePadding(
      context: context,
      removeTop: true,
      child: ListView(
        controller: sc,
        children: <Widget>[
          SizedBox(height: 12.0,),

          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                width: 30,
                height: 5,
                decoration: BoxDecoration(
                color: Colors.grey[300],
                  borderRadius: BorderRadius.all(Radius.circular(12.0))
                ),
              ),
            ],
          ),

          SizedBox(height: 18.0,),

          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                "Explore Pittsburgh",
                style: TextStyle(
                  fontWeight: FontWeight.normal,
                  fontSize: 24.0,
                ),
              ),
            ],
          ),

          SizedBox(height: 36.0,),

          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              _button("Popular", Icons.favorite, Colors.blue),
              _button("Food", Icons.restaurant, Colors.red),
              _button("Events", Icons.event, Colors.amber),
              _button("More", Icons.more_horiz, Colors.green),
            ],
          ),

          SizedBox(height: 36.0,),

          Container(
            padding: const EdgeInsets.only(left: 24.0, right: 24.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[

                Text("Images", style: TextStyle(fontWeight: FontWeight.w600,)),

                SizedBox(height: 12.0,),

                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[

                      CachedNetworkImage(
                        imageUrl: "https://images.fineartamerica.com/images-medium-large-5/new-pittsburgh-emmanuel-panagiotakis.jpg",
                        height: 120.0,
                        width: (MediaQuery.of(context).size.width - 48) / 2 - 2,
                        fit: BoxFit.cover,
                      ),

                      CachedNetworkImage(
                        imageUrl: "https://cdn.pixabay.com/photo/2016/08/11/23/48/pnc-park-1587285_1280.jpg",
                        width: (MediaQuery.of(context).size.width - 48) / 2 - 2,
                        height: 120.0,
                        fit: BoxFit.cover,
                      ),

                  ],
                ),
              ],
            ),
          ),

          SizedBox(height: 36.0,),

          Container(
            padding: const EdgeInsets.only(left: 24.0, right: 24.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text("About", style: TextStyle(fontWeight: FontWeight.w600,)),

                SizedBox(height: 12.0,),

                Text(
                  """Pittsburgh is a city in the state of Pennsylvania in the United States, and is the county seat of Allegheny County. A population of about 302,407 (2018) residents live within the city limits, making it the 66th-largest city in the U.S. The metropolitan population of 2,324,743 is the largest in both the Ohio Valley and Appalachia, the second-largest in Pennsylvania (behind Philadelphia), and the 27th-largest in the U.S.\n\nPittsburgh is located in the southwest of the state, at the confluence of the Allegheny, Monongahela, and Ohio rivers. Pittsburgh is known both as "the Steel City" for its more than 300 steel-related businesses and as the "City of Bridges" for its 446 bridges. The city features 30 skyscrapers, two inclined railways, a pre-revolutionary fortification and the Point State Park at the confluence of the rivers. The city developed as a vital link of the Atlantic coast and Midwest, as the mineral-rich Allegheny Mountains made the area coveted by the French and British empires, Virginians, Whiskey Rebels, and Civil War raiders.\n\nAside from steel, Pittsburgh has led in manufacturing of aluminum, glass, shipbuilding, petroleum, foods, sports, transportation, computing, autos, and electronics. For part of the 20th century, Pittsburgh was behind only New York City and Chicago in corporate headquarters employment; it had the most U.S. stockholders per capita. Deindustrialization in the 1970s and 80s laid off area blue-collar workers as steel and other heavy industries declined, and thousands of downtown white-collar workers also lost jobs when several Pittsburgh-based companies moved out. The population dropped from a peak of 675,000 in 1950 to 370,000 in 1990. However, this rich industrial history left the area with renowned museums, medical centers, parks, research centers, and a diverse cultural district.\n\nAfter the deindustrialization of the mid-20th century, Pittsburgh has transformed into a hub for the health care, education, and technology industries. Pittsburgh is a leader in the health care sector as the home to large medical providers such as University of Pittsburgh Medical Center (UPMC). The area is home to 68 colleges and universities, including research and development leaders Carnegie Mellon University and the University of Pittsburgh. Google, Apple Inc., Bosch, Facebook, Uber, Nokia, Autodesk, Amazon, Microsoft and IBM are among 1,600 technology firms generating \$20.7 billion in annual Pittsburgh payrolls. The area has served as the long-time federal agency headquarters for cyber defense, software engineering, robotics, energy research and the nuclear navy. The nation's eighth-largest bank, eight Fortune 500 companies, and six of the top 300 U.S. law firms make their global headquarters in the area, while RAND Corporation (RAND), BNY Mellon, Nova, FedEx, Bayer, and the National Institute for Occupational Safety and Health (NIOSH) have regional bases that helped Pittsburgh become the sixth-best area for U.S. job growth.
                  """,
                  softWrap: true,
                ),
              ],
            ),
          ),

          SizedBox(height: 24,),
        ],
      )
    );
  }

  Widget _button(String label, IconData icon, Color color){
    return Column(
      children: <Widget>[
        Container(
          padding: const EdgeInsets.all(16.0),
          child: Icon(
            icon,
            color: Colors.white,
          ),
          decoration: BoxDecoration(
            color: color,
            shape: BoxShape.circle,
            boxShadow: [BoxShadow(
              color: Color.fromRGBO(0, 0, 0, 0.15),
              blurRadius: 8.0,
            )]
          ),
        ),

        SizedBox(height: 12.0,),

        Text(label),
      ],

    );
  }

  Widget _body(){
    return FlutterMap(
      options: MapOptions(
        center: LatLng(40.441589, -80.010948),
        zoom: 13,
        maxZoom: 15,
      ),
      layers: [
        TileLayerOptions(
          urlTemplate: "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png"
        ),

        MarkerLayerOptions(
          markers: [
            Marker(
              point: LatLng(40.441753, -80.011476),
              builder: (ctx) => Icon(
                Icons.location_on,
                color: Colors.blue,
                size: 48.0,
              ),
              height: 60
            ),
          ]
        ),
      ],
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  sliding_up_panel: ^1.0.2

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:sliding_up_panel/sliding_up_panel.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
97
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
98
Learn more about scoring.

We analyzed this package on Jul 2, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

because of import path [sliding_up_panel] that is in a package requiring null.

Health suggestions

Format lib/sliding_up_panel.dart.

Run flutter format to format lib/sliding_up_panel.dart.

Format lib/src/panel.dart.

Run flutter format to format lib/src/panel.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8
Dev dependencies
flutter_test