라이브 방

- 하트 애니메이션 추가
This commit is contained in:
klaus 2024-10-16 15:08:36 +09:00
parent c7409e4dec
commit 6c9ace146d
2 changed files with 667 additions and 567 deletions

View File

@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.live.room
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.app.Service
@ -21,8 +22,11 @@ import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
@ -90,6 +94,7 @@ import kr.co.vividnext.sodalive.report.UserReportDialog
import kr.co.vividnext.sodalive.settings.notification.MemberRole
import org.koin.android.ext.android.inject
import java.util.regex.Pattern
import kotlin.random.Random
class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomBinding::inflate) {
@ -257,17 +262,6 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
viewModel.getMemberCan()
viewModel.getRoomInfo(roomId)
viewModel.getBlockedMemberIdList()
binding.etChat.setOnFocusChangeListener { view, hasFocus ->
if (isNoChatting && hasFocus) {
Toast.makeText(
applicationContext,
"${remainingNoChattingTime}초 동안 채팅하실 수 없습니다",
Toast.LENGTH_SHORT
).show()
view.clearFocus()
}
}
}
override fun onStart() {
@ -449,6 +443,16 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
}
)
binding.etChat.setOnFocusChangeListener { view, hasFocus ->
if (isNoChatting && hasFocus) {
Toast.makeText(
applicationContext,
"${remainingNoChattingTime}초 동안 채팅하실 수 없습니다",
Toast.LENGTH_SHORT
).show()
view.clearFocus()
}
}
binding.tvQuit.setOnClickListener { onClickQuit() }
binding.flMicrophoneMute.setOnClickListener {
microphoneMute()
@ -522,6 +526,102 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
super.onDestroy()
}
private fun secondToMillis(second: Float): Long {
return (second * 1000).toLong()
}
private fun addHeartAnimation(button: View) {
// 버튼의 위치
val buttonPosition = IntArray(2)
button.getLocationInWindow(buttonPosition)
// 하트 이미지뷰 생성
val heart = ImageView(this).apply {
setImageResource(R.drawable.ic_heart_pink) // 투명한 하트 이미지
layoutParams = FrameLayout.LayoutParams(
33.3f.dpToPx().toInt(),
33.3f.dpToPx().toInt()
) // 하트 크기 설정
}
// 하트의 초기 위치를 버튼의 위치로 설정
heart.x = (buttonPosition[0] + button.width / 2f - 50) // X축 (가운데 정렬)
heart.y = (buttonPosition[1] - 100).toFloat() // Y축 (버튼 바로 위에 생성)
binding.flRoot.addView(heart)
// 하트가 위로 올라가는 애니메이션
val animateDuration = secondToMillis(2.5f)
val moveUpAnimator = ObjectAnimator.ofFloat(
heart,
"translationY",
heart.y,
heart.y - (screenHeight * 1000 / 2337)
).apply {
duration = animateDuration
interpolator = AccelerateDecelerateInterpolator()
}
val isNegativeFirst = Random.nextBoolean()
// 좌우 이동 범위를 랜덤으로 설정
val x = 13.3f
val startX = if (isNegativeFirst) (0 - x).dpToPx() else x.dpToPx()
val endX = if (isNegativeFirst) x.dpToPx() else (0 - x).dpToPx()
val moveAnimator = ObjectAnimator.ofFloat(
heart,
"translationX",
heart.x + startX,
heart.x + endX
).apply {
duration = secondToMillis(1.5f)
repeatCount = ObjectAnimator.INFINITE
repeatMode = ObjectAnimator.REVERSE
interpolator = AccelerateDecelerateInterpolator()
}
val scaleXAnimator = ObjectAnimator.ofFloat(
heart,
"scaleX",
0.5f,
1.0f
).apply {
duration = animateDuration
}
val scaleYAnimator = ObjectAnimator.ofFloat(
heart,
"scaleY",
0.5f,
1.0f
).apply {
duration = animateDuration
}
// 하트 투명도 애니메이션
val fadeOutAnimator = ObjectAnimator.ofFloat(
heart,
"alpha",
1f,
0f
).apply {
duration = animateDuration
}
// 애니메이션 실행
moveUpAnimator.start()
moveAnimator.start()
fadeOutAnimator.start()
scaleXAnimator.start()
scaleYAnimator.start()
// 애니메이션이 끝나면 하트 제거
handler.postDelayed({
binding.flRoot.removeView(heart)
}, animateDuration)
}
private fun showOptionMenu(
context: Context,
userId: Long,
@ -997,7 +1097,7 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
private fun initLikeHeartButton(isHost: Boolean) {
if (!isHost) {
binding.flLikeHeart.visibility = View.VISIBLE
binding.flLikeHeart.setOnClickListener { }
binding.flLikeHeart.setOnClickListener { addHeartAnimation(it) }
} else {
binding.flLikeHeart.visibility = View.GONE
}

View File

@ -1,11 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
tools:background="@color/black">
android:background="@color/black"
android:keepScreenOn="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_cover"
@ -37,7 +42,7 @@
android:paddingStart="20dp"
android:paddingEnd="0dp"
app:layout_constraintBottom_toTopOf="@+id/rl_input_chat"
app:layout_constraintEnd_toStartOf="@+id/rl_option_buttons"
app:layout_constraintEnd_toStartOf="@+id/ll_option_buttons"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fl_margin"
app:layout_goneMarginEnd="0dp" />
@ -452,10 +457,10 @@
android:layout_marginStart="6.7dp"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center_vertical"
tools:text="999,999"
android:textColor="@color/color_bbbbbb"
android:textSize="11sp"
tools:ignore="SmallSp" />
tools:ignore="SmallSp"
tools:text="999,999" />
</LinearLayout>
<LinearLayout
@ -535,21 +540,16 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:id="@+id/rl_option_buttons"
<LinearLayout
android:id="@+id/ll_option_buttons"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:orientation="vertical"
android:paddingStart="6.7dp"
android:paddingEnd="13.3dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fl_margin">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
app:layout_constraintEnd_toEndOf="parent">
<FrameLayout
android:id="@+id/fl_speaker_mute"
@ -672,7 +672,6 @@
android:src="@drawable/ic_mic_on" />
</FrameLayout>
</LinearLayout>
</RelativeLayout>
<TextView
android:id="@+id/tv_new_chat"
@ -698,7 +697,7 @@
android:layout_marginBottom="13.3dp"
android:paddingHorizontal="13.3dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/rl_option_buttons"
app:layout_constraintEnd_toStartOf="@+id/ll_option_buttons"
app:layout_constraintStart_toStartOf="parent">
<EditText
@ -745,3 +744,4 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>