美文网首页
自定义behavior

自定义behavior

作者: 李晓通 | 来源:发表于2018-06-28 11:44 被阅读103次

    前言

    用过CoordinatorLayout的小伙伴应该都会发现,在这个布局里面,我们有一个behavior属性,可以实现一些比较不错的动画效果,比如折叠式toolbar,snackbar顶起floatingActionBar等等,那么今天我们就来自定义一个behavior实现我们想要的效果。

    最终效果演示

    左边的View是可以随着手指拖动的,右边的button的x轴反向移动,y轴相同


    跟随手指移动的view

    这个实现起来比较简单,重写触摸事件即可,直接贴代码了

    class MoveView : TextView {
        constructor(context: Context?) : this(context, null)
        constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
        constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    
        private var downX : Float = 0.0f
        private var downY : Float = 0.0f
    
        override fun onTouchEvent(event: MotionEvent?): Boolean {
            when (event?.action) {
                MotionEvent.ACTION_DOWN -> {
                    downX = event.x
                    downY = event.y
                }
                MotionEvent.ACTION_MOVE -> {
                    //x是滑动的距离
                    translationX = x + (event.x - downX)
                    translationY = y + (event.y - downY)
                }
                MotionEvent.ACTION_UP -> {
                    downX = event.x
                    downY = event.y
                }
            }
            return true
        }
    }
    

    传统实现跟随滑动方式

    1.在MoveView中添加button,加入相关的逻辑操作
    2.在Activity中通过GestureDetector改变button的位置
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val gestureDetector = GestureDetector(this,object : GestureDetector.OnGestureListener {
                override fun onShowPress(e: MotionEvent?) {}
    
                override fun onSingleTapUp(e: MotionEvent?): Boolean { return false }
    
                override fun onDown(e: MotionEvent?): Boolean { return false }
    
                override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean { return false }
    
                override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {
                    //在屏幕上拖动事件
                    btn.x = windowManager.defaultDisplay.width - mv.x
                    btn.y = mv.y
                    return false
                }
    
                override fun onLongPress(e: MotionEvent?) {}
            })
            mv.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) }
        }
    }
    

    上面2种方式确实可以实现上述效果,但是,可扩展性基本为0,如果我现在想把button改成imageview,如果是第一种方式,我就不得不去修改MoveView中的代码,如果是第二种方式,我就必须去修改Activity中的代码,这显然不行,如果多个地方都用到这种效果,代码量就很大了,而且不灵活。

    自定义behavior实现

    我们只需要继承CoordinatorLayout.Behavior,然后重写layoutDependsOn和onDependentViewChanged这两个方法即可,剩下的操作全部在这里执行,然后给你想要实现拖动的view添加一个behavior即可。

    class CustomBehavior : CoordinatorLayout.Behavior<View> {
    
        constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    
        /**
         * 判断child是否依赖dependency,也可以理解为是否要响应behavior,如果用户操作的view是你需要的view,那么就响应
         */
        override fun layoutDependsOn(parent: CoordinatorLayout?, child: View?, dependency: View?): Boolean {
            Log.d("lxt", (dependency is MoveView).toString())
            //返回true,响应事件
            return dependency is MoveView
        }
    
        /**
         * 当dependency发生改变时(位置、宽高等),执行这个函数
         * 返回true表示child的位置或者是宽高要发生改变,否则就返回false
         */
        override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean {
            //根据dependency的位置,设置child的位置
            Log.d("lxt", dependency.y.toString())
            val left = dependency.x
            val screenWidth = parent.width
    
            child.x = screenWidth - left - child.width
            child.y = dependency.y
    
            return true
        }
    }
    

    用behavior的好处显而易见

    1.不用修改MoveView中的任何代码
    2.不用在Activity中添加任何代码
    3.可以给任何你想要实现效果的view添加behavior,耦合度为0

    相关文章

      网友评论

          本文标题:自定义behavior

          本文链接:https://www.haomeiwen.com/subject/qxhgyftx.html