【Android】ドラッグ可能なwebView

## webViewをドラッグしたい！
アプリ開発をしている中で、ドラッグして大きさが変えられるwebViewを作ることになりました。
ドラッグして操作できるviewというのを作ったことがなかったので、色々試してみた結果を残しておきます。

## パターン１：全体を上下にスライド
DraggableBrowse()がメインのViewです。
DraggableArea()がドラッグする時につかむところ、BrowserWebViewはそのままwebViewです。
以下のコードではDraggableAreaで`Modifier.draggable`を使って、上下にドラッグしたときにoffsetを増減させています。
このoffsetをDraggableBrowserのColumnの`Modifier.offset`に渡してあげることでドラッグを実現させています。
DraggableBrowser全体が上下に移動するようなイメージです。

```kotlin
@Composable
private fun DraggableBrowser() {
    var offsetY by remember { mutableFloatStateOf(0f) }
    Column(
        Modifier
            .windowInsetsPadding(WindowInsets.statusBars)
            .fillMaxWidth()
            .offset { IntOffset(x = 0, y = offsetY.roundToInt()) },
        verticalArrangement = Arrangement.Bottom,
    ) {
        DraggableArea(
            modifier = Modifier
                .fillMaxWidth()
                .draggable(
                    orientation = Orientation.Vertical,
                    state = rememberDraggableState { delta ->
                        offsetY = (offsetY + delta).coerceAtLeast(0f)
                    },
                )
        )
        BrowserWebView(url = "https://www.youtube.com/")
    }
}

@Composable
private fun DraggableArea(modifier: Modifier) {
    Row(
        modifier = modifier
            .fillMaxWidth()
            .height(30.dp)
            .background(color = Color.Black),
        horizontalArrangement = Arrangement.Center,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Box(
            modifier = Modifier
                .size(width = 40.dp, height = 4.dp)
                .border(2.dp, Color.White)
                .background(Color.White)
        )
    }
}

@SuppressLint("SetJavaScriptEnabled")
@Composable
private fun BrowserWebView(url: String, modifier: Modifier = Modifier) {
    val isInspecting = LocalInspectionMode.current
    var webView: WebView? by remember { mutableStateOf(null) }
    Column {
        AndroidView(
            modifier = modifier.clipToBounds(),
            factory = {
                WebView(it).apply {
                    if (!isInspecting) {
                        settings.javaScriptEnabled = true
                        settings.domStorageEnabled = true
                    }
                    layoutParams = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                    webViewClient = WebViewClient()
                    webChromeClient = WebChromeClient()
                    loadUrl(url)
                }
            },
            update = { newWebView ->
                if (isInspecting) return@AndroidView
                webView = newWebView
            }
        )
    }
}
```

## パターン2: webViewを拡大・縮小
こちらのパターンでは、webViewの大きさを変更します。
`LocalConfiguration.current.screenHeightDp`であらかじめ画面全体の高さを取得しておきます。
DraggableAreaの`Modifier.draggable`では上下のドラッグに合わせてwindowSizePxを増減させます。
このwindowSizePxをBrowserWebViewの高さとして設定することで、webViewそのものの高さを増減させることで、ドラッグして引っ張ったり押し込めたりしているように見せることができます。
`Modifier.height()` はpx のままだと適用できないので、`with(density) { windowSizePx.toDp() }`でdpに変換してから渡しています。

```kotlin
@Composable
private fun DraggableBrowser() {
    val density = LocalDensity.current
    val screenHeightPx = with(density) { LocalConfiguration.current.screenHeightDp.dp.toPx() }
    var windowSizePx by remember { mutableFloatStateOf(screenHeightPx) }
    Box(modifier = Modifier.fillMaxSize()) {
        Column(
            Modifier
                .windowInsetsPadding(WindowInsets.statusBars)
                .fillMaxWidth()
                .align(Alignment.BottomCenter),
            verticalArrangement = Arrangement.Bottom,
        ) {
            DraggableArea(
                modifier = Modifier
                    .fillMaxWidth()
                    .draggable(
                        orientation = Orientation.Vertical,
                        state = rememberDraggableState { delta ->
                            windowSizePx = (windowSizePx - delta).coerceAtMost(screenHeightPx)
                        },
                    )
            )
            BrowserWebView(
                url = "https://www.youtube.com/",
                modifier = Modifier.height(with(density) { windowSizePx.toDp() }),
            )
        }
    }
}

@Composable
private fun DraggableArea(modifier: Modifier) {
    Row(
        modifier = modifier
            .fillMaxWidth()
            .height(30.dp)
            .background(color = Color.Black),
        horizontalArrangement = Arrangement.Center,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Box(
            modifier = Modifier
                .size(width = 40.dp, height = 4.dp)
                .border(2.dp, Color.White)
                .background(Color.White)
        )
    }
}

@SuppressLint("SetJavaScriptEnabled")
@Composable
private fun BrowserWebView(url: String, modifier: Modifier = Modifier) {
    val isInspecting = LocalInspectionMode.current
    var webView: WebView? by remember { mutableStateOf(null) }
    Column {
        AndroidView(
            modifier = modifier.clipToBounds(),
            factory = {
                WebView(it).apply {
                    if (!isInspecting) {
                        settings.javaScriptEnabled = true
                        settings.domStorageEnabled = true
                    }
                    layoutParams = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                    webViewClient = WebViewClient()
                    webChromeClient = WebChromeClient()
                    loadUrl(url)
                }
            },
            update = { newWebView ->
                if (isInspecting) return@AndroidView
                webView = newWebView
            }
        )
    }
}
```

## ドラッグできた
どちらの方法でもドラッグすることができました。
好みで多分大丈夫だとは思いますが、状況によってはうまくいかないこともあると思うのでお気をつけください。
（xmlのcomposeViewにsetContentして使うとうまくいかないこともあるかも......）