개발새발 - IT 기술블로그
article thumbnail

안녕하세요. 이번 포스팅에서는 액티비티를 전환할 때 뷰의 이동 애니메이션을 부여하는 기능에 대해 알아보겠습니다.

 

AnimationOptions의 하위 메서드인 makeSceneTransitionAnimationTransition이 발생할 때 전환 할 액티비티와 전환 되어질 액티비티에서 두 View를 연결하여 Animation을 지정해 주는 기능입니다. 

 

먼저 실행화면부터 보시겠습니다.

 

 

 

 

코드 진행순서는 이렇습니다.

 

1. startActivity와 endActivity를 생성하고 레이아웃을 구성

2. transitionName을 동일하게 입력

3. ActivityOptions.makeSceneTransitionAnimation 메서드를 구현

4. 전환할 액티비티에 intent를 통해 데이터 전달

5. 전환된 액티비티에서 전달받은 데이터로 뷰생성

 

 


 

작성코드👀

 

Theme.xml

<item name="android:windowActivityTransitions">true</item>

 

 

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="@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)
    }
}

 

코드소개

 

transitionAnimation을 등록하기 위해 뷰에 등록해주는 유니크한 Key형태의 String값 입니다.

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() 함수는 이미지의 ByteArrayBitmap으로 변환시켜 Bitmap의 Drawable을 리턴하는 로직입니다.

 

이것으로 액티비티 전환 시 뷰의 이동 애니메이션을 구현해보았는데요. 

예제와 같이 간단한 애니메이션이 필요한 경우엔 유용한 것 같습니다. 감사합니다.

 

 

 

 

예제코드

https://github.com/tekken5953/ViewTransitionAnimExam

 

GitHub - tekken5953/ViewTransitionAnimExam

Contribute to tekken5953/ViewTransitionAnimExam development by creating an account on GitHub.

github.com