Android

Android | Activity Sliding Open

8iggy 2021. 5. 1. 12:50

읽기 전

  • 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다.
  • 개인적으로 사용해보면서 배운 점을 정리한 글입니다.

사이드 프로젝트에서 커뮤니티 기능을 구현하자는 의견이 나왔다. 커뮤니티 기능은 사실 제대로 구현하려면 거의 준 프로젝트 급이라 따로 페이지를 만들어서 구현하는게 낫겠다는 판단이 섰다. 시연용 앱만 제작하라고 주문받았지만 원래 관심이 있었던 분야라 기능적 구현 완성을 목표로 정리를 시작하려 한다.

이번 포스팅은 액티비티 전환 시 슬라이딩 애니메이션 효과 적용에 대한 내용입니다.

이전 포스팅 - Android Toolbar Custom하기와 이어집니다.

동작 설명

MainActivity에서 버튼 클릭 시 액티비티를 종료하고 새로운 액티비티를 생성할 때 sliding 전환 효과를 주려고 한다.

UI 배치하기

MainActivity.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">

    <Button
        android:id="@+id/btnGoToCommunity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Go To Community"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

새로운 액티비티를 불러올 버튼 한 개만 간단히 생성하였다.

CommunityActivity.xml

<androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/toolbar_layout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/communityToolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            android:theme="?attr/actionBarTheme"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navigationIcon="@drawable/abc_vector_test">

            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/colorPrimary"
                android:orientation="horizontal">

                <androidx.constraintlayout.widget.Guideline
                    android:id="@+id/toolbar_hg_10"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    app:layout_constraintGuide_percent="0.15" />

                <androidx.constraintlayout.widget.Guideline
                    android:id="@+id/toolbar_hg_90"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    app:layout_constraintGuide_percent="0.85" />

                <TextView
                    android:id="@+id/toolBarTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="커뮤니티"
                    android:textColor="#FFFFFF"
                    android:textSize="18sp"
                    android:textStyle="bold"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

            </androidx.constraintlayout.widget.ConstraintLayout>
        </androidx.appcompat.widget.Toolbar>
    </androidx.constraintlayout.widget.ConstraintLayout>

이어지는 액티비티에는 다시 이전 액티비티로 돌려보낼 툴바 한 개를 생성하였다.

Anim 리소스 폴더, action.xml 생성하기

원하는 Animation을 따로 관리하고 싶다면 anim resouce type을 갖는 resource 폴더를 생성해야 한다. res 폴더에 새로운 폴더를 생성하면서 [New] - [Android Resource Directory]를 클릭하면 특정 리소트 타입을 갖는 폴더 생성이 가능하다. Resource Type을 Anim로 지정하고 폴더를 생성한다.

더 상위 버전인 Animator를 사용하지 않는 이유는 액티비티 내부에서 클릭과 같은 특정 이벤트 발생 시 시연되는 객체 별 애니메이션이 아니라 액티비티 자체를 전환하기 위해 사용하기에 비교적 단순한 작업이므로 Anim을 채택하였다.

Android_Sliding_Activity_01

폴더를 생성한 뒤 애니메이션을 지정하기 위한 xml 파일을 생성한다.액티비티 진입 시 왼쪽으로 퇴장, 오른쪽으로 진입하는 경우와 액티비티 퇴장 시 오른쪽으로 퇴장, 왼쪽으로 진입하는 경우의 4가지 Action이 필요하다.

액티비티 진입 - 왼쪽으로 퇴장

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromXDelta="0%"
        android:toXDelta="-100%" />
</set>

퇴장 액티비티 왼쪽을 기준으로 0에서 -100으로 퇴장한다. 지속시간은 0.3초이다.

액티비티 진입 - 오른쪽에서 등장

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromXDelta="100%"
        android:toXDelta="0%" />
</set>

등장 액티비티 왼쪽을 기준으로 100에서 0으로 등장한다. 지속시간은 0.3초이다.

액티비티 퇴장 - 오른쪽으로 퇴장

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromXDelta="0%"
        android:toXDelta="100%" />
</set>

퇴장 액티비티 왼쪽을 기준으로 0에서 100으로 퇴장한다. 지속시간은 0.3초이다.

액티비티 퇴장 - 왼쪽에서 등장

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromXDelta="-100%"
        android:toXDelta="0%" />
</set>

등장 액티비티 왼쪽을 기준으로 -100에서 0으로 등장한다. 지속시간은 0.3초이다.

코드 작업하기

MainActivity

public class MainActivity extends AppCompatActivity {
    Button btnGoToCommunity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnGoToCommunity = findViewById(R.id.btnGoToCommunity);
        btnGoToCommunity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                    Intent intent = new Intent(MainActivity.this, CommunityActivity.class);
                    startActivity(intent);
                    overridePendingTransition(R.anim.right_in, R.anim.left_out);
                    finish();
                }
            }
        });
    }
}

생성해둔 버튼을 정의한 뒤 클릭 리스너를 생성한다. 다음 액티비티로 가는 Intent를 정의한 뒤 액티비티를 실행한다 그리고 overridePendingTransition(등장 anim, 퇴장 anim)을 작성한다. 등장 anim은 CommunityActivity가 어떻게 등장해야 하는지, 퇴장 anim은 MainActivity가 어떻게 퇴장해야 하는지 정의한다.

CommunityActivity

    private void initView() {
        Toolbar communityToolbar = findViewById(R.id.communityToolbar);
        setSupportActionBar(communityToolbar);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        communityToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                goToMainActivity();
            }
        });
    }

    private void goToMainActivity() {
        Intent intent = new Intent(CommunityActivity.this, MainActivity.class);
        startActivity(intent);
        overridePendingTransition(R.anim.left_in, R.anim.right_out);
        finish();
    }

커스텀 툴바 적용하는 코드는 이전 포스팅을 참고하기로 하고 sliding anim 적용에 필요한 코드만 발췌해서 가져왔다. MainActivity에서 넘어온 뒤 툴바의 뒤로가기 버튼을 클릭하여 다시 슬라이딩 효과로 MainActivity로 되돌아가려 한다. 따라서 MainActivity처럼 goToMainActivity() 메소드 내부에 액티비티 전환 코드를 작성하였다. 등장 anim은 MainActivity가 어떻게 등장해야 하는지, 퇴장 anim은 CommunityActivity가 어떻게 퇴장해야 하는지를 의미한다. 이제 커스텀 툴바의 navigation 버튼에 클릭 리스너를 정의하여 뒤로가기 버튼 클릭 시 goToMainActivity 메소드를 호출하게 만들자.

그리고 별도로 back 버튼 press에도 적용하지 않으면 일반적인으로 액티비티가 퇴장하듯 아래로 소멸한다. back 버튼을 press했을 경우에도 똑같이 동작하게끔 하고 싶으면 아래 코드를 작성하면 된다.

    @Override
    public void onBackPressed() {
        goToMainActivity();
    }

동작 결과

Android_Sliding_Activity_02