popwindow实现可拖动+滑到屏幕外+屏幕外回弹

可拖动效果

fun makeDraggable(popupWindow: PopupWindow) {
        popupWindow.contentView.setOnTouchListener(object : View.OnTouchListener {
            var lastX = 0f
            var lastY = 0f
            var isDragging = false
            override fun onTouch(v: View?, event: MotionEvent): Boolean {
                val touchSlop = ViewConfiguration.getTouchSlop() * 2

                when (event.action) {
                    MotionEvent.ACTION_DOWN -> {
                        lastX = event.rawX
                        lastY = event.rawY
                        isDragging = false
                        return isDragging
                    }
                    MotionEvent.ACTION_MOVE -> {
                        val dx = event.rawX - lastX
                        val dy = event.rawY - lastY

                        if (Math.abs(dx) > touchSlop || Math.abs(dy) > touchSlop) {
                            val decorView = popupWindow.contentView.parent as ViewGroup //popwindow的内部变量decorView
                            val lp = decorView.layoutParams as WindowManager.LayoutParams
                            lp.flags = lp.flags or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                            popupWindow.update(lp.x + dx.toInt(), lp.y + dy.toInt(), -1, -1)
                            lastX = event.rawX
                            lastY = event.rawY
                            isDragging = true
                        }
                        return isDragging
                    }
                    MotionEvent.ACTION_UP -> {
                        return isDragging
                    }
                }
                return true
            }

        })
    }

用法很简单,只需要调用
makeDraggable(yourPopupWindow)

支持滑到屏幕外

默认是不允许滑动屏幕外的,要想支持滑到屏幕外也很简单
popupWindow.isClippingEnabled = false

支持屏幕外回弹

当支持滑到屏幕外时候通常都需要有回弹效果,即松手时从屏幕外回弹到屏幕内。
只要在松手时使用属性动画即刻(处理MotionEvent.ACTION_UP 事件)

MotionEvent.ACTION_UP -> {
    ...
    ...

    val supportRollback = true
    if (supportRollback) {
        var tartgetX = 0
        var tartgetY = 0
        val decorView = popupWindow.contentView.parent as ViewGroup //popwindow的内部变量decorView
        val lp = decorView.layoutParams as WindowManager.LayoutParams
        tartgetX = Math.min(Math.max(lp.x, 0), ScreenUtils.getScreenWidth() - popupWindow.width)
        tartgetY = Math.min(Math.max(lp.y, 0), ScreenUtils.getScreenHeight() - popupWindow.height)
        if (tartgetX != lp.x || tartgetY != lp.y) {
            val ofObject = ValueAnimator.ofObject(TypeEvaluator<Point> { fraction, startValue, endValue ->
                Point((startValue.x + (endValue.x - startValue.x) * fraction).toInt(),
                        (startValue.y + (endValue.y - startValue.y) * fraction).toInt())
            }, Point(lp.x, lp.y), Point(tartgetX, tartgetY))
            ofObject.addUpdateListener {
                val value = it.animatedValue as Point
                popupWindow.update(value.x, value.y, -1, -1)
            }
            ofObject.interpolator = LinearInterpolator()
            ofObject.start()
        }
    }

   ...
   ...
}

当需要给回弹设置一个边界(默认是手机屏幕四边),只需要改下面两行代码

tartgetX = Math.min(Math.max(lp.x, 0), ScreenUtils.getScreenWidth() - popupWindow.width)//(0代表左边界,ScreenUtils.getScreenWidth()代表右边界)
tartgetY = Math.min(Math.max(lp.y, 0), ScreenUtils.getScreenHeight() - popupWindow.height)//(0代表上边界,ScreenUtils.getScreenWidth()代表下边界)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,319评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,676评论 2 59
  • 一个个圆滚滚 有点调皮 又很规矩 挤挤挨挨 你压着我 我踩着你 手足情深 本是同根 鼓鼓囊囊 低垂着头 自信而不张...
    梦之芬芳阅读 268评论 0 0
  • 引言 代码格式决定读者对代码质量最初的判断。好的格式能够增强代码的可读性,并且能让读者阅读代码的时候心情愉悦。 ...
    前进中的奋斗猿阅读 512评论 0 1
  • (一) 老屋残墙无影踪,高楼庭院绿荫浓。 农民种地四时乐,机械耕耘五谷丰。 妇幼猎奇开电脑,亲朋问候拨联通。 客来...
    果苗儿阅读 555评论 0 1