網站首頁 編程語言 正文
1,背景
在開發中總會遇到一個可拖拽的懸浮View,不管是在開發中,還是在線上,都時長有這樣的控件,我們通常遇到這種情況,經常需要自己封裝,需要耗費時間,我這邊封裝了一個可以通用的懸浮可拖拽View,這樣使用的時候,只需要傳入自己要設計的樣式和位置既可
2,思路
2.1,封裝通用的基礎懸浮View
設計通用的父View
1,傳入的childView是可以自定義layout,可以傳入任何樣式
childView = setChildView()
2,可以設置初始的位置
layoutParams = setChildInitLayoutParams()
3,可以修改自定義view控件
setChildAction(childView)
4,提供點擊事件處理
protected abstract fun setEventClick()
子view繼承父view就可以實現自己想要的功能了
abstract class AbsParentDragView : FrameLayout, View.OnTouchListener {
//需要添加的子控件
private var childView: View? = null
//子控件的寬
protected var childWidth: Int = 0
//子控件的高
protected var childHeight: Int = 0
//子控件的位置屬性
lateinit var layoutParams: LayoutParams
//點擊區域偏移量
private var regionW: Int = 0
//判斷是否可以移動
private var isCanMove: Boolean = false
private val MIN_TAP_TIME = 1000
private val MIN_DISTANCE_MOVE = 4
private var mState = TouchState.STATE_STOP
private var distance: Int = 0
private enum class TouchState {
STATE_MOVE, STATE_STOP
}
constructor(context: Context) : super(context) {
initView()
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
initView()
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
initView()
}
private fun initView() {
childView = setChildView()
setChildAction(childView)
addView(childView)
setOnTouchListener(this)
layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
regionW = DensityUtil.dip2px(context, 3f)
distance = DensityUtil.dip2px(context,1f) * MIN_DISTANCE_MOVE
post {
childView?.width?.let {
childWidth = it
}
childView?.height?.let {
childHeight = it
}
layoutParams = setChildInitLayoutParams()
initLayoutParams()
}
}
protected abstract fun setChildView(): View?
protected abstract fun setChildInitLayoutParams(): FrameLayout.LayoutParams
protected abstract fun setChildAction(childView: View?)
private fun initLayoutParams() {
layoutParams.gravity = Gravity.LEFT or Gravity.TOP
childView?.layoutParams = layoutParams
}
private fun updateLayoutParams(dx: Int, dy: Int) {
layoutParams.gravity = Gravity.LEFT or Gravity.TOP
layoutParams.leftMargin = dx - childWidth / 2
layoutParams.topMargin = dy - childHeight / 2 - StateUtils.getStatusBarHeight(context)
childView?.layoutParams = layoutParams
}
private var mStartX:Int = 0
private var mStartY:Int = 0
override fun onTouch(view: View, event: MotionEvent): Boolean {
val x = event.rawX.toInt()
val y = event.rawY.toInt()
when(event.action){
MotionEvent.ACTION_DOWN -> {
mStartX = x
mStartY = y
if (isPointChoice(x, y)) {
isCanMove = true
}
}
MotionEvent.ACTION_MOVE -> {
if (Math.abs(x - mStartX) < distance
&& Math.abs(y - mStartY) < distance) {
if (mState == TouchState.STATE_STOP) {
return true
//break
}
} else if (mState != TouchState.STATE_MOVE) {
mState = TouchState.STATE_MOVE
}
if(isCanMove){
updateLayoutParams(x, y)
}
mState = TouchState.STATE_MOVE
}
MotionEvent.ACTION_UP -> {
isCanMove = false
if (mState != TouchState.STATE_MOVE
&& event.eventTime - event.downTime < MIN_TAP_TIME) {
setEventClick()
}
mState = TouchState.STATE_STOP
}
}
return isCanMove
}
protected abstract fun setEventClick()
private fun isPointChoice(x: Int, y: Int): Boolean {
val cLocation = IntArray(2)
childView?.getLocationOnScreen(cLocation)
val horizontalMatch =
x > (cLocation[0] + regionW) && x < (cLocation[0] + childWidth + regionW)
val verticalMatch =
y < (cLocation[1] + childHeight + DensityUtil.dip2px(context,10f)) && y > (cLocation[1] - regionW)
if (horizontalMatch && verticalMatch) {
return true
}
return false
}
}
2.1,繼承通用View
class DemoLineView(context: Context, attrs: AttributeSet?) : AbsParentDragView(context, attrs) {
override fun setChildView(): View? {
return LayoutInflater.from(context).inflate(R.layout.layout_draw_item, this, false)
}
override fun setChildInitLayoutParams(): LayoutParams {
layoutParams.topMargin = DensityUtil.getScreenHeight(
context
) - childHeight - DensityUtil.dip2px(context, 80f)
layoutParams.leftMargin = DensityUtil.getScreenWidth(
context
) - childWidth - DensityUtil.dip2px(context, 20f)
return layoutParams
}
override fun setChildAction(childView: View?) {
val tvSafeLine = childView?.findViewById<TextView>(R.id.tvSafeLine)
tvSafeLine?.text = "設置懸浮"
}
override fun setEventClick() {
Toast.makeText(context,"懸浮view",Toast.LENGTH_LONG).show()
}
}
2.3,設計view的控制器
open class DragViewManager private constructor(context: Activity) {
private var activity: Activity = context
companion object : SingletonHolder<DragViewManager, Activity>(::DragViewManager)
private lateinit var dragView: AbsParentDragView
private val contentView = activity.window.decorView.findViewById<View>(android.R.id.content) as FrameLayout
fun create(dragView: AbsParentDragView){
this.dragView = dragView
if(contentView.contains(dragView)){
contentView.removeView(dragView)
}
contentView.addView(dragView)
}
fun show(){
dragView.visibility = View.VISIBLE
}
fun dismiss(){
dragView.visibility = View.INVISIBLE
}
}
2.4,view的添加和使用
//創建出要顯示的View
DragViewManager.getInstance(this).create(new DemoLineView(this,null));
//隱藏要顯示的View
DragViewManager.getInstance(this).dismiss();
//顯示要顯示的View
DragViewManager.getInstance(this).show();
代碼鏈接地址:gitee.com/component_i…
原文鏈接:https://juejin.cn/post/7039300295775485965
相關推薦
- 2022-10-04 goland把go項目打包進docker鏡像的全過程記錄_Golang
- 2022-11-06 React?Hooks--useEffect代替常用生命周期函數方式_React
- 2022-03-20 C語言數學公式來實現土味表白_C 語言
- 2023-03-11 Pandas讀取csv的實現_python
- 2022-09-21 LyScript獲取上一條與下一條匯編指令的方法詳解_python
- 2022-06-25 詳解如何基于Pyecharts繪制常見的直角坐標系圖表_python
- 2022-09-09 Go語言中defer語句的用法_Golang
- 2024-04-23 Win11右下角時間怎么顯示星期幾?
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支