目录
- 1,背景
 - 2,思路
 - 2.1,封装通用的基础悬浮View
 - 2.1,继承通用View
 - 2.3,设计view的控制器
 - 2.4,view的添加和使用
 
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…
	声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
		
评论(0)