美文网首页
Android 自定义侧滑Demo

Android 自定义侧滑Demo

作者: 拉弓的松鼠在旋转 | 来源:发表于2023-01-29 12:15 被阅读0次

模仿侧滑效果

XML

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.zasko.library.ui.sliding.SlidingFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <com.zasko.library.ui.sliding
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:background="@color/black" />

    </com.zasko.library.ui.sliding.SlidingFrameLayout>

</FrameLayout>

SlidingFrameLayout


import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.ViewConfiguration
import android.widget.FrameLayout
import androidx.core.view.forEach
import com.zasko.library.utils.TAG
import kotlin.math.abs

class SlidingFrameLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {

    private var mTouchSlop: Int = 0


    init {
        mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
        this.isClickable = true
    }

    private var allowRightTouch = true


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        Log.d(TAG, "onMeasure: widthMeasureSpec:${widthMeasureSpec} heightMeasureSpec:${heightMeasureSpec} width:${width}")
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        when (widthMode) {
            MeasureSpec.AT_MOST -> {
                Log.d(TAG, "onMeasure: widthMode AT_MOST widthSize:${widthSize}")
            }
            MeasureSpec.EXACTLY -> {    //match_parent
                Log.d(TAG, "onMeasure: widthMode EXACTLY widthSize:${widthSize}")
            }
            MeasureSpec.UNSPECIFIED -> {
                Log.d(TAG, "onMeasure: widthMode UNSPECIFIED widthSize:${widthSize}")
            }
        }
        forEach { child ->
//            if (child is SlidingRightView) {
//                //MeasureSpec.makeMeasureSpec()
//                child.measure(widthMeasureSpec, heightMeasureSpec)
//            }

        }
        if (rightViewStart == -1) {
            rightViewStart = measuredWidth / 2
        }
    }

    private var mRightScrollLen = 0F
    private var rightViewStart = -1


    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        Log.d(TAG, "onLayout: left:$left top:$top right:$right bottom:$bottom")
        forEach { child ->
            if (child is SlidingRightView) {
                val l = rightViewStart + mRightScrollLen.toInt()
                child.layout(l, top, l + child.measuredWidth, bottom)
            }
        }
    }


    private var startX: Float = 0F
    private var isStartMoving = false
    private var mLastX = 0F

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {

        if (allowRightTouch && ev != null) {
            when (ev.action) {
                MotionEvent.ACTION_DOWN -> {
                    isStartMoving = false
                    startX = ev.x
                }
                MotionEvent.ACTION_MOVE -> {

                    val diff = ev.x - startX
                    Log.e(TAG, "onInterceptTouchEvent: MotionEvent.ACTION_MOVE   diff:${diff}")
                    if (abs(diff) >= mTouchSlop && diff < 0) {
                        return true
                    }
                }
                MotionEvent.ACTION_UP -> {
                    startX = 0F
                }
            }
        }
        val tmp = super.onInterceptTouchEvent(ev)
        Log.d(TAG, "onInterceptTouchEvent: tmp:${tmp} ev:${ev}")
        return tmp
    }


    private var mTmpMoveX = 0F

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        event?.let { e ->
            when (e.action) {
                MotionEvent.ACTION_DOWN -> {
                    Log.d(TAG, "onTouchEvent: ACTION_DOWN")
                    mLastX = e.x
                }
                MotionEvent.ACTION_MOVE -> {
                    Log.d(TAG, "onTouchEvent: ACTION_MOVE")
                    moveRightView(e)
                }
                MotionEvent.ACTION_UP -> {
                    Log.d(TAG, "onTouchEvent: ACTION_UP")
                    stopRightMove()
                }
                else -> {

                }
            }
        }
        return super.onTouchEvent(event)
    }

    private fun moveRightView(event: MotionEvent) {
        val moveX = event.x
        var diffX = moveX - mLastX
        if (diffX != mTmpMoveX) {
            if (mRightScrollLen + diffX <= (-measuredWidth / 2)) {
                diffX = -measuredWidth / 2 - (mRightScrollLen)
            }
            if (mRightScrollLen + diffX >= 0) {
                diffX = 0 - mRightScrollLen
            }
            mTmpMoveX = diffX
            mLastX = moveX

            mRightScrollLen += diffX
            Log.e(TAG, "onTouchEvent: mRightScrollLen:${mRightScrollLen} diffX:${diffX}")
            requestLayout()
        }
    }

    private fun stopRightMove() {
        val diffX: Float = if (abs(mRightScrollLen) >= measuredWidth / 4) {
            -measuredWidth / 2F
        } else {
            0F
        }
        Log.d(TAG, "stopRightMove: mRightScrollLen:${mRightScrollLen} diffX:${diffX}")
        val ani = ValueAnimator.ofFloat(mRightScrollLen, diffX)
        ani.addUpdateListener { animation ->
            mRightScrollLen = animation.animatedValue as Float
            requestLayout()
        }
        val time = 1 - abs(mRightScrollLen / (measuredWidth / 2))
        ani.duration = (300 * abs(time)).toLong()
        ani.start()

    }
}

SlidingRightView


import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout

class SlidingRightView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {
}

相关文章

网友评论

      本文标题:Android 自定义侧滑Demo

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