개발하자
앱 주 화면 로드 시 자동으로 알림 대화 상자 표시
Cuire
2023. 7. 28. 18:42
반응형
앱 주 화면 로드 시 자동으로 알림 대화 상자 표시
조건에 따라 알림 대화 상자를 표시합니다. 버튼 누르기 이벤트와 같은 사용자 상호 작용에 기반하지 않습니다.
앱 상태 데이터 경고 대화 상자에 플래그가 설정되어 있으면 그렇지 않으면 표시되지 않습니다.
아래는 내가 보여주고 싶은 샘플 경고 대화상자이다
void _showDialog() {
// flutter defined function
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: new Text("Alert Dialog title"),
content: new Text("Alert Dialog body"),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
메인 화면 위젯의 빌드 방식 안에서 그 방식을 부르려고 했는데 오류가 난다
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
E/flutter ( 3667): #0 Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.dart:1179:9)
E/flutter ( 3667): #1 Navigator.of (package:flutter/src/widgets/navigator.dart:1186:6)
E/flutter ( 3667): #2 showDialog (package:flutter/src/material/dialog.dart:642:20)
문제는 내가 어디서부터 그것을 _showDialog method라고 불러야 할지 모르겠다는 것이다?
내용을 다른 내용(상태 비저장)으로 감싸야 합니다.
예:
변경 위치:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Trial',
home: Scaffold(
appBar: AppBar(title: Text('List scroll')),
body: Container(
child: Text("Hello world"),
)));
}
}
여기에:
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Trial',
home: Scaffold(
appBar: AppBar(title: Text('List scroll')), body: new MyHome()));
}
}
class MyHome extends StatelessWidget { // Wrapper Widget
@override
Widget build(BuildContext context) {
Future.delayed(Duration.zero, () => showAlert(context));
return Container(
child: Text("Hello world"),
);
}
void showAlert(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Text("hi"),
));
}
}
참고: 내부의 래핑 쇼 알림을 참조하십시오
나는 그것을 a에 넣을 것이다.
위젯 방식으로 배치하는 것은 유혹적이지만 경고가 여러 번 트리거됩니다.
아래 예제에서는 와이파이에 장치가 연결되지 않은 경우 경고를 표시하고 연결되지 않은 경우 [다시 시도] 버튼을 표시합니다.
import 'package:flutter/material.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
void main() => runApp(MaterialApp(title: "Wifi Check", home: MyPage()));
class MyPage extends StatefulWidget {
@override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
bool _tryAgain = false;
@override
void initState() {
super.initState();
_checkWifi();
}
_checkWifi() async {
// the method below returns a Future
var connectivityResult = await (new Connectivity().checkConnectivity());
bool connectedToWifi = (connectivityResult == ConnectivityResult.wifi);
if (!connectedToWifi) {
_showAlert(context);
}
if (_tryAgain != !connectedToWifi) {
setState(() => _tryAgain = !connectedToWifi);
}
}
@override
Widget build(BuildContext context) {
var body = Container(
alignment: Alignment.center,
child: _tryAgain
? RaisedButton(
child: Text("Try again"),
onPressed: () {
_checkWifi();
})
: Text("This device is connected to Wifi"),
);
return Scaffold(
appBar: AppBar(title: Text("Wifi check")),
body: body
);
}
void _showAlert(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text("Wifi"),
content: Text("Wifi not detected. Please activate it."),
)
);
}
}
플러터 커뮤니티에서 개발한 패키지로 해결했습니다. 여기요
이것을 당신의 pubspec.yaml에 추가하세요
after_layout: ^1.0.7+2
그리고 아래의 예를 시도해 보십시오
import 'package:after_layout/after_layout.dart';
import 'package:flutter/material.dart';
class DialogDemo extends StatefulWidget {
@override
_DialogDemoState createState() => _DialogDemoState();
}
class _DialogDemoState extends State<DialogDemo>
with AfterLayoutMixin<DialogDemo> {
@override
void initState() {
super.initState();
}
@override
void afterFirstLayout(BuildContext context) {
_neverSatisfied();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
decoration: BoxDecoration(color: Colors.red),
),
);
}
Future<void> _neverSatisfied() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('Rewind and remember'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('You will never be satisfied.'),
Text('You\’re like me. I’m never satisfied.'),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Regret'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
그냥 오버라이드하고 메소드를 안으로 호출하거나:
@override
void initState() {
super.initState();
// Use either of them.
Future(_showDialog);
Timer.run(_showDialog); // Requires import: 'dart:async'
}
간단한 방법으로 이를 달성한 방법은 다음과 같습니다:
더하다
기본 화면(또는 원하는 위젯)의 빌드 방법 위에:
Future checkFirstRun(BuildContext context) async { SharedPreferences prefs = await SharedPreferences.getInstance(); bool isFirstRun = prefs.getBool('isFirstRun') ?? true; if (isFirstRun) { // Whatever you want to do, E.g. Navigator.push() prefs.setBool('isFirstRun', false); } else { return null; } }
그런 다음 위젯의 initState:
@override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) => checkFirstRun(context)); }
이렇게 하면 위젯을 작성한 후 기능이 실행됩니다.
블록을 사용하는 경우 다음 답변에서 @mirkancal에서 제안하는 대로 a를 사용합니다:
나는 이것을 사용하기 때문에 사용자가 페이지를 클릭할 때마다 사용자는 이 면책조항을 표시할 것이다
void showDisclaimerPopup() {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text(
'Q and A ?',
),
content: SizedBox(
width: double.maxFinite,
child: ListView.builder(
shrinkWrap: true,
itemCount: disclaimerPoints.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'• ',
style: TextStyle(fontSize: 18),
),
Expanded(
child: Text(
disclaimerPoints[index],
style: const TextStyle(fontSize: 16),
),
),
],
),
);
},
),
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)),
),
actions: [
Center(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
),
child: Text(
'okay',
style: txtSubheadBlack,
),
onPressed: () {
Navigator.pop(context);
},
),
),
],
),
); }
@override void initState() {
super.initState();
Future.delayed(Duration.zero, () => showDisclaimerPopup()); }
반응형