我的应用程序有一个简介屏幕,但每次打开应用程序时都会显示 我需要第一次显示 怎么做?
//ThIS IS THE SCREEN COMES 1ST WHEN OPENING THE APP (SPLASHSCREEN)
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState()
{
super.initState();
//After 2seconds of time the Introscreen will e opened by bellow code
Timer(Duration(seconds: 2), () => MyNavigator.goToIntroscreen(context));
}
//The below code has the text to show for the spalshing screen
@override
Widget build(BuildContext context)
{
return Scaffold
(
body: new Center(child:Text('SPLASH SCREEN'),)
);
}
}
此屏幕始终打开内部屏幕,延迟时间为2秒。 但我只是第一次想要如何使用共享偏好? 请添加所需的代码pls ....
答案 0 :(得分:13)
如果您希望仅首次显示介绍屏幕,则需要在本地保存此用户已经看过的介绍。
对于这样的事情你可以使用Shared Preference。您可以使用共享首选项flutter package
<强> EDITED 强>:
请参阅以下完整测试代码以了解如何使用:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
color: Colors.blue,
home: new Splash(),
);
}
}
class Splash extends StatefulWidget {
@override
SplashState createState() => new SplashState();
}
class SplashState extends State<Splash> {
Future checkFirstSeen() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool _seen = (prefs.getBool('seen') ?? false);
if (_seen) {
Navigator.of(context).pushReplacement(
new MaterialPageRoute(builder: (context) => new Home()));
} else {
prefs.setBool('seen', true);
Navigator.of(context).pushReplacement(
new MaterialPageRoute(builder: (context) => new IntroScreen()));
}
}
@override
void initState() {
super.initState();
new Timer(new Duration(milliseconds: 200), () {
checkFirstSeen();
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Text('Loading...'),
),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Hello'),
),
body: new Center(
child: new Text('This is the second page'),
),
);
}
}
class IntroScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Text('This is the intro page'),
new MaterialButton(
child: new Text('Gogo Home Page'),
onPressed: () {
Navigator.of(context).pushReplacement(
new MaterialPageRoute(builder: (context) => new Home()));
},
)
],
),
),
);
}
}
答案 1 :(得分:1)
我只需要做完全一样的事情,这就是我的做事方式:
首先,在我的main
方法中,打开常规主页和教程:
MaterialApp(
title: 'myApp',
onGenerateInitialRoutes: (_) => [MaterialPageRoute(builder: mainPageRoute), MaterialPageRoute(builder: tutorialSliderRoute)],
)
...然后仅在必要时使用FutureBuilder
来构建本教程:
var tutorialSliderRoute = (context) => FutureBuilder(
future: Provider.of<UserConfiguration>(context, listen: false).loadShowTutorial() // does a lookup using Shared Preferences
.timeout(Duration(seconds: 3), onTimeout: () => false),
initialData: null,
builder: (context, snapshot){
if (snapshot.data == null){
return CircularProgressIndicator(); // This is displayed for up to 3 seconds, in case data loading doesn't return for some reason...
} else if (snapshot.data == true){
return TutorialSlider(); // The Tutorial, implemented using IntroSlider()
} else {
// In case the tutorial shouldn't be shown, just return an empty Container and immediately pop it again so that the app's main page becomes visible.
SchedulerBinding.instance.addPostFrameCallback((_){Navigator.of(context).pop();});
return Container(width: 0, height: 0);
}
},
);
此外,我认为应该在用户未完成本教程的情况下再次显示该教程,因此,一旦用户完成(或跳过)该变量,我只会将变量showTutorial
设置为false
。教程:
class TutorialSlider extends StatefulWidget {
@override
State<StatefulWidget> createState() => TutorialSliderState();
}
class TutorialSliderState extends State<TutorialSlider> {
...
@override
Widget build(BuildContext context) => IntroSlider(
...
onDonePress: (){
Provider.of<UserConfiguration>(context, listen: false).setShowTutorial(false);
Navigator.of(context).pop();
}
);
}
答案 2 :(得分:1)
我能够不使用after_layout软件包和Mixins而使用FutureBuilder。
from seleniumwire import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
def get_firefox():
options = webdriver.FirefoxOptions()
options.add_argument("-headless")
profile = webdriver.FirefoxProfile()
profile.accept_untrusted_certs = True
profile.set_preference("network.proxy.type", 1)
profile.set_preference('network.proxy.socks', 'proxy')
profile.set_preference('network.proxy.socks_port', 1080)
profile.update_preferences()
driver = webdriver.Firefox(firefox_profile=profile,options=options)
return driver
driver = get_firefox()
答案 3 :(得分:0)
每次启动应用程序时,您都需要存储布尔值。为此,您需要使用shared preferences。
首先,我们为共享首选项创建自定义类,因此您可以从任何页面访问它。
import 'package:shared_preferences/shared_preferences.dart';
class MySharedPreferences {
MySharedPreferences._privateConstructor();
static final MySharedPreferences instance =
MySharedPreferences._privateConstructor();
setBooleanValue(String key, bool value) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
myPrefs.setBool(key, value);
}
Future<bool> getBooleanValue(String key) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
return myPrefs.getBool(key) ?? false;
}
}
然后,我们需要在每次启动应用程序时检查布尔值。如果value为false,则必须显示简介屏幕,否则显示主屏幕。
import 'package:flutter/material.dart';
import 'my_shared_preferences.dart';
import 'intro.dart';
import 'home.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
// This widget is the root of your application.
bool isFirstTimeOpen = false;
MyAppState() {
MySharedPreferences.instance
.getBooleanValue("firstTimeOpen")
.then((value) => setState(() {
isFirstTimeOpen = value;
}));
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: isFirstTimeOpen ? Home() : Intro());
}
}
还将布尔值true存储在简介屏幕中,因此不会每次都显示简介屏幕。您也可以在here上参考示例。
MySharedPreferences.instance.setBooleanValue("firstTimeOpen", true);
答案 4 :(得分:0)
我采取了另一种方法。我同意其他答案,您应该通过isFirstRun
保存SharedPreferences
状态。然后,棘手的部分是如何以正确的方式显示正确的小部件,这样当您回弹时就可以正确关闭应用程序,依此类推。我首先尝试通过在构建{{1 }},但这实际上导致了一些奇怪的SplashWidget
错误。
相反,我最终视情况使用不同的小部件多次调用HomePageWidget
。当我需要关闭Navigator
而不是将其弹出时,我再次调用runApp()
,这次以我的SplashWidget
作为runApp()
属性。即使根据启动画面,也可以根据this issue多次呼叫HomePageWidget
,这很安全。
所以看起来像这样(明显简化了):
child
我在runApp()
上有一个Future<void> main() async {
bool needsFirstRun = await retrieveNeedsFirstRunFromPrefs();
if (needsFirstRun) {
// This is will probably be an async method but no need to
// delay the first widget.
saveFirstRunSeen();
runApp(child: SplashScreenWidget(isFirstRun: true));
} else {
runApp(child: HomePageWidget());
}
}
属性,因为我可以通过两种方式启动它:一次是一个真正的启动屏幕,一次是从设置启动的,以便用户根据需要再次看到它。然后,我在isFirstRun
中进行检查,以确定应该如何返回应用程序。
SplashScreenWidget
答案 5 :(得分:0)
完整代码:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
var prefs = await SharedPreferences.getInstance();
var boolKey = 'isFirstTime';
var isFirstTime = prefs.getBool(boolKey) ?? true;
runApp(MaterialApp(home: isFirstTime ? IntroScreen(prefs, boolKey) : RegularScreen()));
}
class IntroScreen extends StatelessWidget {
final SharedPreferences prefs;
final String boolKey;
IntroScreen(this.prefs, this.boolKey);
Widget build(BuildContext context) {
prefs.setBool(boolKey, false); // You might want to save this on a callback.
return Scaffold();
}
}
class RegularScreen extends StatelessWidget {
Widget build(BuildContext context) => Scaffold();
}
答案 6 :(得分:0)
我总是尝试使用最小数量的包,因为将来它可能会与 ios 或 android 冲突。所以我没有任何包的简单解决方案:
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
final splashDelay = 2;
@override
void initState() {
super.initState();
_loadWidget();
}
_loadWidget() async {
var _duration = Duration(seconds: splashDelay);
return Timer(_duration, checkFirstSeen);
}
Future checkFirstSeen() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool _introSeen = (prefs.getBool('intro_seen') ?? false);
Navigator.pop(context);
if (_introSeen) {
Navigator.pushNamed(context, Routing.HomeViewRoute);
} else {
await prefs.setBool('intro_seen', true);
Navigator.pushNamed(context, Routing.IntroViewRoute);
}
}
@override
Widget build(BuildContext context) {
//your splash screen code
}
}