Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make SingleChildScrollView start at the bottom?

Tags:

flutter

dart

I'm developing an app and ran into an issue where SingleChildScrollView starts at the top:

enter image description here

How do I make it start at the bottom like this:

enter image description here

The scroll view is implemented in the topContent, which is the top half of the screen:

    final topContent = Stack(
      children: <Widget>[
        Container(
            padding: EdgeInsets.only(left: 10.0),
            height: MediaQuery.of(context).size.height * 0.5,
            decoration: new BoxDecoration(
              image: new DecorationImage(
                image: new AssetImage("assets/images/drones1.jpg"),
                fit: BoxFit.cover,
              ),
            )),
        Container(
          height: MediaQuery.of(context).size.height * 0.5,
          padding: EdgeInsets.all(40.0),
          width: MediaQuery.of(context).size.width,
          decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, .9)),
          child: SingleChildScrollView(      //scroll view implemented here 
            child: Center(
              child: topContentText,
            ),
          ),
        ),
        Positioned(
          left: 8.0,
          top: 60.0,
          child: InkWell(
            onTap: () {
              Navigator.pop(context);
            },
            child: Icon(Icons.arrow_back, color: Colors.white),
          ),
        )
      ],
    );

UPDATE: I assigned a controller and followed this link's example to try and use SchedulerBinding.instance.addPostFrameCallback to call the jumpTo function for scroll controller but it gives me an exception with the result the same as before where it is not scrolled down:

import 'package:garuda_academy_app/Constants.dart';
import 'Lesson.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

class DetailPage extends StatefulWidget {
  final Lesson lesson;
  DetailPage({Key key, this.lesson}) : super(key: key);

  @override
  _DetailPageState createState() => _DetailPageState(lesson: lesson);
}
class _DetailPageState extends State<DetailPage> {
  final Lesson lesson;
  ScrollController _scrollController;
  _DetailPageState({this.lesson});

  @override                             // I use the SchedularBinding here
  void initState() {
    super.initState();
    SchedulerBinding.instance.addPostFrameCallback((_) =>
      _scrollController.jumpTo(_scrollController.position.maxScrollExtent));
  }

  @override
  Widget build(BuildContext context) {
    final levelIndicator = Container(
      child: Container(
        child: LinearProgressIndicator(
            backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
            value: lesson.indicatorValue,
            valueColor: AlwaysStoppedAnimation(Colors.green)),
      ),
    );

    final course = Container(
      padding: const EdgeInsets.all(7.0),
      decoration: new BoxDecoration(
          border: new Border.all(color: Colors.white),
          borderRadius: BorderRadius.circular(5.0)),
      child: new Text(
        lesson.course,
        style: TextStyle(color: Colors.white),
      ),
    );

    final topContentText = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        SizedBox(height: 120.0),
        Icon(
          Icons.flight,
          color: Colors.white,
          size: 40.0,
        ),
        Container(
          width: 90.0,
          child: new Divider(color: Colors.green),
        ),
        SizedBox(height: 10.0),
        Text(
          lesson.title,
          style: TextStyle(color: Colors.white, fontSize: 45.0),
        ),
        SizedBox(height: 30.0),
        Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Expanded(flex: 1, child: levelIndicator),
            Expanded(
                flex: 6,
                child: Padding(
                    padding: EdgeInsets.only(left: 10.0),
                    child: Text(
                      lesson.level,
                      style: TextStyle(color: Colors.white),
                    ))),
            Expanded(flex: 1, child: course)
          ],
        ),
      ],
    );

    final topContent = Stack(
      children: <Widget>[
        Container(
            padding: EdgeInsets.only(left: 10.0),
            height: MediaQuery.of(context).size.height * 0.5,
            decoration: new BoxDecoration(
              image: new DecorationImage(
                image: new AssetImage(lesson.imagePath),
                fit: BoxFit.cover,
              ),
            )),
        Container(
          height: MediaQuery.of(context).size.height * 0.5,
          padding: EdgeInsets.all(40.0),
          width: MediaQuery.of(context).size.width,
          decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, .9)),
          child: SingleChildScrollView(
            controller: _scrollController,      // Where I pin the ScrollController
            child: Center(
              child: topContentText,
            ),
          ),
        ),
        Positioned(
          left: 8.0,
          top: 60.0,
          child: InkWell(
            onTap: () {
              Navigator.pop(context);
            },
            child: Icon(Icons.arrow_back, color: Colors.white),
          ),
        )
      ],
    );

    final bottomContentText = Text(
      lesson.content,
      style: TextStyle(fontSize: 18.0),
    );
    final downloadButton = Container(
        padding: EdgeInsets.symmetric(vertical: 16.0),
        width: MediaQuery.of(context).size.width,
        child: RaisedButton(
          onPressed: () => {},
          color: Color.fromRGBO(58, 66, 86, 1.0),
          child:
              Text(DETAIL_PAGE_DOWNLOAD, style: TextStyle(color: Colors.white)),
        ));
    final bottomContent = Container(
      width: MediaQuery.of(context).size.width,
      padding: EdgeInsets.all(40.0),
      child: Center(
        child: Column(
          children: <Widget>[bottomContentText, downloadButton],
        ),
      ),
    );

    return Scaffold(
      body: Column(                  
        children: <Widget>[topContent, bottomContent],
      ),
    );
  }  
}

Exception: I/flutter ( 1567): Another exception was thrown: NoSuchMethodError: The getter 'position' was called on null.

like image 500
Rajdeep Avatar asked May 20 '19 04:05

Rajdeep


2 Answers

I solved it by further adding (from the update) this when I defined the ScrollController:

  ScrollController _scrollController = new ScrollController(
    initialScrollOffset: 0.0,
    keepScrollOffset: true,
  );
like image 93
Rajdeep Avatar answered Oct 16 '22 03:10

Rajdeep


Just add reverse true inside SingleChildScrollView:

SingleChildScrollView( reverse: true, child: Column(), )

like image 44
Battle Hunter OFFICIAL Avatar answered Oct 16 '22 02:10

Battle Hunter OFFICIAL