이번에는 플러터로 만든 앱에
웹뷰를 넣는 방법을 정리하려한다.
내 경우 router용 패키지로 auto route를 사용중이기에,
go_router를 쓰거나 다른 패키지를 쓴다면
그에 맞게 변형해 사용하면 된다.
웹뷰를 구현하려는 이유는 앱마다 매우 다양하다.
하지만 굳이 flutter로 앱을 만드는 중이라면,
공지사항이나 버전 업데이트 사항등을
노션 페이지로 안내하는 정도로만 사용하자.
즉 그냥 링크타고 들어가서 페이지 보여주는
정도만 사용하라는 것이다.
웹뷰앱 수준의 기능을 구현하려고 하면 복잡하기만 하다.
그럼에도 더 깊은 수준의 기능을 원한다면,
이 포스팅과는 취지가 맞지 않으니
다른 개발 문서를 찾아보길 바란다.
여기 공식 패키지 사용 설명이 있으니
필요하다면 보고 활용하자.
pubspec.yaml에서 아래 패키지를 추가
dependencies:
webview_flutter: ^4.9.0
이 부분 때문에 에러를 한 번 만났다.
아래를 설정해주면 된다.
웹뷰 스크린을 구현하는 여러가지 방법이 있겠으나,
나는 주로 틀을 만들어두고 app bar에 쓰인 문구와
보여주려는 페이지의 url 두 가지만
변경해주며 재사용하는 방식을 선호한다.
@RoutePage()
class WebViewScreen extends StatefulWidget {
final String appBarTitle;
final String url;
const WebViewScreen({super.key, required this.appBarTitle, required this.url});
@override
WebViewScreenState createState() => WebViewScreenState();
}
스크린 생성 시에 app bar에 표시할 스크린 title과
url 주소를 파라미터로 받는다.
auto_route 패키지를 사용하는 관계로,
@RoutePage() annotation을 추가해준 모습이다.
class WebViewScreenState extends State<WebViewScreen> {
late final WebViewController _controller;
int _progress = 0;
@override
void initState() {
super.initState();
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) => setState(() => _progress = progress),
onPageStarted: (String url) {},
onPageFinished: (String url) {},
onHttpError: (HttpResponseError error) {},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith(widget.url)) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(widget.url));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: DefaultAppBar(
titleStr: widget.appBarTitle, canPop: true, onBack: context.router.popUntilRoot),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: MediaQuery.of(context).size.width * (_progress/100),
height: 4,
color: _progress==100 ? Colors.transparent : Colors.grey,
),
],
),
Expanded(child: WebViewWidget(controller: _controller))
],
),
);
}
}
DefaultAppbar는 내가 만든 custom appbar 이므로,
각자 자신의 앱에 맞는 appbar를 만들거나 custom해
사용하도록 하자.
_progress 상태를 활용해 웹뷰 상단에
페이지 로드 정도를 표시하는 로직을 짜봤다.
자, 여기까지 했다면 프레임은 완성이다.
@AutoRouterConfig()
class AppRouter extends RootStackRouter {
@override
RouteType get defaultRouteType => const RouteType.material();
@override
List<AutoRoute> get routes => [
.
.
.
AutoRoute(path: '/web_view', page: WebViewRoute.page),
.
.
];
}
이제 원하는 곳에서 웹뷰로 이동하는 로직만 짜주면 된다.
위에서 계속 auto route와 routing 방식을 언급했던 이유는,
웹뷰를 만든다 = 웹뷰로 어떻게 screen routing할지 설계한다
라고해도 과언이 아니기 때문이다.
auto_route를 쓴다면 아래와 같이 해주면 된다.
Column(
children: [
.
.
.
GestureDetector(
onTap: () => context.router.push(WebViewRoute(appBarTitle: "공지사항", url: "https://cafejari.notion.site/3ebe53162df04aa79146765424bf5c80?pvs=74")),
child: const Text("공지사항 >"),
),
GestureDetector(
onTap: () => context.router.push(WebViewRoute(appBarTitle: "앱 버전", url: "https://www.notion.so/cafejari/a81ea1d045f24d26865b68373e30e15f")),
child: const Text("앱 버전 >"),
)
.
.
.
]
)
플러터 기본 route 방식인 Navigator를 쓴다면 다음과 같다.
Column(
children: [
.
.
.
GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => WebViewScreen(appBarTitle: "공지사항", url: "https://cafejari.notion.site/3ebe53162df04aa79146765424bf5c80?pvs=74")), // 이동할 페이지 정의
),
child: const Text("공지사항 >"),
)
.
.
.
]
)
무슨 방식을 사용하든, screen에
title과 url만 잘 전달해주면 된다.
인터넷 무료 사이트로 gif 변환을 했더니
화질이 구리다. 그냥 감안해주자.
이런식으로 하면 간단한 공지사항 전달이나
각종 처리방침과 약관, 패치노트등을
전달하는데 귀찮게 스크린을 만들 필요가 없다.
그냥 노션으로 페이지 파서 그것만 관리하자.
안녕하세요 혹시 초보개발자입니다. 계속 에러가 뜨는데 혹시 도와주실수있으신가요?