Skip to content

Commit

Permalink
新增拖拽边界等
Browse files Browse the repository at this point in the history
  • Loading branch information
Lewis committed Mar 9, 2021
1 parent 3f67d92 commit 31259fe
Show file tree
Hide file tree
Showing 11 changed files with 426 additions and 181 deletions.
29 changes: 29 additions & 0 deletions easyfloat/src/main/java/com/lzf/easyfloat/EasyFloat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.lzf.easyfloat.interfaces.OnPermissionResult
import com.lzf.easyfloat.permission.PermissionUtils
import com.lzf.easyfloat.utils.LifecycleUtils
import com.lzf.easyfloat.interfaces.FloatCallbacks
import com.lzf.easyfloat.utils.DisplayUtils
import com.lzf.easyfloat.utils.Logger
import java.lang.Exception

Expand Down Expand Up @@ -87,6 +88,15 @@ class EasyFloat {
@JvmOverloads
fun getFloatView(tag: String? = null): View? = getConfig(tag)?.layoutView

/**
* 更新浮窗坐标,未指定坐标执行吸附动画
* @param tag 浮窗标签
* @param x 更新后的X轴坐标
* @param y 更新后的Y轴坐标
*/
fun updateFloat(tag: String? = null, x: Int = -1, y: Int = -1) =
FloatingWindowManager.getHelper(tag)?.updateFloat(x, y)

// 以下几个方法为:系统浮窗过滤页面的添加、移除、清空
/**
* 为当前浮窗过滤,设置需要过滤的Activity
Expand Down Expand Up @@ -200,6 +210,25 @@ class EasyFloat {
*/
fun setLocation(x: Int, y: Int) = apply { config.locationPair = Pair(x, y) }

/**
* 设置浮窗的拖拽边距值
* @param left 浮窗左侧边距
* @param top 浮窗顶部边距
* @param right 浮窗右侧边距
* @param bottom 浮窗底部边距
*/
fun setBorder(
left: Int = 0,
top: Int = -DisplayUtils.getStatusBarHeight(activity),
right: Int = DisplayUtils.getScreenWidth(activity),
bottom: Int = DisplayUtils.getScreenHeight(activity)
) = apply {
config.leftBorder = left
config.topBorder = top
config.rightBorder = right
config.bottomBorder = bottom
}

/**
* 设置浮窗的标签:只有一个浮窗时,可以不设置;
* 有多个浮窗必须设置不容的浮窗,不然没法管理,所以禁止创建相同标签的浮窗
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,4 +319,19 @@ internal class FloatingWindowHelper(val context: Context, var config: FloatConfi
Logger.e("浮窗关闭出现异常:$e")
}

/**
* 更新浮窗坐标
*/
fun updateFloat(x: Int, y: Int) {
frameLayout?.let {
if (x == -1 && y == -1) {
// 未指定具体坐标,执行吸附动画
it.postDelayed({ touchUtils.updateFloat(it, params, windowManager) }, 200)
} else {
params.x = x
params.y = y
windowManager.updateViewLayout(it, params)
}
}
}
}
107 changes: 82 additions & 25 deletions easyfloat/src/main/java/com/lzf/easyfloat/core/TouchUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.lzf.easyfloat.data.FloatConfig
import com.lzf.easyfloat.enums.ShowPattern
import com.lzf.easyfloat.enums.SidePattern
import com.lzf.easyfloat.utils.DisplayUtils
import kotlin.math.max
import kotlin.math.min

/**
Expand All @@ -28,6 +29,12 @@ internal class TouchUtils(val context: Context, val config: FloatConfig) {
private var parentHeight = 0
private var parentWidth = 0

// 四周坐标边界值
private var leftBorder = 0
private var topBorder = 0
private var rightBorder = 0
private var bottomBorder = 0

// 起点坐标
private var lastX = 0f
private var lastY = 0f
Expand Down Expand Up @@ -70,17 +77,16 @@ internal class TouchUtils(val context: Context, val config: FloatConfig) {
// 记录触摸点的位置
lastX = event.rawX
lastY = event.rawY
// 屏幕宽高需要每次获取,可能会有屏幕旋转、虚拟导航栏的状态变化
parentWidth = DisplayUtils.getScreenWidth(context)
parentHeight = config.displayHeight.getDisplayRealHeight(context)
// 获取在整个屏幕内的绝对坐标
view.getLocationOnScreen(location)
// 通过绝对高度和相对高度比较,判断包含顶部状态栏
statusBarHeight = if (location[1] > params.y) statusBarHeight(view) else 0
emptyHeight = parentHeight - view.height - statusBarHeight
// 初始化一些边界数据
initBoarderValue(view, params)
}

MotionEvent.ACTION_MOVE -> {
// 过滤边界值之外的拖拽
if (event.rawX < leftBorder || event.rawX > rightBorder + view.width
|| event.rawY < topBorder || event.rawY > bottomBorder + view.width
) return

// 移动值 = 本次触摸值 - 上次触摸值
val dx = event.rawX - lastX
val dy = event.rawY - lastY
Expand All @@ -92,8 +98,8 @@ internal class TouchUtils(val context: Context, val config: FloatConfig) {
var y = params.y + dy.toInt()
// 检测浮窗是否到达边缘
x = when {
x < 0 -> 0
x > parentWidth - view.width -> parentWidth - view.width
x < leftBorder -> leftBorder
x > rightBorder -> rightBorder
else -> x
}

Expand All @@ -104,11 +110,12 @@ internal class TouchUtils(val context: Context, val config: FloatConfig) {
}

y = when {
y < topBorder -> topBorder
// 状态栏沉浸时,最小高度为-statusBarHeight,反之最小高度为0
y < 0 -> if (config.immersionStatusBar) {
if (y < -statusBarHeight) -statusBarHeight else y
} else 0
y > emptyHeight -> emptyHeight
y > bottomBorder -> bottomBorder
else -> y
}

Expand Down Expand Up @@ -154,7 +161,7 @@ internal class TouchUtils(val context: Context, val config: FloatConfig) {
lastY = event.rawY
}

MotionEvent.ACTION_UP -> {
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
if (!config.isDrag) return
// 回调拖拽事件的ACTION_UP
config.callbacks?.drag(view, event)
Expand All @@ -178,48 +185,98 @@ internal class TouchUtils(val context: Context, val config: FloatConfig) {
}
}

/**
* 根据吸附类别,更新浮窗位置
*/
fun updateFloat(
view: View,
params: LayoutParams,
windowManager: WindowManager
) {
initBoarderValue(view, params)
sideAnim(view, params, windowManager)
}

/**
* 初始化边界值等数据
*/
private fun initBoarderValue(view: View, params: LayoutParams) {
// 屏幕宽高需要每次获取,可能会有屏幕旋转、虚拟导航栏的状态变化
parentWidth = DisplayUtils.getScreenWidth(context)
parentHeight = config.displayHeight.getDisplayRealHeight(context)
// 获取在整个屏幕内的绝对坐标
view.getLocationOnScreen(location)
// 通过绝对高度和相对高度比较,判断包含顶部状态栏
statusBarHeight = if (location[1] > params.y) statusBarHeight(view) else 0
emptyHeight = parentHeight - view.height - statusBarHeight

leftBorder = max(0, config.leftBorder)
rightBorder = min(parentWidth, config.rightBorder) - view.width
topBorder = if (config.showPattern == ShowPattern.CURRENT_ACTIVITY) {
// 单页面浮窗,坐标屏幕顶部计算
if (config.immersionStatusBar) config.topBorder
else config.topBorder + statusBarHeight(view)
} else {
// 系统浮窗,坐标从状态栏底部开始,沉浸时坐标为负
if (config.immersionStatusBar) config.topBorder - statusBarHeight(view) else config.topBorder
}
bottomBorder = if (config.showPattern == ShowPattern.CURRENT_ACTIVITY) {
// 单页面浮窗,坐标屏幕顶部计算
if (config.immersionStatusBar)
min(emptyHeight, config.bottomBorder - view.height)
else
min(emptyHeight, config.bottomBorder + statusBarHeight(view) - view.height)
} else {
// 系统浮窗,坐标从状态栏底部开始,沉浸时坐标为负
if (config.immersionStatusBar)
min(emptyHeight, config.bottomBorder - statusBarHeight(view) - view.height)
else
min(emptyHeight, config.bottomBorder - view.height)
}
}

private fun sideAnim(
view: View,
params: LayoutParams,
windowManager: WindowManager
) {
initDistanceValue(params, view)
initDistanceValue(params)
val isX: Boolean
val end = when (config.sidePattern) {
SidePattern.RESULT_LEFT -> {
isX = true
0
leftBorder
}
SidePattern.RESULT_RIGHT -> {
isX = true
params.x + rightDistance
}
SidePattern.RESULT_HORIZONTAL -> {
isX = true
if (leftDistance < rightDistance) 0 else params.x + rightDistance
if (leftDistance < rightDistance) leftBorder else params.x + rightDistance
}

SidePattern.RESULT_TOP -> {
isX = false
if (config.immersionStatusBar) -statusBarHeight else 0
topBorder
}
SidePattern.RESULT_BOTTOM -> {
isX = false
// 不要轻易使用此相关模式,需要考虑虚拟导航栏的情况
emptyHeight
bottomBorder
}
SidePattern.RESULT_VERTICAL -> {
isX = false
if (topDistance < bottomDistance) 0 else emptyHeight
if (topDistance < bottomDistance) topBorder else bottomBorder
}

SidePattern.RESULT_SIDE -> {
if (minX < minY) {
isX = true
if (leftDistance < rightDistance) 0 else params.x + rightDistance
if (leftDistance < rightDistance) leftBorder else params.x + rightDistance
} else {
isX = false
if (topDistance < bottomDistance) if (config.immersionStatusBar) -statusBarHeight else 0 else emptyHeight
if (topDistance < bottomDistance) topBorder else bottomBorder
}
}
else -> return
Expand Down Expand Up @@ -262,11 +319,11 @@ internal class TouchUtils(val context: Context, val config: FloatConfig) {
/**
* 计算一些边界距离数据
*/
private fun initDistanceValue(params: LayoutParams, view: View) {
leftDistance = params.x
rightDistance = parentWidth - (leftDistance + view.right)
topDistance = params.y
bottomDistance = emptyHeight - topDistance
private fun initDistanceValue(params: LayoutParams) {
leftDistance = params.x - leftBorder
rightDistance = rightBorder - params.x
topDistance = params.y - topBorder
bottomDistance = bottomBorder - params.y

minX = min(leftDistance, rightDistance)
minY = min(topDistance, bottomDistance)
Expand Down
6 changes: 6 additions & 0 deletions easyfloat/src/main/java/com/lzf/easyfloat/data/FloatConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ data class FloatConfig(
var locationPair: Pair<Int, Int> = Pair(0, 0),
// ps:优先使用固定坐标,若固定坐标不为原点坐标,gravity属性和offset属性无效

// 四周边界值
var leftBorder: Int = 0,
var topBorder: Int = -999,
var rightBorder: Int = 9999,
var bottomBorder: Int = 9999,

// Callbacks
var invokeView: OnInvokeView? = null,
var callbacks: OnFloatCallbacks? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import java.io.InputStreamReader

/**
* @author: liuzhenfeng
* @github:https://github.com/princekin-f/EasyHttp
* @github:https://github.com/princekin-f/EasyFloat
* @function: 判断手机ROM
* @date: 2020-01-07 22:30
*/
Expand Down Expand Up @@ -40,7 +40,7 @@ object RomUtils {
input = BufferedReader(InputStreamReader(p.inputStream), 1024)
line = input.readLine()
input.close()
} catch (ex: IOException) {
} catch (ex: Exception) {
Log.e(TAG, "Unable to read sysprop $propName", ex)
return null
} finally {
Expand Down
1 change: 1 addition & 0 deletions example/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<activity android:name=".activity.SecondActivity" />
<activity android:name=".activity.JavaTestActivity" />
<activity android:name=".activity.SwipeTestActivity" />
<activity android:name=".activity.BorderTestActivity" />

</application>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.lzf.easyfloat.example.activity

import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.widget.ImageView
import com.lzf.easyfloat.EasyFloat
import com.lzf.easyfloat.enums.SidePattern
import com.lzf.easyfloat.example.R
import com.lzf.easyfloat.utils.DisplayUtils
import kotlinx.android.synthetic.main.activity_border_test.*

/**
* @author: liuzhenfeng
* @date: 3/9/21 11:27
* @Package: com.lzf.easyfloat.example.activity
* @Description:
*/
class BorderTestActivity : BaseActivity() {

private val tag = "borderTest"

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_border_test)

tv_show.setOnClickListener { showBorderTest() }
tv_dismiss.setOnClickListener { EasyFloat.dismiss(tag) }
}

private fun showBorderTest() {
EasyFloat.with(this)
.setTag(tag)
.setLayout(R.layout.float_border_test) {
val ivLogo = it.findViewById<ImageView>(R.id.iv_logo)
val ivLogo2 = it.findViewById<ImageView>(R.id.iv_logo2)
ivLogo.setOnClickListener {
ivLogo2.visibility =
if (ivLogo2.visibility == View.VISIBLE) View.GONE else View.VISIBLE
EasyFloat.updateFloat(tag)
}
ivLogo2.setOnClickListener {
ivLogo.visibility =
if (ivLogo.visibility == View.VISIBLE) View.GONE else View.VISIBLE
EasyFloat.updateFloat(tag)
}
}
.setBorder(
30f.dp2px(), 50f.dp2px(),
DisplayUtils.getScreenWidth(this) - 30f.dp2px(),
DisplayUtils.getScreenHeight(this) - 180f.dp2px()
)
.setGravity(Gravity.CENTER)
.setSidePattern(SidePattern.RESULT_SIDE)
.show()
}

private fun Float.dp2px() = DisplayUtils.dp2px(this@BorderTestActivity, this)

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class MainActivity : BaseActivity(), View.OnClickListener {

openSecond.setOnClickListener(this)
openSwipeTest.setOnClickListener(this)
openBorderTest.setOnClickListener(this)
}

override fun onClick(v: View?) {
Expand Down Expand Up @@ -79,6 +80,7 @@ class MainActivity : BaseActivity(), View.OnClickListener {

openSecond -> startActivity<SecondActivity>(this)
openSwipeTest -> startActivity<SwipeTestActivity>(this)
openBorderTest -> startActivity<BorderTestActivity>(this)

else -> return
}
Expand Down
Loading

0 comments on commit 31259fe

Please sign in to comment.