0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Android】ドラッグ可能なwebView

Posted at

webViewをドラッグしたい!

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

パターン1:全体を上下にスライド

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

@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に変換してから渡しています。

@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して使うとうまくいかないこともあるかも......)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?