同じ機能が必要な人にアップデートを提供したいと思います。これまでのところ、この機能の実装には多くの進歩があり、現在、ビューは必要に応じて正確に機能しています。
ViewPagerには、setPageMargin()というメソッドがあります。このメソッドは、フラグメント/ビューを互いにオーバーラップさせる負の値を受け取る可能性があります。目的のレイアウトに到達するために、最初に画面のパーセンテージで左右のマージンを動的に計算しました。これは静的にも実行できますが、さまざまな画面サイズをターゲットにするため、これが最善のアプローチのようです。
後で、ViewPagerのページマージンをサイドマージンのサイズの2倍に設定しました。これにより、ビューが元に戻ります。ただし、現時点では、ViewPagerによって複数のビューが表示されます。
あとは、左右のビューに変換(スケール)を適用するか(Android 3.0以降)、周囲に余白を追加して適切なサイズに縮小する(3.0より前)だけです。
OnPageChangeListener.onPageScrolled()を使用して、ViewPagerのスクロールを追跡できます。スムーズな変換が可能です。コードは次のようになります。
private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// positionOffset varies from 0 to 1 and indicates how far the view is
// from the center of the ViewPager. When a view is selected (centered), this
// value is 0.
// Fades the text in an out while the ViewPager scrolls from one view to another.
// On our final design the text views are fixed to the center of the screen and
// do not scroll along with the views.
if (positionOffset < 0.5) {
setTextViewAlpha(1 - positionOffset * 2);
} else {
setTextViewAlpha((positionOffset - 0.5f) * 2);
}
// It's surprisingly complicated to get the current object being displayed by
// a ViewPager (there's no getCurrentObject method). ScaleableFragment is just
// a custom class to allow an adapter to cache it internally and also correctly
// manage a fragment's lifecycle and restore from a saved state.
ScaleableFragment sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager
.getAdapter()).getItem(position);
// Calculates by how much the current view will be scaled down. The RATIO_SCALE
// is 0.3 in our case, which makes the side views 70% of the size of the
// center view. When centered, the scale will be 1. When
// fully scrolled, the scale will be 0.7.
float scale = 1 - (positionOffset * RATIO_SCALE);
// Just a shortcut to findViewById(R.id.image).setScale(scale);
sampleFragment.scaleImage(scale);
// Now, if not in the last element, scale the next one up (in opposite direction).
if (position + 1 < pager.getAdapter().getCount()) {
sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager.getAdapter())
.getItem(position + 1);
scale = positionOffset * RATIO_SCALE + (1 - RATIO_SCALE);
sampleFragment.scaleImage(scale);
}
}
// Once scrolling is done. Make sure the views are in the right scale (1 for center,
// 0.7 for sides). Required as the onPageScrolled() method does not guarantee it
// will interpolate to 1.0 precisely.
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
setTextViewAlpha(1);
ScaleableFragment sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager
.getAdapter()).getItem(pager.getCurrentItem());
sampleFragment.scaleImage(1);
sampleFragment.enableClicks();
if (pager.getCurrentItem() > 0) {
sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager.getAdapter())
.getItem(pager.getCurrentItem() - 1);
sampleFragment.scaleImage(1 - RATIO_SCALE);
sampleFragment.disableClicks();
}
if (pager.getCurrentItem() + 1 < pager.getAdapter().getCount()) {
sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager.getAdapter())
.getItem(pager.getCurrentItem() + 1);
sampleFragment.scaleImage(1 - RATIO_SCALE);
sampleFragment.disableClicks();
}
}
}
};
これだよ。私は完全な解決策を投稿しませんでしたが、これが他の誰かを始めるのに十分であることを願っています。
PS On 3.0+は、ハードウェアアクセラレーションを有効にします。それがないと、サムスンギャラクシータブ10.1でスクロールが途切れ途切れに見えました。