dart - How to limit scroll distance in a scroll view in Flutter? -


i've made page contains several textfields , buttons in column contained in container has background image. , container child of scrollview widget.

so when person clicks on 1 of fields, keyboard pop (taking portion of screen), means buttons/fields offscreen, scrollview widget serves purpose.

the problem here want limit how far scroll view allows user scroll.

there blank space under lowest button, , don't want user able scroll way there. keep experience simple , not have user "overscroll" past fields should typing in.

but since background image part of scroll view view allow user scroll far down bottom of image. want limit this.

as follow-up i'm trying figure out how set initial scroll position. (so when clicking on field scroll view scrolls down first text field, fields in view. without user needing scroll down them. don't want scroll position re-applied every time user clicks on field, of course.)

here relevant (if of code looks bad please so, i'm new programming in general , accept advice improve):

class loginpageconstructor extends statelesswidget {   @override   widget build(buildcontext context) {     assetimage loginbackgroundasset =         new assetimage("assets/loginscreen/backgroundrock.png"); //    var _scrollcontroller = new scrollcontroller( //        initialscrolloffset: 200.0, //        keepscrolloffset: true);     return new scaffold(         body: new container(       child: new listview(key: new pagestoragekey("divider 1"), //        controller: _scrollcontroller,         children: <widget>[           new stack(children: <widget>[             new container(             constraints: new boxconstraints.expand(height: 640.0),               decoration: new boxdecoration(                   image: new decorationimage(                       image: loginbackgroundasset, fit: boxfit.cover)),             child: new column(               children: <widget>[                 new divider(height: 300.0,),                 new center(child: new usernametext(),),                 new divider(height: 8.0,),                 new center(child: new passwordtext(),),                 new divider(),                 new loginbutton(),                 new divider(),                 new signupbutton(),               ],             ))           ])         ],       ),     ));   } } 

for auto-scrolling fields view, sounds wrestling issue 10826. posted workaround on issue. adapted workaround sample code; see below. (you may want tweak little.)

if want prevent users scrolling, might want ensure fields visible using same techniques below , use neverscrollablescrollphysics physics of listview. or if you're feeling ambitious implement custom scroll physics shown in gallery example. if i'd hold out #10826 fixed, though.

video

import 'package:meta/meta.dart'; import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart';  void main() {   runapp(new materialapp(home: new loginpage())); }  /// widget ensures visible when focused. class ensurevisiblewhenfocused extends statefulwidget {   const ensurevisiblewhenfocused({     key key,     @required this.child,     @required this.focusnode,     this.curve: curves.ease,     this.duration: const duration(milliseconds: 100),   }) : super(key: key);    /// node monitor determine if child focused   final focusnode focusnode;    /// child widget wrapping   final widget child;    /// curve use scroll ourselves view.   ///   /// defaults curves.ease.   final curve curve;    /// duration use scroll ourselves view   ///   /// defaults 100 milliseconds.   final duration duration;    ensurevisiblewhenfocusedstate createstate() => new ensurevisiblewhenfocusedstate(); }  class ensurevisiblewhenfocusedstate extends state<ensurevisiblewhenfocused> {   @override   void initstate() {     super.initstate();     widget.focusnode.addlistener(_ensurevisible);   }    @override   void dispose() {     super.dispose();     widget.focusnode.removelistener(_ensurevisible);   }    future<null> _ensurevisible() async {     // wait keyboard come view     // todo: position doesn't seem notify listeners when metrics change,     // perhaps notificationlistener around scrollable avoid     // need insert delay here.     await new future.delayed(const duration(milliseconds: 600));      if (!widget.focusnode.hasfocus)       return;      final renderobject object = context.findrenderobject();     final renderabstractviewport viewport = renderabstractviewport.of(object);     assert(viewport != null);      scrollablestate scrollablestate = scrollable.of(context);     assert(scrollablestate != null);      scrollposition position = scrollablestate.position;     double alignment;     if (position.pixels > viewport.getoffsettoreveal(object, 0.0)) {       // move down top of viewport       alignment = 0.0;     } else if (position.pixels < viewport.getoffsettoreveal(object, 1.0)) {       // move bottom of viewport       alignment = 1.0;     } else {       // no scrolling necessary reveal child       return;     }     position.ensurevisible(       object,       alignment: alignment,       duration: widget.duration,       curve: widget.curve,     );   }    widget build(buildcontext context) => widget.child; }  class loginpage extends statefulwidget {   loginpagestate createstate() => new loginpagestate(); }  class loginpagestate extends state<loginpage> {   focusnode _usernamefocusnode = new focusnode();   focusnode _passwordfocusnode = new focusnode();    @override   widget build(buildcontext context) {     return new scaffold(       appbar: new appbar(         title: new text('example app'),       ),       body: new container(         child: new listview(           physics: new neverscrollablescrollphysics(),           key: new pagestoragekey("divider 1"),           children: <widget>[             new container(               constraints: new boxconstraints.expand(height: 640.0),               decoration: new boxdecoration(                 image: new decorationimage(                   image: new networkimage(                     'https://flutter.io/images/flutter-mark-square-100.png',                   ),                   fit: boxfit.cover,                 ),               ),               child: new column(                 children: <widget>[                   new container(                     height: 300.0,                   ),                   new center(                     child: new ensurevisiblewhenfocused(                       focusnode: _usernamefocusnode,                       child: new textformfield(                         focusnode: _usernamefocusnode,                         decoration: new inputdecoration(                           labeltext: 'username',                         ),                       ),                     ),                   ),                   new container(height: 8.0),                   new center(                     child: new ensurevisiblewhenfocused(                       focusnode: _passwordfocusnode,                       child: new textformfield(                         focusnode: _passwordfocusnode,                         obscuretext: true,                         decoration: new inputdecoration(                           labeltext: 'password',                         ),                       ),                     ),                   ),                   new container(),                   new raisedbutton(                     onpressed: () {},                     child: new text('log in'),                   ),                   new divider(),                   new raisedbutton(                     onpressed: () {},                     child: new text('sign up'),                   ),                 ],               ),             ),           ],         ),       ),     );   } } 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -