This commit is contained in:
lunaticbum 2026-03-23 14:53:26 +09:00
parent a8c7641e69
commit 9aee32e42d
3 changed files with 60 additions and 27 deletions

View File

@ -1084,9 +1084,14 @@ class FloatingActionButton : ImageButton {
if (animate) { if (animate) {
playHideAnimation() playHideAnimation()
} }
if (this.isSelected) {
super.setVisibility(GONE)
} else {
super.setVisibility(INVISIBLE) super.setVisibility(INVISIBLE)
} }
} }
}
fun toggle(animate: Boolean) { fun toggle(animate: Boolean) {
if (this.isHidden) { if (this.isHidden) {

View File

@ -11,10 +11,12 @@ import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Handler import android.os.Handler
import android.os.Looper
import android.text.TextUtils import android.text.TextUtils
import android.util.AttributeSet import android.util.AttributeSet
import android.util.TypedValue import android.util.TypedValue
import android.view.ContextThemeWrapper import android.view.ContextThemeWrapper
import android.view.HapticFeedbackConstants
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -570,12 +572,24 @@ class FloatingActionMenu @JvmOverloads constructor(
} }
}) })
mMenuButton!!.setOnTouchListener(object : OnTouchListener { mMenuButton!!.setOnTouchListener(object : OnTouchListener {
var dX: Float = 0f var dX: Float = 0f
var dY: Float = 0f var dY: Float = 0f
var startX: Float = 0f var startX: Float = 0f
var startY: Float = 0f var startY: Float = 0f
// 💡 롱클릭 감지를 위한 변수 추가
private val longClickHandler = Handler(Looper.getMainLooper())
private var isLongClickPerformed = false
private val longClickRunnable = Runnable {
isLongClickPerformed = true
// 여기에 롱클릭 시 실행할 동작을 넣으세요.
// 예: Vibrator 실행 또는 특정 함수 호출
performLongClickAction()
}
override fun onTouch(v: View, event: MotionEvent): Boolean { override fun onTouch(v: View, event: MotionEvent): Boolean {
val oldX = v.x val oldX = v.x
val oldY = v.y val oldY = v.y
@ -586,48 +600,52 @@ class FloatingActionMenu @JvmOverloads constructor(
dY = v.y - event.rawY dY = v.y - event.rawY
startX = event.rawX startX = event.rawX
startY = event.rawY startY = event.rawY
// 💡 1. 500ms 뒤에 롱클릭으로 간주하도록 예약
isLongClickPerformed = false
longClickHandler.postDelayed(longClickRunnable, 500)
} }
MotionEvent.ACTION_MOVE -> { MotionEvent.ACTION_MOVE -> {
if (!isDragMenuDisabled) { // 💡 2. 사용자가 일정 거리 이상 움직이면 롱클릭 예약을 취소 (드래그로 판단)
// 1. 드래그하려는 목표 좌표 계산 if (abs(startX - event.rawX) > 10 || abs(startY - event.rawY) > 10) {
var newX = event.rawX + dX longClickHandler.removeCallbacks(longClickRunnable)
var newY = event.rawY + dY }
// 2. 화면 전체 너비와 높이 가져오기 (현재 FloatingActionMenu가 match_parent이므로 자체 크기 사용) if (!isDragMenuDisabled && !isLongClickPerformed) {
val menuWidth = this@FloatingActionMenu.width // 드래그 로직 (기존과 동일)
val menuHeight = this@FloatingActionMenu.height var newX = (event.rawX + dX).coerceIn(paddingLeft.toFloat(), (this@FloatingActionMenu.width - v.width - paddingRight).toFloat())
var newY = (event.rawY + dY).coerceIn(paddingTop.toFloat(), (this@FloatingActionMenu.height - v.height - paddingBottom).toFloat())
// 3. 화면을 벗어나지 않도록 좌표 가두기 (패딩 포함)
val minX = paddingLeft.toFloat()
val maxX = (menuWidth - v.width - paddingRight).toFloat()
val minY = paddingTop.toFloat()
val maxY = (menuHeight - v.height - paddingBottom).toFloat()
// coerceIn 함수를 사용하여 최소~최대 값 사이로 강제 보정
newX = newX.coerceIn(minX, maxX)
newY = newY.coerceIn(minY, maxY)
// 4. 보정된 좌표로 뷰 이동
v.x = newX v.x = newX
v.y = newY v.y = newY
// 5. 하위 메뉴들도 바뀐 메인 버튼 위치에 맞춰 다시 그리기
moveElements(v, newX, newY, oldX, oldY) moveElements(v, newX, newY, oldX, oldY)
} }
} }
MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> {
// 드래그가 아니라 단순 클릭(오차 10픽셀 이내)이었다면 메뉴 토글 // 💡 3. 손을 떼면 예약된 롱클릭 취소
longClickHandler.removeCallbacks(longClickRunnable)
// 롱클릭이 이미 발생했다면 클릭 이벤트를 무시
if (isLongClickPerformed) return true
if (abs(startX - event.rawX) < 10 && abs(startY - event.rawY) < 10) { if (abs(startX - event.rawX) < 10 && abs(startY - event.rawY) < 10) {
toggle(mIsAnimated) toggle(mIsAnimated)
} }
} }
else -> return false MotionEvent.ACTION_CANCEL -> {
// 💡 4. 취소 이벤트 발생 시에도 리스너 제거
longClickHandler.removeCallbacks(longClickRunnable)
}
} }
return true return true
} }
private fun performLongClickAction() {
mMenuButton!!.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
toggle(animate = mIsAnimated, true)
}
}) })
} }
} }
@ -795,15 +813,15 @@ class FloatingActionMenu @JvmOverloads constructor(
return super.onTouchEvent(event) return super.onTouchEvent(event)
} }
fun toggle(animate: Boolean) { fun toggle(animate: Boolean, allShow: Boolean = false) {
if (this.isOpened) { if (this.isOpened) {
close(animate) close(animate)
} else { } else {
open(animate) open(animate, allShow)
} }
} }
fun open(animate: Boolean) { fun open(animate: Boolean, allShow : Boolean = false) {
if (!this.isOpened) { if (!this.isOpened) {
if (this.isBackgroundEnabled) { if (this.isBackgroundEnabled) {
mShowBackgroundAnimator!!.start() mShowBackgroundAnimator!!.start()
@ -823,6 +841,10 @@ class FloatingActionMenu @JvmOverloads constructor(
mIsMenuOpening = true mIsMenuOpening = true
for (i in getChildCount() - 1 downTo 0) { for (i in getChildCount() - 1 downTo 0) {
val child = getChildAt(i) val child = getChildAt(i)
if (allShow && !child.equals(mMenuButton) && child.getVisibility() == GONE) {
child.isSelected = true
child.visibility = View.INVISIBLE
}
if (child is FloatingActionButton && child.getVisibility() != GONE) { if (child is FloatingActionButton && child.getVisibility() != GONE) {
counter++ counter++
@ -877,6 +899,7 @@ class FloatingActionMenu @JvmOverloads constructor(
mIsMenuOpening = false mIsMenuOpening = false
for (i in 0..<getChildCount()) { for (i in 0..<getChildCount()) {
val child = getChildAt(i) val child = getChildAt(i)
if (child is FloatingActionButton && child.getVisibility() != GONE) { if (child is FloatingActionButton && child.getVisibility() != GONE) {
counter++ counter++

View File

@ -65,26 +65,31 @@
android:id="@+id/perplexity"/> android:id="@+id/perplexity"/>
<bums.lunatic.launcher.view.FloatingActionButton <bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="😂" app:fab_label="😂"
android:visibility="gone"
style="@style/CommonFabStyle" style="@style/CommonFabStyle"
android:id="@+id/zzalbang"/> android:id="@+id/zzalbang"/>
<bums.lunatic.launcher.view.FloatingActionButton <bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="🐦" app:fab_label="🐦"
android:visibility="gone"
style="@style/CommonFabStyle" style="@style/CommonFabStyle"
android:id="@+id/btn_x"/> android:id="@+id/btn_x"/>
<bums.lunatic.launcher.view.FloatingActionButton <bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="🔞" app:fab_label="🔞"
android:visibility="gone"
style="@style/CommonFabStyle" style="@style/CommonFabStyle"
android:id="@+id/btn_i"/> android:id="@+id/btn_i"/>
<bums.lunatic.launcher.view.FloatingActionButton <bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="🧲" app:fab_label="🧲"
android:visibility="gone"
style="@style/CommonFabStyle" style="@style/CommonFabStyle"
android:id="@+id/btn_torrent" android:id="@+id/btn_torrent"
/> />
<bums.lunatic.launcher.view.FloatingActionButton <bums.lunatic.launcher.view.FloatingActionButton
app:fab_label="📦" app:fab_label="📦"
android:visibility="gone"
style="@style/CommonFabStyle" style="@style/CommonFabStyle"
android:id="@+id/btn_completed_files" android:id="@+id/btn_completed_files"
/> />