效果图:

xml布局
XML
<!-- 关键修改:添加 clipToPadding 和 padding 实现两侧露出效果 -->
<!-- 使用 FrameLayout 包裹,确保内容居中 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/viewPagerPoster"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:clipToPadding="false"
android:paddingStart="40dp"
android:paddingEnd="40dp"
android:overScrollMode="never" />
</FrameLayout>
关键代码:
java
/**
* 配置 ViewPager 画廊效果(居中显示,两侧露出相邻页面)
*/
private void setupGalleryViewPager() {
// 设置预加载页面数,确保相邻页面已加载
viewPagerPoster.setOffscreenPageLimit(2);
// 设置页面间距(item之间的间距)
viewPagerPoster.setPageMargin(getResources().getDimensionPixelSize(R.dimen.dp_6));
// 设置 PageTransformer 实现缩放效果(可选,增强视觉层次)
viewPagerPoster.setPageTransformer(false, new ViewPager.PageTransformer() {
private static final float MIN_SCALE = 0.9f; // 最小缩放比例
private static final float MAX_SCALE = 1.0f; // 最大缩放比例
@Override
public void transformPage(View page, float position) {
// position: -1(左侧页面) 0(当前页面) 1(右侧页面)
if (position < -1 || position > 1) {
page.setAlpha(0.5f);
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
} else {
// 计算缩放比例:当前页面最大,两侧页面缩小
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position) * 0.1f);
page.setScaleX(scaleFactor);
page.setScaleY(scaleFactor);
// 透明度变化
page.setAlpha(0.9f + (scaleFactor - MIN_SCALE) / (MAX_SCALE - MIN_SCALE) * 0.5f);
// page.setAlpha(1);
}
}
});
// 重要:设置点击事件,让两侧页面可点击切换
viewPagerPoster.setOnTouchListener(new View.OnTouchListener() {
private float startX;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
break;
case MotionEvent.ACTION_UP:
float endX = event.getX();
float width = v.getWidth();
// 点击左侧区域切换到上一页
if (startX < width * 0.2f && currentPosition > 0) {
viewPagerPoster.setCurrentItem(currentPosition - 1, true);
return true;
}
// 点击右侧区域切换到下一页
else if (startX > width * 0.8f && currentPosition < posterUrls.size() - 1) {
viewPagerPoster.setCurrentItem(currentPosition + 1, true);
return true;
}
break;
}
return false;
}
});
}
/**
* 更新页码指示器
*/
private void updatePageIndicator() {
if (posterUrls != null && !posterUrls.isEmpty()) {
int currentPage = currentPosition + 1;
int totalPages = posterUrls.size();
tvPageIndicator.setText(currentPage + "/" + totalPages);
} else {
tvPageIndicator.setText("0/0");
}
}