Android webView 实现阻尼回弹效果

简介: iOS webView默认滑动到顶部或者底部的时候,还可以继续通过手指拉扯滑动,松手后回弹;而Android webView默认是不行的,要实现跟iOS一样的效果,就需要自定义webView。

ios中对可以滚动的视图都在系统层面上实现了触碰到边缘的阻尼回弹效果,用户一看便知自己的操作已经到了边界。android中也有类似的方案,不过当到达边界的时候不是用阻尼的方式,而是逐渐显示一个渐变颜色。

显然iOS的效果对用户体验来说更加的友好,Android可以通过自定义View的方式来实现类似iOS一样的阻尼回弹效果,大致的逻辑是,通过监听Touch事件,当滑动到底部或顶部的时候,继续向下/向上拖动时,通过添加偏移量重新layout控件,让控件超出原来设定的区域,达到可以继续拖扯的效果,当手指松开时,控件再次layout到原来位置,同时添加阻尼回弹效果,即可实现类似于iOS的回弹效果,代码具体如下(以webView为例,ScrollView 的做法一致):

class ScrollableWebview @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : WebView(context, attrs) {
    //Y轴本次点击的位置
    private var currentY = 0

    //Y轴本次down点击的位置
    private var startY = 0

    //Y轴上次move事件点击的位置
    private var lastY = 0

    //Y轴上两次move事件之间的偏移量
    private var offset = 0

    //Y轴上两次move事件之间的偏移量*系数
    private var curOffset = 0
    private val scrollFactor = 0.35f
    private val scrollIv = 200
    private var canScroll = false
    private val rect = Rect()

    //是否正在scrolled中
    private var isScrolled = false
    override fun onOverScrolled(scrollX: Int, scrollY: Int, clampedX: Boolean, clampedY: Boolean) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY)
        //这个方法在webview内容滑动到顶部和底部时调用
        log("onOverScrolled scrollX $scrollX scrollY $scrollY clampedX $clampedX clampedY $clampedY")
        canScroll = clampedY
    }

    companion object {
        private const val TAG = "ScrollableWebview"
    }

    private fun log(message: String) {
        Log.d(TAG, message)
    }

    override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
        super.onWindowFocusChanged(hasWindowFocus)
        Log.d(TAG, "onFinishInflate left $left top $top  right $right bottom $bottom")
        rect.set(left, top, right, bottom)

    }

    override fun onTouchEvent(ev: MotionEvent): Boolean {
        //拦截这个方法
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                startY = ev.y.toInt()
            }
            MotionEvent.ACTION_MOVE -> {
                if (canScroll) {
                    currentY = ev.y.toInt()
                    offset = currentY - lastY
                    curOffset = (offset * scrollFactor).toInt()
                    lastY = currentY
                    if (currentY != startY && 0 < abs(offset) && abs(offset) < scrollIv) {
                        isScrolled = true
                        layout(
                            left,
                            top + curOffset,
                            right,
                            bottom + curOffset
                        )
                    }
                }
            }
            MotionEvent.ACTION_UP -> {
                if (isScrolled) {
                    upDownMoveAnimation()
                    layout(rect.left, rect.top, rect.right, rect.bottom)
                }
            }
            else -> {}
        }

        return super.onTouchEvent(ev)
    }

    // 初始化上下回弹的动画效果
    private fun upDownMoveAnimation() {
        val animation = TranslateAnimation(
            0.0f, 0.0f,
            top.toFloat(), rect.top.toFloat()
        )
        animation.duration = 800
        animation.fillAfter = true
        //设置阻尼动画效果
        animation.interpolator = SpringInterpolation()
        this.animation = animation
    }

    class SpringInterpolation : Interpolator {
        override fun getInterpolation(input: Float): Float {
            val minus10 = -10
            val int4 = 4
            val factor=4
            return (2.0.pow((minus10 * input).toDouble()) * sin((input - factor / int4) * (2 * Math.PI) / factor) + 1).toFloat()
        }
    }
}
相关文章
|
API Android开发 数据安全/隐私保护
解决android webview 加载http url 失败 net::ERR_CLEARTEXT_NOT_PERMITTED 错误
解决android webview 加载http url 失败 net::ERR_CLEARTEXT_NOT_PERMITTED 错误
951 0
|
21天前
|
程序员 开发工具 Android开发
Android|WebView 禁止长按,限制非白名单域名的跳转层级
如何限制 WebView 仅域名白名单网址能随意跳转,并禁用长按选择文字。
28 2
|
5月前
|
安全 JavaScript 前端开发
kotlin开发安卓app,JetPack Compose框架,给webview新增一个按钮,点击刷新网页
在Kotlin中开发Android应用,使用Jetpack Compose框架时,可以通过添加一个按钮到TopAppBar来实现WebView页面的刷新功能。按钮位于右上角,点击后调用`webViewState?.reload()`来刷新网页内容。以下是代码摘要:
|
5月前
|
JavaScript 前端开发 Android开发
kotlin安卓在Jetpack Compose 框架下使用webview , 网页中的JavaScript代码如何与native交互
在Jetpack Compose中使用Kotlin创建Webview组件,设置JavaScript交互:`@Composable`函数`ComposableWebView`加载网页并启用JavaScript。通过`addJavascriptInterface`添加`WebAppInterface`类,允许JavaScript调用Android方法如播放音频。当页面加载完成时,执行`onWebViewReady`回调。
|
4月前
|
Web App开发 JavaScript 前端开发
Android端使用WebView注入一段js代码实现js调用android
Android端使用WebView注入一段js代码实现js调用android
108 0
|
5月前
|
Web App开发 移动开发 前端开发
52. 【Android教程】网页视图:WebView
52. 【Android教程】网页视图:WebView
90 1
|
5月前
|
安全 网络安全 API
kotlin安卓开发JetPack Compose 如何使用webview 打开网页时给webview注入cookie
在Jetpack Compose中使用WebView需借助AndroidView。要注入Cookie,首先在`build.gradle`添加WebView依赖,如`androidx.webkit:webkit:1.4.0`。接着创建自定义`ComposableWebView`,通过`CookieManager`设置接受第三方Cookie并注入Cookie字符串。最后在Compose界面使用这个自定义组件加载URL。注意Android 9及以上版本可能需要在网络安全配置中允许第三方Cookie。
|
6月前
|
XML Android开发 数据格式
安卓和webview交互
安卓和webview交互
61 0
|
6月前
|
XML Android开发 数据格式
安卓和webview交互
安卓和webview交互
101 1
|
小程序 Android开发 iOS开发
在钉钉小程序中安卓无法打开webview
在钉钉小程序中安卓无法打开webview
201 1