您好,登錄后才能下訂單哦!
本篇內容主要講解“android怎么實現可拖動的浮動view”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“android怎么實現可拖動的浮動view”吧!
頁面最小化后,需要出現一個浮動 view 告知用戶,防止遮擋視線,需要對 view 做可滑動處理
已知會遇到的問題
1.view 的依賴的布局類型未知【為了后續方便擴展】
外界傳遞 ViewGroup 自己本身繼承 LinearLayout【或者其他 ViewGroup 】
class FloatChannelView(var mContext: Context?, var viewGroup: ViewGroup) : LinearLayout(mContext){ private var mIcon: ImageView = ImageView(context) private var mName: TextView = TextView(context) private var mClose: ImageView = ImageView(context) private var iconWH = dip2Px(38) private var groupPadding = dip2Px(3) private var mViewGroupH = dip2Px(44) private var mViewGroupW = dip2Px(152) private var mBoundaryLeft: Float private var mBoundaryTop: Float private var mBoundaryRight: Float private var mBoundaryBottom: Float private var mScreenWidth = getScreenWidth() // 獲取屏幕寬高 private var mScreenHeight = getScreenHeight() private var mDownEventX: Float = 0f // 相對控件的x private var mDownEventY: Float = 0f private var mDownX: Float = 0f // 相對屏幕所在的 x private var mDownY: Float = 0f private var mListener: OnClickListener? = null private var mIsStartAnimation: Boolean = false private val mDefaultMargin = dip2Px(12) private var mMarginLeft = mDefaultMargin private var mMarginTop = mDefaultMargin private var mMarginRight = mDefaultMargin private var mMarginBottom = mDefaultMargin init { layoutParams = LayoutParams(mViewGroupW, mViewGroupH) setPadding(groupPadding, groupPadding, groupPadding, groupPadding) setBackgroundResource(R.drawable.backage) // 建議加一些透明 orientation = HORIZONTAL gravity = Gravity.CENTER_VERTICAL mBoundaryLeft = mMarginLeft.toFloat() mBoundaryTop = mMarginTop.toFloat() mBoundaryRight = mScreenWidth - mMarginRight.toFloat() mBoundaryBottom = (mScreenHeight - mMarginBottom - dip2Px(85)).toFloat() setView() } }
2.拖動事件影響點擊,事件分發處理。
override fun onTouchEvent(event: MotionEvent?): Boolean { if (mIsStartAnimation) { // 動畫正在進行無需處理 onTouch return true } if (event == null) { return super.onTouchEvent(event) } mIsOnTouch = true //懸浮區域左上角坐標 val x = x val y = y //懸浮區域寬高 val width = mViewGroupW val height = mViewGroupH when (event.actionMasked) { ACTION_DOWN -> { //點擊位置坐標 mDownEventX = event.x mDownEventY = event.y mDownX = x mDownY = y } ACTION_UP -> { mUpTime = System.currentTimeMillis() if (mIsMove && abs(mDownX - x) <= 8f && abs(mDownY - y) <= 8f) { mListener?.onClick(this) } mIsMove = false // 抬起后處理邊界溢出問題 resilienceAnimation(x, y, x + mViewGroupW, y + mViewGroupH) } ACTION_MOVE -> { val changeX = event.x.toInt() - mDownEventX val changeY = event.y.toInt() - mDownEventY mIsMove = true if (changeX == 0f && changeY == 0f) { return super.onTouchEvent(event) } val left = (x + changeX).toInt() val top = (y + changeY).toInt() val right = left + mViewGroupW val bottom = top + mViewGroupH layout(left, top, right, bottom) } } return true }
3.拖到邊界問題。
拖出邊界后做了回彈處理
/** * 超出邊界回彈 * @param left 當前 x 方向位置 * @param right 當前 y 方向位置 */ private fun resilienceAnimation(left: Float, top: Float, right: Float, bottom: Float) { var startX = 0f var resilienceX = 0f if (mBoundaryLeft <= left && right <= mBoundaryRight) { // x 方向在范圍內 // 不處理 } else if (mBoundaryLeft > left) { // left 溢出 startX = 0f resilienceX = mBoundaryLeft - left } else { // right 方向底部溢出 startX = 0f resilienceX = mBoundaryRight - right } var startY = 0f var resilienceY = 0f if (mBoundaryTop <= top && bottom <= mBoundaryBottom) { // y 方向在范圍內 // 不處理 } else if (mBoundaryTop > top) { // top 溢出 startY = 0f resilienceY = mBoundaryTop - top } else { // bottom 溢出 startY = 0f resilienceY = mBoundaryBottom - bottom } if (resilienceX == 0f && resilienceY == 0f) { // 在范圍內無需回彈 return } // 超出邊界回彈 val phaseFirstDuration: Long = 400 var oAnimPhaseFirstTUpX: ObjectAnimator? = null if (resilienceX != 0f) { oAnimPhaseFirstTUpX = ObjectAnimator.ofFloat(this, "translationX", startX, resilienceX) .setDuration(phaseFirstDuration) } var oAnimPhaseFirstTUpY: ObjectAnimator? = null if (resilienceY != 0f) { oAnimPhaseFirstTUpY = ObjectAnimator.ofFloat(this, "translationY", startY, resilienceY) .setDuration(phaseFirstDuration) } val animatorSet = AnimatorSet() if (oAnimPhaseFirstTUpX != null && oAnimPhaseFirstTUpY != null) { animatorSet.play(oAnimPhaseFirstTUpX).with(oAnimPhaseFirstTUpY) } else if (oAnimPhaseFirstTUpX != null) { animatorSet.play(oAnimPhaseFirstTUpX) } else { animatorSet.play(oAnimPhaseFirstTUpY) } animatorSet.childAnimations[animatorSet.childAnimations.size - 1].addListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator?) { mIsStartAnimation = true } override fun onAnimationEnd(animation: Animator?) { var l = left var t = top var r = right var b = bottom when { mBoundaryLeft > left -> { // x左邊溢出 l = mBoundaryLeft r = mBoundaryLeft + mViewGroupW } mBoundaryRight < right -> { // x右邊溢出 l = mBoundaryRight - mViewGroupW r = mBoundaryRight } else -> { // x方向未溢出 } } when { mBoundaryTop > top -> { // y 頂部溢出 t = mBoundaryTop b = mBoundaryTop + mViewGroupH } mBoundaryBottom < bottom -> { // y 底部溢出 t = mBoundaryBottom - mViewGroupH b = mBoundaryBottom } else -> { // y方向未溢出 } } // 只進行偏移,實際位置未變化,需要重置偏移量,并重繪 this@FloatChannelView.translationX = 0f this@FloatChannelView.translationY = 0f layout(l.toInt(), t.toInt(), r.toInt(), b.toInt()) mMarginLeft = l.toInt() mMarginTop = t.toInt() mIsStartAnimation = false } override fun onAnimationCancel(animation: Animator?) {} override fun onAnimationRepeat(animation: Animator?) {} }) animatorSet.start()
到此,相信大家對“android怎么實現可拖動的浮動view”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。