๊ด€๋ฆฌ ๋ฉ”๋‰ด

ruriruriya

[Flutter] ํ”Œ๋Ÿฌํ„ฐ ์›น๋ทฐ ๋’ค๋กœ๊ฐ€๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„(webview_flutter) ๋ณธ๋ฌธ

๐Ÿ“ฑFlutter/Flutter Framework

[Flutter] ํ”Œ๋Ÿฌํ„ฐ ์›น๋ทฐ ๋’ค๋กœ๊ฐ€๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„(webview_flutter)

๋ฃจ๋ฆฌ์•ผใ…‘ 2025. 5. 12. 17:47
๋ฐ˜์‘ํ˜•

 

์›น๋ทฐ ์•ฑ์„ ๋งŒ๋“ค๋ฉด ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ์•ฑ์ด ๊บผ์ง€๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•œ๋‹ค.

๊ทธ๋Ÿด ๋•Œ ์•ฑ ๊ฐœ๋ฐœ ์ชฝ์—์„œ ์ปจํŠธ๋กค์„ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

ํ”Œ๋Ÿฌํ„ฐ๋กœ ๊ทธ๋ ‡๊ฒŒ ์ปจํŠธ๋กค ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜์—ฌ ๊ธฐ๋กํ•œ๋‹ค.

ํ•˜์ง€๋งŒ iOS๋Š” ๋’ค๋กœ๊ฐ€๊ธฐ ์Šค์™€์ดํ”„ ๊ธฐ๋Šฅ์ด ์žˆ๋Š”๋ฐ webview_flutter ํŒจํ‚ค์ง€์—์„œ๋Š” ๊ตฌํ˜„์„ ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.
InAppWebView๋กœ๋Š” ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๋ฐ ๋‹ค์Œ์—” InAppWebView๋กœ ์›น๋ทฐ๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ํ•ด๋ด์•ผ๊ฒ ๋‹ค.

 

0. ์›น๋ทฐ ๊ตฌํ˜„ํ•˜๊ธฐ

https://ruriruriya.tistory.com/270

 

[Flutter] ํ”Œ๋Ÿฌํ„ฐ ์›น๋ทฐ ์•ฑ ๋งŒ๋“ค๊ธฐ (package:webview_flutter)

ํ”Œ๋Ÿฌํ„ฐ๋กœ ์›น๋ทฐ ์•ฑ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•! ๋…ธ์น˜์™€ ์ƒํƒœ๋ฐ” ๋ถ€๋ถ„ SafeArea๋กœ ์ฒ˜๋ฆฌํ•ด์„œ ํŽธ์•ˆํ•˜๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.0. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ์€ ์ƒ๋žต.. 1. ์›น๋ทฐ ํ”Œ๋Ÿฌ๊ทธ์ธ(webview_flutter) ์ถ”๊ฐ€ - pubspec.yaml์•„๋ž˜์™€ ๊ฐ™์ด depen

ruriruriya.tistory.com

 

1. ์•ˆ๋“œ๋กœ์ด๋“œ ๋’ค๋กœ๊ฐ€๊ธฐ ๋Œ€์‘ ํ•จ์ˆ˜ ์ƒ์„ฑ

// ์•ˆ๋“œ๋กœ์ด๋“œ ๋’ค๋กœ๊ฐ€๊ธฐ ๋Œ€์‘ ํ•จ์ˆ˜
  Future<bool> _onWillPop() async {
    if (await _controller.canGoBack()) {
      _controller.goBack(); // WebView ๋‚ด ๋’ค๋กœ๊ฐ€๊ธฐ ์‹คํ–‰
      return false; // ์•ฑ ์ข…๋ฃŒ ๋ฐฉ์ง€
    }
    return true; // ๋’ค๋กœ ๊ฐˆ ํŽ˜์ด์ง€ ์—†์œผ๋ฉด ์•ฑ ์ข…๋ฃŒ ํ—ˆ์šฉ
  }

 

2. WillPopScope ์œ„์ ฏ์œผ๋กœ WebView ๊ฐ์‹ธ๊ธฐ

@override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        backgroundColor: Colors.white,
        resizeToAvoidBottomInset: true,
        body: SafeArea(
          child: WebViewWidget(controller: _controller),
        ),         
      ),
    );
  }

 

3. ์ „์ฒด์ฝ”๋“œ

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter WebView App',
      debugShowCheckedModeBanner: false,
      theme: ThemeData( 
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const WebViewExample(),
    );
  }
}

class WebViewExample extends StatefulWidget {
  const WebViewExample({super.key});

  @override
  State<WebViewExample> createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
  late final WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _controller = WebViewController()
      ..loadRequest(Uri.parse('https://flutter.dev'));
  }

  // ์•ˆ๋“œ๋กœ์ด๋“œ ๋’ค๋กœ๊ฐ€๊ธฐ ๋Œ€์‘ ํ•จ์ˆ˜
  Future<bool> _onWillPop() async {
    if (await _controller.canGoBack()) {
      _controller.goBack(); // WebView ๋‚ด ๋’ค๋กœ๊ฐ€๊ธฐ ์‹คํ–‰
      return false; // ์•ฑ ์ข…๋ฃŒ ๋ฐฉ์ง€
    }
    return true; // ๋’ค๋กœ ๊ฐˆ ํŽ˜์ด์ง€ ์—†์œผ๋ฉด ์•ฑ ์ข…๋ฃŒ ํ—ˆ์šฉ
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        backgroundColor: Colors.white,
        resizeToAvoidBottomInset: true,
        body: SafeArea(
          child: WebViewWidget(controller: _controller),
        ),         
      ),
    );
  }
}
๋ฐ˜์‘ํ˜•