어제(SNS 앱 팀 프로젝트 (1))에 이어 오늘도 메인 화면을 구현했다. 메인 화면에서 캐릭터를 클릭하여 디테일 화면으로 이동할 시 animation을 적용하는 부분을 추가했다.
kotlin animation을 검색하면 가장 많이 나오는 함수는overridePendingTransition
인데 해당 함수는deprecated
되었다고 표시되어 다른 것을 찾던 중makeSceneTransitionAnimation
을 알게 되었다.makeSceneTransitionAnimation
를 적용한 내용을 정리하고자 한다.
makeSceneTransitionAnimation
는 Transition이 발생할 때 전환 할 액티비티와 전환 되어질 액티비티에서 두 View를 연결하여 Animation을 지정해주는 기능이다. <item name="android:windowActivityTransitions">true</item>
class MainActivity : AppCompatActivity() {
private val rcCharacter: RecyclerView by lazy { findViewById(R.id.rcCharacter) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
}
private fun initView() {
val items = CharacterManager.getItems().sortedBy { it.korName }
val adapter = RecyclerCharacterAdapter(items)
rcCharacter.adapter = adapter
rcCharacter.layoutManager = GridLayoutManager(this, 3)
adapter.setItemClickListener(object : RecyclerCharacterAdapter.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
showToast("$position")
startDetailActivity(view, position)
}
})
}
private fun showToast(message: String) {
Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()
}
private fun startDetailActivity(view: View, position: Int) {
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra(characterId, position)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
val transitionPairs = getTransitionPairs(view)
/*
Activity 전환 옵션을 설정한다.
ImageView, TextView 두개의 View를 등록하였다.
*/
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(
this, *transitionPairs.toTypedArray()
)
// 인텐트에 Activity 옵션을 추가한다.
startActivity(intent, options.toBundle())
}
private fun getTransitionPairs(view: View): List<Pair<View, String>> {
val characterPair = Pair<View, String>(view.findViewById(R.id.ivCharacter), "transImage")
val characterNamePair =
Pair<View, String>(view.findViewById(R.id.tvCharacterName), "transName")
return listOf(characterPair, characterNamePair)
}
}
class RecyclerCharacterAdapter(private val items: List<Character>) :
RecyclerView.Adapter<RecyclerCharacterAdapter.ViewHolder>() {
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
}
private lateinit var listener: OnItemClickListener
fun setItemClickListener(itemClickListener: OnItemClickListener) {
listener = itemClickListener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.item_rv_character, parent, false)
return ViewHolder(itemView)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindItem(items[position])
}
override fun getItemCount(): Int = items.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItem(item: Character) {
val ivCharacter: ImageView = itemView.findViewById(R.id.ivCharacter)
val tvName: TextView = itemView.findViewById(R.id.tvCharacterName)
val tvComment: TextView = itemView.findViewById(R.id.tvCharacterComment)
with(ivCharacter) {
setImageResource(item.profileImage)
clipToOutline = true
}
tvName.text = item.korName
val commentsSize = "댓글 ${item.korName.getSize()}"
tvComment.text = commentsSize
itemView.setOnClickListener {
val position = adapterPosition
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(itemView, position)
}
}
}
}
private fun String.getSize() = MyCommentsTempDatas().getCommentSize(this)
}
transitionAnimation
을 등록하기 위해key형태의 String
값을 View에 등록해주며 전환 할 액티비티와 전환 되어질 액티비티의 layout에 동일한 이름으로 등록한다.android:transitionName="transImage" android:transitionName="transName"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="vertical">
<ImageView
android:id="@+id/ivCharacter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@drawable/iv_background_radius"
android:transitionName="transImage" />
<TextView
android:id="@+id/tvCharacterName"
style="@style/ThemeTvCharacter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:transitionName="transName" />
<TextView
android:id="@+id/tvCharacterComment"
style="@style/ThemeTvCharacter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="13sp" />
</LinearLayout>
android:transitionName="transImage" android:transitionName="transName"
...
<ImageView
android:id="@+id/profileImage"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@drawable/hawkeye"
android:transitionName="transImage" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/korName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24dp"
android:textStyle="bold"
android:transitionName="transName"
app:layout_constraintBottom_toBottomOf="@+id/img_hawk"
app:layout_constraintStart_toEndOf="@+id/img_hawk"
app:layout_constraintTop_toTopOf="@+id/img_hawk" />
...
공부가 됐습니다 감사합니다~