안녕하세요. 이번 포스팅에서는 액티비티 전환 시 뷰의 모션 애니메이션을 보여주는 기능에 대해 알아보도록 하겠습니다.
AnimationOptions의 하위 메서드인 MakeSceneTransitionAnimation은 전환이 발생할 때 전환할 활동으로 토글됩니다. 두 개의 동일한 뷰를 하나의 액티비티로 연결하여 애니메이션을 호출하는 기능입니다.
주로 어댑터의 항목을 클릭하여 해당 항목의 상세 정보를 볼 때 사용합니다.
먼저 실행 화면을 보겠습니다.

코드의 순서는 다음과 같습니다.
1. StartActivity 및 EndActivity 생성 및 레이아웃 구성
2. 전환 이름즉시 입력
삼. ActivityOptions.makeSceneTransitionAnimation 방법을 구현
4. 인텐트를 통해 전환할 활동으로 데이터 전달
5. 변환된 활동에서 전달된 데이터로 보기 만들기
코드 작성
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageViewMain"
android:layout_width="150dp"
android:layout_height="150dp"
android:transitionName="imageTran"
android:src="http://tekken5953.m/@android:mipmap/sym_def_app_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/titleTextMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="타이틀"
android:textSize="18sp"
android:transitionName="titleTran"
app:layout_constraintTop_toBottomOf="@id/imageViewMain" />
<TextView
android:id="@+id/contentTextMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="세부내용입니다. DevJYL Blog 화이팅"
android:transitionName="contentTran"
app:layout_constraintTop_toBottomOf="@+id/titleTextMain" />
<Button
android:id="@+id/btnMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="이동"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contentTextMain" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DetailActivity">
<ImageView
android:id="@+id/imageViewDetail"
android:layout_width="match_parent"
android:layout_height="250dp"
android:transitionName="imageTran"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/titleTextDetail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
android:transitionName="titleTran"
app:layout_constraintTop_toBottomOf="@+id/imageViewDetail" />
<TextView
android:id="@+id/contentTextDetail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:transitionName="contentTran"
android:gravity="center"
app:layout_constraintTop_toBottomOf="@+id/titleTextDetail" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
import android.app.ActivityOptions
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.Pair
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.io.ByteArrayOutputStream
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val title: TextView = findViewById(R.id.titleTextMain)
val img: ImageView = findViewById(R.id.imageViewMain)
val content: TextView = findViewById(R.id.contentTextMain)
val btn: Button = findViewById(R.id.btnMain)
btn.setOnClickListener {
val options = ActivityOptions.makeSceneTransitionAnimation(
this,
Pair.create(title, "titleTran"),
Pair.create(img, "imageTran"),
Pair.create(content, "contentTran")
)
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("title", title.text.toString())
intent.putExtra("image", sendImage(android.R.mipmap.sym_def_app_icon))
intent.putExtra("content", content.text.toString())
startActivity(intent, options.toBundle())
}
}
private fun sendImage(image: Int) : ByteArray {
val sendBitmap = BitmapFactory.decodeResource(resources, image)
val stream = ByteArrayOutputStream()
sendBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
return stream.toByteArray()
}
}
DetailActivity.kt
import android.graphics.BitmapFactory
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.graphics.drawable.toDrawable
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detail)
val title: TextView = findViewById(R.id.titleTextDetail)
val content: TextView = findViewById(R.id.contentTextDetail)
val img: ImageView = findViewById(R.id.imageViewDetail)
title.text = intent.extras?.getString("title")
content.text = intent.extras?.getString("content")
img.setImageDrawable(getImage())
}
private fun getImage() : Drawable {
val arr = intent.getByteArrayExtra("image")
return BitmapFactory.decodeByteArray(arr, 0, arr!!.size).toDrawable(resources)
}
}
그럼 코드에 대한 간략한 소개를 드리겠습니다.
트랜지션 애니메이션을 등록하기 위해 뷰에 등록되는 고유 키 형태의 문자열 값입니다.
android:transitionName="imageTran"
액티비티 전환 옵션을 설정하는 부분입니다.
val options = ActivityOptions.makeSceneTransitionAnimation(
this,
Pair.create(title, "titleTran"),
Pair.create(img, "imageTran"),
Pair.create(content, "contentTran")
)
다수의 뷰를 등록해야 하는 경우 위와 같이 등록하고, 보유하고 있는 경우 다음과 같이 등록합니다.
val options = ActivityOptions.makeSceneTransitionAnimation(
this,
img,
"ImageTran"
)
전환할 액티비티에 현재 데이터를 전달하는 부분입니다.
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("title", title.text.toString())
intent.putExtra("image", sendImage(android.R.mipmap.sym_def_app_icon))
intent.putExtra("content", content.text.toString())
startActivity(intent, options.toBundle())
sendImage(image: Int) 함수는 이미지에서 비트맵을 추출하여 ByteArray 유형으로 변환하는 로직입니다.
마지막으로 전환된 활동에서 데이터를 받는 부분입니다.
title.text = intent.extras?.getString("title")
content.text = intent.extras?.getString("content")
img.setImageDrawable(getImage())
getImage() 함수는 이미지의 ByteArray를 비트맵으로 변환하고 비트맵의 Drawable을 반환하는 로직입니다.
이것으로 나는 활동을 전환할 때 보기의 움직이는 애니메이션을 구현했습니다.
예제와 같이 간단한 애니메이션이 필요할 때 유용할 것 같습니다. 감사해요

샘플 코드
https://github.com/tekken5953/ViewTransitionAnimExam
GitHub – tekken5953/ViewTransitionAnimExam
GitHub에서 계정을 만들어 tekken5953/ViewTransitionAnimExam 개발에 기여하세요.
github.com
