최근 안드로이드 개발을 공부하면서 관심을 가지고 있는 분야가 디자인이다. 앱이 최적화가 잘 돼있고, 효율이 좋은 것도 중요하지만 정작 앱이 멋이 없다면 사용자의 만족도를 끌어올리기 힘들다고 생각했다.
그래서 요즘은 머티리얼 디자인과 애니메이션에 대해서 공부 중인데, 안드로이드 개발 문서에서 흥미로운 애니메이션을
발견했다.
기존 화면 전환은 새로운 화면이 아래에서 위로 올라오는 기본 전환이다. 이 전환에서부터 애니메이션을 통해
보다 감성적인 앱을 만들 수 있다면 얼마나 좋을까? 그 부분의 갈증을 해소하기 위한 방법이 안드로이드 개발 문서에
잘 적혀 있었다.
다음과 같은 예시를 잘만 활용한다면 RecyclerView에 있는 아이템을 클릭 시 상세 뷰로 넘어갈 때
애니메이션을 적용해줘서 이전보다 더 활동감 있는 앱을 만들 수 있을 것 같다.
아무것도 모르고 보면 굉장히 어려울 것 같지만 사실 상 무척이나 쉽게 다음과 같은 애니메이션을 구현할 수 있다.
이번 포스팅에서는 어떤 방식으로 화면 전환할 때 다음과 같은 애니메이션을 적용할 수 있는지 알아보자.
해당 기술은 안드로이드 5.0 ( API 21 ) 이상부터 사용가능하기 때문에 그 이하의 안드로이드 시스템과 호환하고 싶다면
다음과 같이 코드를 작성해주고 해당 영역에서 작업을 해주면 된다.
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Apply activity transition
} else {
// Swap without transition
}
먼저 화면을 두개 준비해 준다. 맨 처음 보이는 화면 MainActivity와 화면 전환 시 보일 SecondAcitivity를 준비한다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:background="#85EBE1"
tools:context=".MainActivity">
<androidx.cardview.widget.CardView
android:id="@+id/main_card"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:elevation="8dp"
android:background="#ffffff"
app:cardCornerRadius="5dp"
android:layout_centerInParent="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/name_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Kang min gu"
android:textColor="#000000"
android:textSize="30sp" />
<TextView
android:id="@+id/content_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_below="@id/name_txt"
android:layout_alignLeft="@id/name_txt"
android:text="title"
android:textSize="20sp" />
<ImageView
android:id="@+id/profile_img"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignBaseline="@id/name_txt"
android:layout_toStartOf="@id/name_txt"
android:layout_marginRight="10dp"
android:scaleType="fitXY"
android:src="@drawable/ic_baseline_accessibility_24" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
기존 포스팅이나 내가 개발할 때는 ConstraintLayout을 사용했는데 이번에는 RelativeLayout을 사용했다.
개발 문서에서는 딱히 특정 Layout사용을 요구하지는 않는데 내가 보고 공부한 예시에서 RelativeLayout을 사용했기에
나도 그에 맞춰서 xml을 꾸몄다. 나중에 Layout을 바꿔서 해볼 때도 적용되는지 확인해 봐야겠다.
화면 중안에 카드뷰 형태로 아이템이 하나 존재하고, 배경색은 민트색으로 되어 있는 MainActivity다.
activity_Second.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".SecondActivity">
<ImageView
android:id="@+id/profile_img"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:layout_marginRight="10dp"
android:scaleType="fitXY"
android:src="@drawable/ic_baseline_accessibility_24" />
<TextView
android:id="@+id/name_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/profile_img"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="Kang min gu"
android:textColor="#000000"
android:textSize="30sp" />
<TextView
android:id="@+id/content_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_below="@id/name_txt"
android:layout_centerHorizontal="true"
android:text="title"
android:textSize="20sp" />
</RelativeLayout>
SecondAcitivy 화면( B화면 )은 MainActivity ( A 화면 )에서 아이템을 클릭했을 때 보여줄 화면이다.
activity_main.xml에서 설정한 뷰의 id값과 second_activity.xml에서 설정한 뷰의 id값이 같은데 화면 전환이 되었을 때
A 화면에서 보여주는 뷰가 B 화면으로 전환 될 때의 뷰라는 것을 헷갈리지 않게 해 놓은 것이다.
화면 전환 할 뷰를 만들었으니 이제 애니메이션을 적용해 주면 화면 전환 시 애니메이션이 적용이 될 것이다.
먼저 Styles.xml에 "android:windowActivityTransitions" 속성을 사용 허가해줘야 한다.
Styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowActivityTransitions">true</item>
</style>
</resources>
AcitivityOptions.makeScenceTransitonAnimation()을 이용한 화면 전환 적용
화면 전환은 Intent를 이용하여 전환될 액티비티를 호출해 준다.
Intent로 화면을 전환하는 것은 똑같으나 여기에 추가적인 옵션을 부여해 주면 된다.
//기존 Intent를 호출하여 화면 전환하던 방식
val intent : Intent = Intent(this, SecondAcitivity::class.java)
startActivity(intent)
xml 코드에 android:transitionName 속성으로 화면이 전환될 때 애니메이션이 적용될 뷰끼리 묶어준다.
<!-- activity_main.xml 코드에 있는 프로필 이미지 -->
<ImageView
android:id="@+id/profile_img"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignBaseline="@id/name_txt"
android:layout_toStartOf="@id/name_txt"
android:layout_marginRight="10dp"
android:transitionName="imageTransition"
android:scaleType="fitXY"
android:src="@drawable/ic_baseline_accessibility_24" />
<!-- activity_second.xml 코드에 있는 프로필 이미지 -->
<ImageView
android:id="@+id/profile_img2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:layout_marginRight="10dp"
android:scaleType="fitXY"
android:transitionName="imageTransition"
android:src="@drawable/ic_baseline_accessibility_24"/>
두 이미지의 id는 다르지만 ( 위에서는 같게 했으나 차이를 보여주기 위해 id 값을 바꿔 주었다. )
transitionName이 "imageTransition"으로 서로 같은 속성을 가지고 있음을 보여주고 있다.
이렇게 화면 전환 시 애니메이션이 될 대상끼리 같은 이름으로 묶어주면 된다. ( 이름은 원하는 이름으로 설정해주면 된다.)
xml에서 transitionName 속성으로 모두 설정을 해줬다면 메인코드에서 화면 전환을 설정해주면 된다.
애니메이션은 다음과 같이 지정해주면 된다.
var intent = Intent(this, SecondActivity::class.java)
var options : ActivityOptions = ActivityOptions.makeSceneTransitionAnimation(
this, View, "String")
startActivity(intent, options.toBundle())
ActivityOptions.makeSceneTransitionAnimation()을 이용하여 애니메이션을 적용시켜 주면 된다.
- View : 애니메이션을 적용시킬 View의 id 값
- "String" : xml에서 설정한 transitionName 값
다음과 같이 코드를 작성해 주면 깔끔한 페이드 인/아웃 애니메이션과 함께 transitionName속성이 일치하는 뷰가
이동하면서 화면이 전환된다. 그러나 우리는 하나의 뷰가 아닌 여러 개의 뷰를 동시다발적으로 적용하고 싶다.
동시에 여러 개의 뷰에 적용을 하고 싶다면 Pair를 이용하여 여러 개를 공유하면 된다.
카드 뷰 아이템을 클릭 할 시 애니메이션이 적용되어야 하므로 MainActivity에서 다음과 같이 코드를 작성한다.
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
main_card.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
var options : ActivityOptions = ActivityOptions.makeSceneTransitionAnimation(
this,
Pair.create(name_txt, "nameTransition"),
Pair.create(content_txt, "contentTransition"),
Pair.create(profile_img, "imageTransition")
)
startActivity(intent, options.toBundle())
}
}
}
간단한 코드 구성으로 생각보다 짧은 시간 내에 있어 보이는 애니메이션을 구현할 수 있었다.
지금은 실습을 통해 간단하게 구성했지만, 실제 적용할 때는 RecyclerView 아이템을 누른 후 상세페이지로 넘어갈 때
다음과 같은 코드를 응용하여 화면을 구성하면 멋진 앱이 만들어지지 않을까 싶다.
전체 실습에 대한 코드를 보고 싶으면 본인의 Git 링크를 타고 들어가면 볼 수 있다.
https://github.com/kangmin1012/NewAndroidExercise/tree/LayoutAnimation
'안드로이드' 카테고리의 다른 글
[Android/Kotlin]ViewPager에 wrap_content 가능케 하기 (0) | 2020.07.06 |
---|---|
[Android/Kotlin] Shared elemet transition - RecyclerView에 적용 (1) | 2020.06.25 |
[Android/Kotlin] CoordinatorLayout 사용하기 (1) - 기초 (0) | 2020.06.09 |
[Android/짤팁] 작업 중인 액티비티만 실행하고 싶을 경우 (0) | 2020.05.07 |
[Android/Kotlin] 카메라로 사진 찍고 이미지뷰에 넣기 (2) (0) | 2020.04.22 |