화면 슬라이드는 전체 화면 간의 전환이며 설정 마법사 또는 슬라이드쇼와 같은 UI에서 일반적으로 사용됩니다. 이 과정에서는 지원 라이브러리에서 제공하는 ViewPager
를 사용하여 화면 슬라이드를 실행하는 방법을 보여줍니다.
ViewPager
객체는 화면 슬라이드에 자동으로 애니메이션을 적용할 수 있습니다. 다음은 콘텐츠의 한 화면에서 다음 화면으로 전환되는 화면 슬라이드입니다.
ViewPager
는 AndroidX의 일부입니다. 자세한 내용은 AndroidX 사용을 참고하세요.
뷰 만들기
나중에 프래그먼트 콘텐츠에 사용할 레이아웃 파일을 만듭니다. 프래그먼트 콘텐츠에 대한 문자열도 정의해야 합니다. 다음 예에는 텍스트를 표시하는 텍스트 뷰가 포함되어 있습니다.
<!-- fragment_screen_slide_page.xml --> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView style="?android:textAppearanceMedium" android:padding="16dp" android:lineSpacingMultiplier="1.2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/lorem_ipsum" /> </ScrollView>
프래그먼트 만들기
onCreateView()
메서드에서 방금 만든 레이아웃을 반환하는 Fragment
클래스를 만듭니다. 그러면 사용자에게 표시할 새 페이지가 필요할 때마다 상위 활동에서 이 프래그먼트의 인스턴스를 만들 수 있습니다.
Kotlin
import android.support.v4.app.Fragment class ScreenSlidePageFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_screen_slide_page, container, false) }
자바
import android.support.v4.app.Fragment; ... public class ScreenSlidePageFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate( R.layout.fragment_screen_slide_page, container, false); return rootView; } }
ViewPager 추가
ViewPager
객체에는 페이지 간에 전환하는 스와이프 동작이 내장되어 있으며 기본적으로 화면 슬라이드 애니메이션을 표시하므로 개발자가 자체 애니메이션을 만들 필요가 없습니다. ViewPager
는 표시할 새 페이지의 공급원으로 PagerAdapter
객체를 사용하므로 PagerAdapter
는 개발자가 이전에 만든 프래그먼트 클래스를 사용합니다.
시작하려면 ViewPager
가 포함된 레이아웃을 만듭니다.
<!-- activity_screen_slide.xml --> <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" />
다음을 수행하는 활동을 만듭니다.
- 콘텐츠 뷰를
ViewPager
가 있는 레이아웃으로 설정합니다. FragmentStatePagerAdapter
추상 클래스를 확장하는 클래스를 만들고getItem()
메서드를 구현하여ScreenSlidePageFragment
인스턴스를 새 페이지로 제공합니다. 페이저 어댑터는 어댑터에서 만들 페이지 수(예에서는 5개)를 반환하는getCount()
메서드도 구현해야 합니다.PagerAdapter
를ViewPager
에 연결합니다.
Kotlin
import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager ... /** * The number of pages (wizard steps) to show in this demo. */ private const val NUM_PAGES = 5 class ScreenSlidePagerActivity : FragmentActivity() { /** * The pager widget, which handles animation and allows swiping horizontally to access previous * and next wizard steps. */ private lateinit var mPager: ViewPager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_screen_slide) // Instantiate a ViewPager and a PagerAdapter. mPager = findViewById(R.id.pager) // The pager adapter, which provides the pages to the view pager widget. val pagerAdapter = ScreenSlidePagerAdapter(supportFragmentManager) mPager.adapter = pagerAdapter } override fun onBackPressed() { if (mPager.currentItem == 0) { // If the user is currently looking at the first step, allow the system to handle the // Back button. This calls finish() on this activity and pops the back stack. super.onBackPressed() } else { // Otherwise, select the previous step. mPager.currentItem = mPager.currentItem - 1 } } /** * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in * sequence. */ private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { override fun getCount(): Int = NUM_PAGES override fun getItem(position: Int): Fragment = ScreenSlidePageFragment() } }
자바
import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; ... public class ScreenSlidePagerActivity extends FragmentActivity { /** * The number of pages (wizard steps) to show in this demo. */ private static final int NUM_PAGES = 5; /** * The pager widget, which handles animation and allows swiping horizontally to access previous * and next wizard steps. */ private ViewPager mPager; /** * The pager adapter, which provides the pages to the view pager widget. */ private PagerAdapter pagerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_screen_slide); // Instantiate a ViewPager and a PagerAdapter. mPager = (ViewPager) findViewById(R.id.pager); pagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); mPager.setAdapter(pagerAdapter); } @Override public void onBackPressed() { if (mPager.getCurrentItem() == 0) { // If the user is currently looking at the first step, allow the system to handle the // Back button. This calls finish() on this activity and pops the back stack. super.onBackPressed(); } else { // Otherwise, select the previous step. mPager.setCurrentItem(mPager.getCurrentItem() - 1); } } /** * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in * sequence. */ private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { public ScreenSlidePagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return new ScreenSlidePageFragment(); } @Override public int getCount() { return NUM_PAGES; } } }
PageTransformer를 사용하여 애니메이션 맞춤설정
기본 화면 슬라이드 애니메이션과 다른 애니메이션을 표시하려면 ViewPager.PageTransformer
인터페이스를 구현하여 뷰 페이저에 제공합니다. 이 인터페이스는 단일 메서드 transformPage()
를 노출합니다. 화면 전환의 각 지점에서 이 메서드는 표시되는 페이지(일반적으로 단 한 개의 페이지만 표시됨)마다, 그리고 화면에 표시되지 않는 인접 페이지에 대해 한 번씩 호출됩니다.
예를 들어 페이지 3이 표시된 상태에서 사용자가 페이지 4로 드래그하는 경우 이 동작의 각 단계에서 페이지 2, 페이지 3, 페이지 4에 대해 transformPage()
가 호출됩니다.
그런 다음 transformPage()
구현에서 화면의 페이지 위치에 따라 변환해야 하는 페이지를 결정하여 맞춤 슬라이드 애니메이션을 만들 수 있습니다. 이 위치는 transformPage()
메서드의 position
매개변수에서 가져옵니다.
position
매개변수는 화면 중앙을 기준으로 특정 페이지의 위치를 나타냅니다.
이 매개변수는 사용자가 페이지를 스크롤할 때 변경되는 동적 속성입니다. 페이지가 화면을 채우면 위치 값은 0
입니다.
페이지가 화면 오른쪽에서 벗어나면 위치 값은 1
입니다. 사용자가 페이지 1과 페이지 2의 중간으로 스크롤하면 페이지 1의 위치 값은 -0.5이고 페이지 2의 위치 값은 0.5입니다. 화면의 페이지 위치에 따라 setAlpha()
, setTranslationX()
또는 setScaleY()
와 같은 메서드로 페이지 속성을 설정하여 맞춤 슬라이드 애니메이션을 만들 수 있습니다.
PageTransformer
를 구현한 경우 구현과 함께 setPageTransformer()
를 호출하여 맞춤 애니메이션을 적용합니다. 예를 들어, ZoomOutPageTransformer
라는 이름의 PageTransformer
가 있다면 다음과 같이 맞춤 애니메이션을 설정할 수 있습니다.
Kotlin
val mPager: ViewPager = findViewById(R.id.pager) ... mPager.setPageTransformer(true, ZoomOutPageTransformer())
자바
ViewPager mPager = (ViewPager) findViewById(R.id.pager); ... mPager.setPageTransformer(true, new ZoomOutPageTransformer());
PageTransformer
의 예와 동영상은 페이지 축소 변환기 및 심도 페이지 변환기 섹션을 참고하세요.
페이지 축소 변환기
이 페이지 변환기는 인접 페이지 사이를 스크롤할 때 페이지를 축소하고 페이드 아웃합니다. 페이지가 중앙에 가까워지면 원래 크기로 다시 커지면서 페이드인됩니다.
Kotlin
private const val MIN_SCALE = 0.85f private const val MIN_ALPHA = 0.5f class ZoomOutPageTransformer : ViewPager.PageTransformer { override fun transformPage(view: View, position: Float) { view.apply { val pageWidth = width val pageHeight = height when { position < -1 -> { // [-Infinity,-1) // This page is way off-screen to the left. alpha = 0f } position <= 1 -> { // [-1,1] // Modify the default slide transition to shrink the page as well val scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)) val vertMargin = pageHeight * (1 - scaleFactor) / 2 val horzMargin = pageWidth * (1 - scaleFactor) / 2 translationX = if (position < 0) { horzMargin - vertMargin / 2 } else { horzMargin + vertMargin / 2 } // Scale the page down (between MIN_SCALE and 1) scaleX = scaleFactor scaleY = scaleFactor // Fade the page relative to its size. alpha = (MIN_ALPHA + (((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA))) } else -> { // (1,+Infinity] // This page is way off-screen to the right. alpha = 0f } } } } }
자바
public class ZoomOutPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0f); } else if (position <= 1) { // [-1,1] // Modify the default slide transition to shrink the page as well float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); } // Scale the page down (between MIN_SCALE and 1) view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); // Fade the page relative to its size. view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0f); } } }
심도 페이지 변환기
이 페이지 변환기에서는 페이지를 왼쪽으로 넘길 때에는 기본 슬라이드 애니메이션을 사용하고, 페이지를 오른쪽으로 넘길 때에는 '심도' 애니메이션을 사용합니다. 이 심도 애니메이션은 페이지를 페이드아웃하고 선형으로 축소합니다.
심도 애니메이션에서는 기본 애니메이션(화면 슬라이드)이 여전히 있기 때문에, 음수의 X 변환을 지정하여 화면 슬라이드를 차단해야 합니다. 예를 들면 다음과 같습니다.
Kotlin
view.translationX = -1 * view.width * position
자바
view.setTranslationX(-1 * view.getWidth() * position);
다음 예는 작동하는 페이지 변환기에서 기본 화면 슬라이드 애니메이션을 차단하는 방법을 보여줍니다.
Kotlin
private const val MIN_SCALE = 0.75f class DepthPageTransformer : ViewPager.PageTransformer { override fun transformPage(view: View, position: Float) { view.apply { val pageWidth = width when { position < -1 -> { // [-Infinity,-1) // This page is way off-screen to the left. alpha = 0f } position <= 0 -> { // [-1,0] // Use the default slide transition when moving to the left page alpha = 1f translationX = 0f scaleX = 1f scaleY = 1f } position <= 1 -> { // (0,1] // Fade the page out. alpha = 1 - position // Counteract the default slide transition translationX = pageWidth * -position // Scale the page down (between MIN_SCALE and 1) val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position))) scaleX = scaleFactor scaleY = scaleFactor } else -> { // (1,+Infinity] // This page is way off-screen to the right. alpha = 0f } } } } }
Java
public class DepthPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0f); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page view.setAlpha(1f); view.setTranslationX(0f); view.setScaleX(1f); view.setScaleY(1f); } else if (position <= 1) { // (0,1] // Fade the page out. view.setAlpha(1 - position); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0f); } } }