Autoscroll when keyboard open on purchase screen
This commit is contained in:
@@ -193,7 +193,6 @@
|
|||||||
28B464359F9DDCC3EF756D7D /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
28B464359F9DDCC3EF756D7D /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
|
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
|
||||||
31F92512BEA3153C65AA90AD /* Pods-Runner.release-dinect.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-dinect.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release-dinect.xcconfig"; sourceTree = "<group>"; };
|
31F92512BEA3153C65AA90AD /* Pods-Runner.release-dinect.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-dinect.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release-dinect.xcconfig"; sourceTree = "<group>"; };
|
||||||
323C7CAF205A43FC0051BB7F /* Dinect-INT.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Dinect-INT.entitlements"; sourceTree = "<group>"; };
|
|
||||||
328A58AF205F68270039EA5A /* Dinect.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Dinect.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
328A58AF205F68270039EA5A /* Dinect.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Dinect.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
328A58B0205F68270039EA5A /* Runner copy2-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Runner copy2-Info.plist"; path = "/Users/dinect/projects/checker/ios/Runner copy2-Info.plist"; sourceTree = "<absolute>"; };
|
328A58B0205F68270039EA5A /* Runner copy2-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Runner copy2-Info.plist"; path = "/Users/dinect/projects/checker/ios/Runner copy2-Info.plist"; sourceTree = "<absolute>"; };
|
||||||
32DA147B1FBC3DCE008F0388 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
32DA147B1FBC3DCE008F0388 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
@@ -343,7 +342,6 @@
|
|||||||
97C146E51CF9000F007C117D = {
|
97C146E51CF9000F007C117D = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
323C7CAF205A43FC0051BB7F /* Dinect-INT.entitlements */,
|
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
@@ -733,7 +731,7 @@
|
|||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||||
"${PODS_ROOT}/../../../flutter/bin/cache/artifacts/engine/ios-release/Flutter.framework",
|
"${PODS_ROOT}/../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework",
|
||||||
);
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
@@ -794,7 +792,7 @@
|
|||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${SRCROOT}/Pods/Target Support Files/Pods-Crypto/Pods-Crypto-frameworks.sh",
|
"${SRCROOT}/Pods/Target Support Files/Pods-Crypto/Pods-Crypto-frameworks.sh",
|
||||||
"${PODS_ROOT}/../../../flutter/bin/cache/artifacts/engine/ios-release/Flutter.framework",
|
"${PODS_ROOT}/../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework",
|
||||||
);
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
@@ -812,7 +810,7 @@
|
|||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${SRCROOT}/Pods/Target Support Files/Pods-Dinect/Pods-Dinect-frameworks.sh",
|
"${SRCROOT}/Pods/Target Support Files/Pods-Dinect/Pods-Dinect-frameworks.sh",
|
||||||
"${PODS_ROOT}/../../../flutter/bin/cache/artifacts/engine/ios-release/Flutter.framework",
|
"${PODS_ROOT}/../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework",
|
||||||
);
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
@@ -1288,7 +1286,6 @@
|
|||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-Checker-INT";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-Checker-INT";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = "Dinect-INT.entitlements";
|
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@@ -1322,7 +1319,6 @@
|
|||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-Checker-INT";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-Checker-INT";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = "Dinect-INT.entitlements";
|
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
|||||||
@@ -318,84 +318,3 @@ abstract class BaseState<T extends StatefulWidget> extends State<T> {
|
|||||||
return new Container(margin: margin, height: buttonHeight, child: new Row(children: <Widget>[new Expanded(child: widget)]));
|
return new Container(margin: margin, height: buttonHeight, child: new Row(children: <Widget>[new Expanded(child: widget)]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/// The node we will monitor to determine if the child is focused
|
|
||||||
final FocusNode focusNode;
|
|
||||||
|
|
||||||
/// The child widget that we are wrapping
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
/// The curve we will use to scroll ourselves into view.
|
|
||||||
///
|
|
||||||
/// Defaults to Curves.ease.
|
|
||||||
final Curve curve;
|
|
||||||
|
|
||||||
/// The duration we will use to scroll ourselves into view
|
|
||||||
///
|
|
||||||
/// Defaults to 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 for the keyboard to come into view
|
|
||||||
// TODO: position doesn't seem to notify listeners when metrics change,
|
|
||||||
// perhaps a NotificationListener around the scrollable could avoid
|
|
||||||
// the need insert a delay here.
|
|
||||||
await new Future.delayed(const Duration(milliseconds: 100));
|
|
||||||
|
|
||||||
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 to the top of the viewport
|
|
||||||
alignment = 0.0;
|
|
||||||
} else if (position.pixels < viewport.getOffsetToReveal(object, 1.0)) {
|
|
||||||
// Move up to the bottom of the viewport
|
|
||||||
alignment = 1.0;
|
|
||||||
} else {
|
|
||||||
// No scrolling is necessary to reveal the child
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
position.ensureVisible(
|
|
||||||
object,
|
|
||||||
alignment: alignment,
|
|
||||||
duration: widget.duration,
|
|
||||||
curve: widget.curve,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget build(BuildContext context) => widget.child;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
loading = true;
|
loading = true;
|
||||||
requestAsyncData(user);
|
requestAsyncData(user);
|
||||||
|
buildFocusNode();
|
||||||
|
scrollController = new ScrollController();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,12 +56,14 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool purchaseInProgress = false;
|
bool purchaseInProgress = false;
|
||||||
|
ScrollController scrollController;
|
||||||
Map user;
|
Map user;
|
||||||
String card = '';
|
String card = '';
|
||||||
String loyalityType = '';
|
String loyalityType = '';
|
||||||
String loyalty = '';
|
String loyalty = '';
|
||||||
String bonus = '';
|
String bonus = '';
|
||||||
List<Map> coupons = [];
|
List<Map> coupons = [];
|
||||||
|
ListView listView;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget getScreenContent() {
|
Widget getScreenContent() {
|
||||||
@@ -119,8 +123,8 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
|||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
return new Container(child: new ListView(reverse: true,
|
listView = new ListView(children: widgetList, controller: scrollController);
|
||||||
children: <Widget>[new Column(children: widgetList)].reversed.toList()));
|
return listView;
|
||||||
}
|
}
|
||||||
|
|
||||||
getBonusInputField() {
|
getBonusInputField() {
|
||||||
@@ -130,6 +134,7 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
|||||||
hintText: (app != 'crypto') ? StringsLocalization.bonusHint() : StringsLocalization.joysHint(),
|
hintText: (app != 'crypto') ? StringsLocalization.bonusHint() : StringsLocalization.joysHint(),
|
||||||
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)
|
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)
|
||||||
),
|
),
|
||||||
|
focusNode: bonusFocusNode,
|
||||||
controller: bonusController,
|
controller: bonusController,
|
||||||
onSubmitted: (String text) {
|
onSubmitted: (String text) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -206,13 +211,13 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
|||||||
hintText: getHintString(),
|
hintText: getHintString(),
|
||||||
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
|
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
|
focusNode: sumFocusNode,
|
||||||
onSubmitted: (String text) {
|
onSubmitted: (String text) {
|
||||||
setState(() {
|
setState(() {
|
||||||
controller.text = _parseSum(text);
|
controller.text = _parseSum(text);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center);
|
||||||
autofocus: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAsyncData(Map user) async {
|
requestAsyncData(Map user) async {
|
||||||
@@ -436,4 +441,39 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
|||||||
Navigator.of(context).pop(token);
|
Navigator.of(context).pop(token);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FocusNode bonusFocusNode = new FocusNode();
|
||||||
|
FocusNode sumFocusNode = new FocusNode();
|
||||||
|
|
||||||
|
// TODO: Удалить дублирующийся код.
|
||||||
|
void buildFocusNode() {
|
||||||
|
|
||||||
|
sumFocusNode.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
|
||||||
|
if (sumFocusNode.hasFocus && bonusFocusNode.hasFocus) {
|
||||||
|
bonusFocusNode.unfocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sumFocusNode.hasFocus) {
|
||||||
|
scrollController.animateTo(100.0, duration: new Duration(seconds: 1), curve: Curves.ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
bonusFocusNode.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
|
||||||
|
if (bonusFocusNode.hasFocus && sumFocusNode.hasFocus) {
|
||||||
|
sumFocusNode.unfocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bonusFocusNode.hasFocus) {
|
||||||
|
scrollController.animateTo(120.0, duration: new Duration(seconds: 1), curve: Curves.ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,15 +57,13 @@ class RegistrationScreenState extends BaseState<RegistrationScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
getTextWidget() {
|
getTextWidget() {
|
||||||
return new EnsureVisibleWhenFocused(
|
return new TextField(
|
||||||
focusNode: _focusNode,
|
|
||||||
child: new TextField(
|
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
decoration: new InputDecoration.collapsed(
|
decoration: new InputDecoration.collapsed(
|
||||||
hintText: getHintString(),
|
hintText: getHintString(),
|
||||||
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
|
hintStyle: new TextStyle(color: greyTextColor, fontSize: 16.0)),
|
||||||
onChanged: (text) => handleUserInput(text)));
|
onChanged: (text) => handleUserInput(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Возвращает кнопку регистрации.
|
/// Возвращает кнопку регистрации.
|
||||||
|
|||||||
Reference in New Issue
Block a user