/AOS-WebBrowser

๐Ÿ›  WebView, SwiperRefreshLayout, ProgressBar๋ฅผ ํ™œ์šฉํ•œ ์›น๋ธŒ๋ผ์šฐ์ €

Primary LanguageKotlin

ํ‚ค์›Œ๋“œ

  • ConstraintLayout
  • EditText
  • WebView

๊ตฌํ˜„ ๋ชฉ๋ก

  • ์›น์‚ฌ์ดํŠธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
  • ์•ž์œผ๋กœ ๊ฐ€๊ธฐ, ๋’ค๋กœ ๊ฐ€๊ธฐ, ํ™ˆ ๋ฒ„ํŠผ
  • ์›น์‚ฌ์ด๋“œ ๋กœ๋”ฉ ํ™•์ธ

๊ฐœ๋ฐœ ๊ณผ์ •(๋…ธ์…˜์—์„œ ํ™•์ธ)

1. ๊ธฐ๋ณธ UI ์„ค์ •ํ•˜๊ธฐ

ConstraintLayout ์„ ์ถ”๊ฐ€๋กœ ์„ค์ •ํ•ด์„œ ์ƒ๋‹จ๋ฐ”๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ์ดํ›„ ์ขŒ์ธก๋ถ€ํ„ฐ ํ™ˆ, ์ฃผ์†Œ์ฐฝ, ๋’ค๋กœ ๊ฐ€๊ธฐ, ์•ž์œผ๋กœ ๊ฐ€๊ธฐ๋ฅผ ๋„ฃ์–ด์คฌ๋‹ค. ์ด๋ฒˆ์— ์–ดํ”Œ์„ ๋งŒ๋“ค๋ฉด์„œ match_parent ์™€ 0dp ์˜ ์ฐจ์ด๊ฐ€ ํ—ท๊ฐˆ๋ ค์„œ ๋‹ค์‹œ ๊ณต๋ถ€ํ–ˆ๋Š”๋ฐ 0dp๋Š” match_constraint ์™€ ๊ฐ™์€ ์˜๋ฏธ์ด๋‹ค.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/toolBar"
        android:layout_width="0dp"
        android:layout_height="?attr/actionBarSize"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageButton
            android:id="@+id/goHomeButton"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:src="@drawable/ic_home"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <EditText
            android:id="@+id/addressBar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:inputType="textUri"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@id/goHomeButton"
            app:layout_constraintRight_toLeftOf="@+id/goBackButton"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageButton
            android:id="@+id/goForwardButton"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:src="@drawable/ic_forward"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageButton
            android:id="@+id/goBackButton"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:src="@drawable/ic_back"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/goForwardButton"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    <WebView
        android:id="@+id/webView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/toolBar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

๊ฐ ๋ฒ„ํŠผ์„ ๋ณด๋ฉด layout_height ์— 0dp๊ฐ€ ๊ฑธ๋ ค์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ match_constraint ์†์„ฑ์— ์˜ํ•ด์„œ ๋†’์ด๊ฐ€ ๊ตฌํ˜„์ด ๋œ๋‹ค.

2. URL ๋กœ๋”ฉ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

initView

์œ„์˜ ์‚ฌ์ง„์„ ๋ณด๋ฉด ์•ฑ์„ ์‹คํ–‰ํ•ด๋„ ์•„์ง webView Layout ์—๋Š” ์•„๋ฌด๊ฒƒ๋„ ๋œจ์ง€ ์•Š์€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์•ฑ์„ ์‹คํ–‰ํ–ˆ์„ ๋•Œ default๋กœ [www.google.com](http://www.google.com) ์ด ์ ‘์†๋˜๋„๋ก ์„ค์ •ํ•˜์˜€๋‹ค.

	private fun initView() {
        webView.webViewClient = WebViewClient() // ์™ธ๋ถ€ ์›น๋ธŒ๋ผ์šฐ์ ธ๋กœ ์ „ํ™˜๋˜๋Š” ๊ฒƒ์„ ๋ง‰์Œ
        webView.settings.javaScriptEnabled = true // ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ์„ ํ—ˆ์šฉ
        webView.loadUrl("https://www.google.com")
    }

// webView ๊ฐ์ฒด๊ฐ€ ์ค‘์ฒฉ๋˜๋ฏ€๋กœ apply๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ์ข€ ๋” ์ด๋ป์ง„๋‹ค.
	private fun initView() {
        webView.apply {
            webViewClient = WebViewClient() // ์™ธ๋ถ€ ์›น๋ธŒ๋ผ์šฐ์ ธ๋กœ ์ „ํ™˜๋˜๋Š” ๊ฒƒ์„ ๋ง‰์Œ
            settings.javaScriptEnabled = true // ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ์„ ํ—ˆ์šฉ
            loadUrl("https://www.google.com")
        }
    }

์•ฑ์„ ์‹คํ–‰ํ•ด์„œ ๊ตฌ๊ธ€ ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•˜๋ฉด ์™ธ๋ถ€ ๋ธŒ๋ผ์šฐ์ ธ๋กœ ์ „ํ™˜๋˜๋Š” ๋ฒ„๊ทธ?๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์›น๋ธŒ๋ผ์šฐ์ ธ๊ฐ€ ์ด ์•ฑ์„ ์˜๋ฏธํ•˜๋„๋ก webViewClient๋ฅผ ์žฌ์„ค์ •ํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณค๋‹ค. ๋˜ํ•œ ์ด๋ ‡๊ฒŒ ๋กœ๋“œ๋œ ๊ตฌ๊ธ€ ์‚ฌ์ดํŠธ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ์ด ๋ง‰ํ˜€์ ธ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ขŒ์ธก ์ƒ๋‹จ์˜ ํ–„๋ฒ„๊ฑฐ ๋ฒ„ํŠผ์ด๋‚˜ ๊ฐ์ข… ๋ฒ„ํŠผ์ด ์‹คํ–‰์ด ์•ˆ๋˜๋Š” ์ด์œ ๊ฐ€ ๋ฐ”๋กœ ์—ฌ๊ธฐ์žˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด javaScriptEnabled ์†์„ฑ์„ ํ†ตํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ์„ ํ—ˆ๊ฐ€ํ•ด์คฌ๋‹ค.

bandicam 2021-09-22 09-25-09-304

bindView

default ๋กœ ๊ตฌ๊ธ€ ์‚ฌ์ดํŠธ๊ฐ€ ์ ‘์†๋˜๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ–ˆ๋‹ค. ๋‹ค์Œ์€ ์ฃผ์†Œ์ฐฝ์— url์„ ์ž…๋ ฅํ–ˆ์„ ๋•Œ ํ•ด๋‹น ์‚ฌ์ดํŠธ๋กœ ์ด๋™๋˜๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ์ด ๋•Œ setOnEditorActionListener ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. setOnClickListener ์™€ ๋™์ผํ•˜๋‹ค.

	<EditText
            android:id="@+id/addressBar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:imeOptions="actionDone"
            android:inputType="textUri"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@id/goHomeButton"
            app:layout_constraintRight_toLeftOf="@+id/goBackButton"
            app:layout_constraintTop_toTopOf="parent" />

EditText ์˜ต์…˜์— ๋„ฃ์–ด์ค€ imeOptions ์†์„ฑ์„ ์ด์šฉํ•œ๋‹ค. ์ด๋Š” EditText๋กœ ๋„์–ด์ง„ ํ‚ค๋ณด๋“œ์— ์†์„ฑ์„ ์ค€๋‹ค.

image

์šฐ์ธก ํ•˜๋‹จ์˜ ์™„๋ฃŒ ๋ฒ„ํŠผ์ด action_done ์†์„ฑ์ด๋‹ค. ์™„๋ฃŒ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฌ๋ฉด Listener ๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  action_id๋ฅผ ๋น„๊ตํ•œ๋‹ค. id๊ฐ€ action_done์ธ ๊ฒฝ์šฐ์— ์ฃผ์†Œ์ฐฝ์— ๋„ฃ์–ด์ค€ text๋ฅผ loadํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ false๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•ด๋„ [naver.com](http://naver.com) ์™€ ๊ฐ™์ด ๋ถˆ์™„์ „ํ•œ ์ƒํƒœ์˜ url์ธ ๊ฒฝ์šฐ์— ์ ‘์†์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.

image

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Manifest ์— usesCleartextTraffic ์ด๋ผ๋Š”์†์„ฑ์„ ์ค˜์„œ ์ž์ฒด์ ์œผ๋กœ [https://www](https://www) ๋ฅผ ๋ถ™์—ฌ์ฃผ๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

3. ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ

bindViews

home, back, forward ๋ฒ„ํŠผ์— ๋™์ž‘์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋‹ค. webView ํด๋ž˜์Šค์—์„œ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋‹ค ๊ตฌํ˜„์ด ๋˜์–ด ์žˆ์–ด์„œ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

	private fun bindViews() {
        addressBar.setOnEditorActionListener { v, actionId, event ->
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                webView.loadUrl(v.text.toString())
            }
            return@setOnEditorActionListener false
        }

        goBackButton.setOnClickListener {
            webView.goBack()
        }

        goForwardButton.setOnClickListener {
            webView.goForward()
        }

        goHomeButton.setOnClickListener {
            webView.loadUrl(DEFAULT_URL)
        }
    }

onBackPressed

ํ•˜์ง€๋งŒ ์ถ”๊ฐ€ํ•ด์ค„ ๊ฒƒ์ด ์žˆ๋Š”๋ฐ ์šฐ๋ฆฌ๊ฐ€ ์›น ๋ธŒ๋ผ์šฐ์ ธ ์–ดํ”Œ์„ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋ฉด ์•ˆ๋“œ๋กœ์ด๋“œ ์ž์ฒด UI์˜ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋”๋ผ๋„ ์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ง€๊ธˆ ์šฐ๋ฆฌ๊ฐ€ ๊ตฌํ˜„ํ•œ ์–ดํ”Œ์€ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋ฐ”๋กœ ์•ฑ์ด ์ข…๋ฃŒํ•˜๋Š”๋ฐ ์ด๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด onBackPressed ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•ด์คฌ๋‹ค.

	// ํ•˜๋‹จ๋ฐ”์˜ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋”๋ผ๋„ ์•ฑ์ด ์ข…๋ฃŒ๋˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด
    override fun onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack()
        } else {
            super.onBackPressed() // ํ•˜๋‹จ๋ฐ”์˜ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ์ข…๋ฃŒ๋˜๋Š” ๋ฉ”์†Œ๋“œ
        }
    }

๊ธฐ๋ณธ์ ์œผ๋กœ super.onBackPressed ๊ฐ€ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ์•ฑ์ด ์ข…๋ฃŒ๋˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค. ๋”ฐ๋ผ์„œ webView๊ฐ€ ์ด์ „ ํŽ˜์ด์ง€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ goBack ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ๋ชปํ•œ ๊ฒฝ์šฐ์—๋งŒ ์•ฑ์„ ์ข…๋ฃŒํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

4. ์™„์„ฑ๋„ ๋†’์ด๊ธฐ

์šฐ์„  ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ์€ ๊ตฌํ˜„์ด ์™„๋ฃŒ๋๋‹ค. ํ•˜์ง€๋งŒ ์•„์ง ๋ญ”๊ฐ€ ๋ถ€์กฑํ•˜๋‹ค. UI๊ฐ€ ์ด์˜์ง€ ์•Š์€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋ฅผ ์ˆ˜์ •ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

์ƒ๋‹จ๋ฐ” ๊พธ๋ฏธ๊ธฐ

ํ˜„์žฌ ์ƒ๋‹จ๋ฐ”์— ์กด์žฌํ•˜๋Š” 3๊ฐœ์˜ ๋ฒ„ํŠผ์„ ๋ณด๋ฉด ๋’ค์— ํšŒ์ƒ‰ ๋ฐฐ๊ฒฝ์ด ๋“ค์–ด๊ฐ„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด ?attr/selectableItemBackground ์†์„ฑ์„ ํ†ตํ•ด drawable ์ด๋ฏธ์ง€ ๊ณ ์œ ์˜ ๋ฐฐ๊ฒฝ์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

	<ImageButton
            android:id="@+id/goHomeButton"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="?attr/selectableItemBackground"
            android:src="@drawable/ic_home"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="1:1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ๊ธฐ์กด์— layout_width๊ฐ€ match_content์˜ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋Š”๋ฐ 0dp๋กœ ๋ณ€๊ฒฝ๋˜๋ฉด์„œ UI์—์„œ ์‚ฌ๋ผ์ง€๊ฒŒ ๋œ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด constraintDimenstionRatio ์†์„ฑ์œผ๋กœ ๊ฐ€๋กœ ์„ธ๋กœ 1:1์˜ ๋น„์œจ์„ ๊ฐ€์ง€๋„๋ก ์ˆ˜์ •ํ–ˆ๋‹ค.

์ƒ๋‹จ ์ฃผ์†Œ์ฐฝ ์—ญ์‹œ ๋ญ”๊ฐ€ ๋ฐ‹๋ฐ‹ํ•˜๋‹ค. drawable ์ด๋ฏธ์ง€๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์ด๋ฅผ ๊พธ๋ฉฐ์คฌ๋‹ค.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/light_gray" />
    <corners android:radius="16dp" />

</shape>

image

์ƒ๋‹จ๋ฐ”๊ฐ€ ์ „๋ณด๋‹ค ํ™•์‹คํžˆ ์ด๋ป์กŒ๋‹ค.

SwipeRefreshLayout

๊ทผ๋ฐ ๋ญ”๊ฐ€ ์•„์ง๋„ ๋ถ€์กฑํ•˜๋‹ค. ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ํ™”๋ฉด์„ reload ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ์—†์—ˆ๋‹ค. ํ™”๋ฉด์„ reload ํ•˜๊ธฐ ์œ„ํ•ด์„  ์šฐ์„  dependencies ์— ์ถ”๊ฐ€๋ฅผ ํ•ด์ค˜์•ผํ•œ๋‹ค.

dependencies {
    implementation 'androidx.core:core-ktx:1.6.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

swiperrefreshlayout ๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์‹œ activity_main.xml ๋กœ ๋„˜์–ด์™€์„œ reload ๊ฐ€ ํ•„์š”ํ•œ ๋ ˆ์ด์•„์›ƒ์ธ webView ์˜์—ญ์„ swiperrefreshlayout ์œผ๋กœ ๊ฐ์‹ธ์ฃผ๋ฉด ๋์ด๋‹ค.

	<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/refreshLayout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/toolBar">

        <WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

ํ•ด๋‹น ๋ ˆ์ด์•„์›ƒ๊ณผ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ ์–ธํ•˜๊ณ  ๋ฆฌ๋กœ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด reload ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ... reload bar ๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š๋Š”๋‹ค.

	inner class WebViewClient : android.webkit.WebViewClient() {
        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)
            refreshLayout.isRefreshing = false
        }
    }

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Inner class ๋กœ WebViewClient ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•ด์คฌ๋‹ค. ํŽ˜์ด์ง€ ๋กœ๋“œ๊ฐ€ ๋๋‚˜๋ฉด isRefreshing ์„ ์ข…๋ฃŒํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

image

ํŽ˜์ด์ง€ ๋กœ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด refresh ๊ฐ€ ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

progressBar

์ „์ฒด์ ์ธ UI๋Š” ์ˆ˜์ •ํ–ˆ์ง€๋งŒ ์•„์ง๋„ ๋ญ”๊ฐ€ ๋ถ€์กฑํ•œ ๋Š๋‚Œ์ด๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ์›นํŽ˜์ด์ง€๋ฅผ ๋ฐฉ๋ฌธํ•  ๋•Œ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋“œ๋˜๊ณ  ์žˆ๋Š”์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” progressBar ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

	<androidx.core.widget.ContentLoadingProgressBar
        android:id="@+id/progressBar"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="0dp"
        android:layout_height="2dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/toolBar" />

activity_main.xml ์— ProgressBar๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  style์„ ์ง€์ •ํ•ด์ค€๋‹ค. ์ˆ˜ํ‰์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” progressBar์ด๋ฏ€๋กœ horizontal ์†์„ฑ์„ ์ค€๋‹ค. ์šฐ์„  ํŽ˜์ด์ง€ ๋กœ๋”ฉ์„ ํ‘œ์‹œํ•  ๋ ˆ์ด์•„์›ƒ์€ ๊ตฌํ˜„ํ–ˆ๋Š”๋ฐ ์ž‘๋™์€ ์–ด๋–ป๊ฒŒ ํ• ๊นŒ? ์ด ๋•Œ WebChromeClient ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์œ„์—์„œ๋Š” WebClient , ์—ฌ๊ธฐ์„œ๋Š” WebChromeClient ๋‘˜์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ผ๊นŒ? WebChromeClient์€ ๋ธŒ๋ผ์šฐ์ € ๊ด€์ ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ˜ธ์ถœ ๋“ฑ ์ข€ ๋” ๋ณต์žกํ•œ ์ผ์„ ํ•  ์ˆ˜ ์žˆ๊ณ , WebClient๋Š” ๋‹จ์ˆœํžˆ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š”? ๊ทธ๋Ÿฐ ๋Š๋‚Œ์ด๋‹ค.

	private val progressBar: ContentLoadingProgressBar by lazy {
        findViewById(R.id.progressBar)
    }

	// ... ์ค‘๋žต

	inner class WebViewClient : android.webkit.WebViewClient() {
        override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
            super.onPageStarted(view, url, favicon)
            progressBar.show()
        }

        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)
            refreshLayout.isRefreshing = false
            progressBar.hide()
            goForwardButton.isEnabled = webView.canGoForward()
            goBackButton.isEnabled = webView.canGoBack()
            addressBar.setText(url)
        }
    }

	inner class WebChromeClient : android.webkit.WebChromeClient() {
        override fun onProgressChanged(view: WebView?, newProgress: Int) {
            super.onProgressChanged(view, newProgress)
            progressBar.progress = newProgress
        }
    }

์—ญ์‹œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์„ ํ†ตํ•ด progressBar ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ–ˆ๋‹ค. ๋˜ํ•œ WebViewClient์—์„œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์คฌ๋Š”๋ฐ ํŽ˜์ด์ง€๊ฐ€ ๋กœ๋”ฉ๋˜๊ธฐ ์‹œ์ž‘ํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” onPageStarted ์— show ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ณ , ํŽ˜์ด์ง€ ๋กœ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ํ˜ธ์ถœ๋˜๋Š” onPageFinished ์— hide ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ๋˜ํ•œ ๊ฐ Button์˜ isEnable ์„ ํ†ตํ•ด ์ด์ „ ํŽ˜์ด์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฌ์ง€ ์•Š๊ฒŒ, ๋‹ค์Œ ํŽ˜์ด์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์•ž์œผ๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฌ์ง€ ์•Š๊ฒŒ ๊ตฌํ˜„ํ–ˆ๋‹ค. ๋˜ํ•œ ์™„์ „ํ•œ url๋กœ ๋ฐ”๋€Œ๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

image

progressBar๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทผ๋ฐ ์ƒ๋‹จ๋ฐ”๊ฐ€ ๊ฑฐ์Šฌ๋ฆฐ๋‹ค.

image

NoActionBar ๋กœ ๋ณ€๊ฒฝํ•ด์„œ ์ƒ๋‹จ์˜ ActionBar๋ฅผ ์ œ๊ฑฐํ•ด์คฌ๋‹ค. ๋‚˜๋ฆ„ ๊ดœ์ฐฎ์€ ์›น๋ธŒ๋ผ์šฐ์ € ์•ฑ์„ ๋งŒ๋“ค์—ˆ๋‹ค.