앱 최초 실행 시 가이드 화면을 표시하는 기능은 많은 개발자들에게 익숙한 요구사항입니다. 이 효과는 어떻게 구현할 수 있을까요? 이번 글에서는 ViewPager를 사용하여 이미지 슬라이드쇼를 만들고, 다양한 전환 애니메이션 효과를 적용하는 방법을 살펴보겠습니다.
ViewPager는 Android에서 화면 간 전환을 처리하는 핵심 컴포넌트입니다. 자세한 설명은 생략하고 바로 실습으로 넘어가겠습니다.
기본 이미지 슬라이더 구현
먼저 간단한 레이아웃 파일부터 작성합니다:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<com.example.android_viewpager.CustomViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
다음은 메인 액티비티 구현 코드입니다:
public class MainActivity extends Activity {
private CustomViewPager pagerInstance;
int[] resourceIds = {R.drawable.guide_image1, R.drawable.guide_image2, R.drawable.guide_image3};
List<ImageView> imageViewList = new ArrayList<ImageView>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pagerInstance = (CustomViewPager) findViewById(R.id.viewPager);
pagerInstance.setAdapter(new PagerAdapter() {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(imageViewList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(resourceIds[position]);
imageView.setScaleType(ScaleType.CENTER_CROP);
container.addView(imageView);
imageViewList.add(imageView);
return imageView;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public int getCount() {
return resourceIds.length;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
애니메이션 효과 적용
Google은 ViewPager에 애니메이션 효과를 추가할 수 있는 공식 API를 제공합니다. 공식 문서(링크)를 참고하여 구현해보겠습니다.
애니메이션을 적용하는 방법은 매우 간단합니다:
pagerInstance.setPageTransformer(true, new DepthPageTransformer());
깊이 기반 전환 효과를 구현한 DepthPageTransformer 클래스:
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MINIMUM_SCALE = 0.75f;
@SuppressLint("NewApi")
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) {
view.setAlpha(0);
} else if (position <= 0) {
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) {
view.setAlpha(1 - position);
view.setTranslationX(pageWidth * -position);
float scaleFactor = MINIMUM_SCALE + (1 - MINIMUM_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else {
view.setAlpha(0);
}
}
}
하위 버전 호환성 처리
위 코드는 Android 3.0(API level 11) 이상에서만 동작합니다. 하위 버전에서도 동일한 효과를 구현하려면 ViewHelper를 사용해야 합니다:
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class CompatibleDepthPageTransformer implements ViewPager.PageTransformer {
private static final float MINIMUM_SCALE = 0.75f;
@SuppressLint("NewApi")
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) {
ViewHelper.setAlpha(view, 0);
} else if (position <= 0) {
ViewHelper.setAlpha(view, 1);
ViewHelper.setTranslationX(view, 0);
ViewHelper.setScaleX(view, 1);
ViewHelper.setScaleY(view, 1);
} else if (position <= 1) {
ViewHelper.setAlpha(view, 1 - position);
ViewHelper.setTranslationX(view, pageWidth * -position);
float scaleFactor = MINIMUM_SCALE + (1 - MINIMUM_SCALE) * (1 - Math.abs(position));
ViewHelper.setScaleX(view, scaleFactor);
ViewHelper.setScaleY(view, scaleFactor);
} else {
ViewHelper.setAlpha(view, 0);
}
}
}
ViewPager 소스코드를 살펴보면 버전 체크 로직이 포함되어 있어 하위 버전에서는 애니메이션이 실행되지 않습니다. 이를 해결하기 위해 ViewPager 클래스를 상속받아 커스터마이징해야 합니다:
public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) {
// if (Build.VERSION.SDK_INT >= 11) 제거
{
final boolean hasTransformer = transformer != null;
final boolean needsPopulate = hasTransformer != (mPageTransformer != null);
mPageTransformer = transformer;
setChildrenDrawingOrderEnabledCompat(hasTransformer);
if (hasTransformer) {
mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD;
} else {
mDrawingOrder = DRAW_ORDER_DEFAULT;
}
if (needsPopulate) populate();
}
}
레이아웃 파일도 수정된 클래스를 사용하도록 변경합니다:
<com.example.android_viewpager.CustomViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
액티비티 코드도 다음과 같이 업데이트합니다:
pagerInstance = (CustomViewPager) findViewById(R.id.viewPager);
추가 애니메이션 효과
회전 효과를 구현한 예제도 함께 소개합니다:
public class RotateDownPageTransformer implements ViewPager.PageTransformer {
private static final float MAX_ROTATION = 20F;
private static float currentRotation = 0F;
@Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) {
ViewHelper.setAlpha(view, 0);
} else if (position <= 0) {
currentRotation = MAX_ROTATION * position;
ViewHelper.setPivotX(view, pageWidth/2);
ViewHelper.setPivotY(view, view.getMeasuredHeight());
ViewHelper.setRotation(view, currentRotation);
} else if (position <= 1) {
currentRotation = MAX_ROTATION * position;
ViewHelper.setPivotX(view, pageWidth/2);
ViewHelper.setPivotY(view, view.getMeasuredHeight());
ViewHelper.setRotation(view, currentRotation);
} else {
ViewHelper.setAlpha(view, 0);
}
}
}
이러한 방법들을 통해 ViewPager에 다양한 전환 애니메이션 효과를 적용할 수 있습니다. 궁금한 점이 있다면 댓글로 문의해주세요.