اسلایدهای صفحه انتقال بین یک صفحه نمایش کامل به صفحه دیگر هستند و در رابط های کاربری مانند جادوگرهای راه اندازی یا نمایش اسلاید رایج هستند. این درس به شما نشان می دهد که چگونه اسلایدهای صفحه را با 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>
قطعه را ایجاد کنید
یک کلاس Fragment
ایجاد کنید که طرحی را که به تازگی در متد onCreateView()
ایجاد کرده اید، برمی گرداند. سپس می توانید هر زمان که نیاز به صفحه جدیدی برای نمایش به کاربر داشتید، نمونه هایی از این قطعه را در فعالیت والد ایجاد کنید:
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
به عنوان صفحات جدید پیاده سازی می کند. آداپتور پیجر همچنین نیاز دارد که متدgetCount()
را پیاده سازی کنید که تعداد صفحاتی را که آداپتور ایجاد می کند (پنج در مثال) برمی گرداند. -
PagerAdapter
بهViewPager
متصل می کند.
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()
را نشان می دهد. در هر نقطه از انتقال صفحه، این روش یک بار برای هر صفحه قابل مشاهده (به طور کلی فقط یک صفحه قابل مشاهده وجود دارد) و برای صفحات مجاور فقط خارج از صفحه فراخوانی می شود. به عنوان مثال، اگر صفحه سه قابل مشاهده باشد و کاربر به سمت صفحه چهار بکشد، transformPage()
برای صفحات دو، سه و چهار در هر مرحله از ژست فراخوانی می شود.
در پیاده سازی transformPage()
، می توانید انیمیشن های اسلاید سفارشی را با تعیین اینکه کدام صفحات باید بر اساس موقعیت صفحه روی صفحه تبدیل شوند، ایجاد کنید، که از پارامتر position
متد transformPage()
بدست می آید.
پارامتر position
نشان می دهد که یک صفحه معین نسبت به مرکز صفحه در کجا قرار دارد. این یک ویژگی پویا است که با پیمایش کاربر در صفحات تغییر می کند. وقتی صفحه ای صفحه را پر می کند، مقدار موقعیت آن 0
است. وقتی صفحه ای درست از سمت راست صفحه کشیده می شود، مقدار موقعیت آن 1
است. اگر کاربر در نیمه راه بین صفحات یک و دو پیمایش کند، صفحه یک موقعیت 0.5- و صفحه دو موقعیت 0.5 دارد. بر اساس موقعیت صفحات روی صفحه، می توانید انیمیشن های اسلاید سفارشی را با تنظیم ویژگی های صفحه با روش هایی مانند setAlpha()
، setTranslationX()
یا setScaleY()
ایجاد کنید.
هنگامی که پیاده سازی یک PageTransformer
دارید، با پیاده سازی خود setPageTransformer()
را فراخوانی کنید تا انیمیشن های سفارشی خود را اعمال کنید. به عنوان مثال، اگر یک PageTransformer
به نام ZoomOutPageTransformer
دارید، می توانید انیمیشن های سفارشی خود را به این صورت تنظیم کنید:
val mPager: ViewPager = findViewById(R.id.pager)
...
mPager.setPageTransformer(true, ZoomOutPageTransformer())
ViewPager mPager = (ViewPager) findViewById(R.id.pager);
...
mPager.setPageTransformer(true, new ZoomOutPageTransformer());
برای مثالها و ویدیوهای یک PageTransformer
به بخش Zoom-out page Transformer و Depth page Transformer مراجعه کنید.
ترانسفورماتور صفحه بزرگنمایی
این ترانسفورماتور صفحه هنگام پیمایش بین صفحات مجاور صفحات را کوچک و محو می کند. همانطور که یک صفحه به مرکز نزدیکتر می شود، به اندازه طبیعی خود باز می گردد و محو می شود.
ZoomOutPageTransformer
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);
}
}
}
ترانسفورماتور صفحه عمق
این ترانسفورماتور صفحه از انیمیشن اسلاید پیش فرض برای لغزش صفحات به سمت چپ استفاده می کند، در حالی که از انیمیشن "عمق" برای کشویی صفحات به سمت راست استفاده می کند. این انیمیشن عمقی صفحه را محو می کند و آن را به صورت خطی کوچک می کند.
DepthPageTransformer
در طول انیمیشن عمقی، انیمیشن پیشفرض (یک اسلاید صفحه) همچنان انجام میشود، بنابراین باید با یک ترجمه X منفی با اسلاید صفحه مقابله کنید. به عنوان مثال:
view.translationX = -1 * view.width * position
view.setTranslationX(-1 * view.getWidth() * position);
مثال زیر نحوه مقابله با انیمیشن اسلاید صفحه پیش فرض را در یک ترانسفورماتور صفحه کاری نشان می دهد:
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
}
}
}
}
}
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);
}
}
}