[Android] 引っ張って閉じるWebView作った

引っ張ったらViewを少しずつ小さくしてしきい値を超えたら閉じるっていうWebViewFragment作った。

こんなの。

ベースはこのクラス使ったw

ってことで実装。

スポンサーリンク

実装

ジェスチャーを検知できるWebViewを作成

class ObservableWebView : WebView {

    interface OnScrollChangedListener {
        fun onScroll(l: Int, t: Int)
    }
    private var gd: GestureDetector? = null
    private var listener: GestureDetector.SimpleOnGestureListener? = null
    private var scrollChangedListener: OnScrollChangedListener? = null

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttrs: Int) : super(context, attrs, defStyleAttrs)

    override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
        super.onScrollChanged(l, t, oldl, oldt)
        scrollChangedListener?.onScroll(l, t)
    }

    fun setListener(listener: GestureDetector.SimpleOnGestureListener) {
        this.listener = listener
        gd = GestureDetector(context, listener)
    }


    fun setOnScrollChangedCallback(onScrollChangedListener: OnScrollChangedListener) {
        scrollChangedListener = onScrollChangedListener
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {

        gd?.onTouchEvent(event)
        return super.onTouchEvent(event)
    }

}

雑だけどw

基本的には↑に乗せてる記事と一緒で、ジェスチャーイベントを検知できるようにしただけ。

Fragmentのレイアウトファイル

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/backgroundLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#77777777">


    <FrameLayout
        android:id="@+id/topLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <hoge.package.view.ObservableWebView
            android:id="@+id/webView"
            android:overScrollMode="never"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <ImageView
            android:id="@+id/closeImageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:src="@drawable/icon_web_close" />
    </FrameLayout>

    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:visibility="gone" />

</FrameLayout>

スケールを小さくするようのViewの下にWebViewを置く感じ。

WebViewを直接操作したらタッチ位置がずれるのかガクガクした。。。ような気もした。

もっと良いレイアウト構成あったら教えてほしい。

引っ張って小さくする、そして閉じる

//
view.webView.apply {

    webChromeClient = WebChromeClient()
    webViewClient = object : WebViewClient() {

        override fun onPageStarted(webiew: WebView?, url: String?, favicon: Bitmap?) {
            view.progressBar.visibility = View.VISIBLE
            super.onPageStarted(webiew, url, favicon)
        }

        override fun onPageFinished(webview: WebView?, url: String?) {
            super.onPageFinished(webview, url)
            view.progressBar.visibility = View.INVISIBLE

        }
    }
    settings.apply {
        javaScriptEnabled = true
        isVerticalFadingEdgeEnabled = false
        isVerticalScrollBarEnabled = false
    }
    isFocusable = false

    setOnScrollChangedCallback(object : ObservableWebView.OnScrollChangedListener {
        override fun onScroll(l: Int, t: Int) {
            webViewScrollOffset = t
        }
    })

    setListener(object : GestureDetector.SimpleOnGestureListener() {

        override fun onDown(e: MotionEvent?): Boolean {
            oldY = e?.y ?: 0f
            return true
        }

        override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {

            if (webViewScrollOffset > 0) return super.onScroll(e1, e2, distanceX, distanceY)

            e2?.also {
                val dest = it.y - oldY
                if (dest > 0) {
                    val scale = 1 - (dest / 1000)
                    view.topLayout.scaleX = scale
                    view.topLayout.scaleY = scale
                    if (scale < 0.8) {
                        view.backgroundLayout.setBackgroundColor(
                            ContextCompat.getColor(
                                view.context,
                                android.R.color.transparent
                            )
                        )
                        activity?.onBackPressed()
                    }
                } else {
                    view.topLayout.scaleX = 1f
                    view.topLayout.scaleY = 1f
                }

            }
            return super.onScroll(e1, e2, distanceX, distanceY)
        }
    })

    loadUrl(loadUrl)
}

onScrollを受信したらもりもりViewを縮小させて閾値超えたら閉じる。

とりあえずこれで動画のような動きにはなる。

タイトルとURLをコピーしました