效果图
实现方式核心思想是自定义PageTransformer继承ViewPager.PageTransformer,精确控制每一个page的动效。
PageTransformer的transformPage方法并不会区分当前的page是哪一个,所以需要我们自己去识别,我的方法是每个page添加一个text显示position,在PageTransformer中获取Text显示的内容来区分,实际使用的时候将textVew隐藏就行了
package com.example.anchorviewpagedemo;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.widget.ViewPager2;
/*
居中效果
*/
public class OverlayTransformerLan5 implements ViewPager.PageTransformer {
// public static final String TAG = OverlayTransformerLan2.class.getSimpleName();
public static final String TAG = "YinTest_";
public float mOffset = 40 * 2 - 20;
public int viewPageMarginHorizontal = 30;
public float screenWidth;
private Context mContext;
private float mMinScale;
public ViewPager mViewPager;
private int saveIndex = -1;
private int leftMostPageIndex = -1;
private int leftPageIndex = -1;
private int currentPageIndex = -1;
private int rightPageIndex = -1;
private int rightMostPageIndex = -1;
private int dataSize = -1;
public OverlayTransformerLan5(float minScale) {
mMinScale = minScale;
}
public OverlayTransformerLan5(Context context, ViewPager viewPager, int size, float minScale) {
mMinScale = minScale;
mContext = context;
mViewPager = viewPager;
dataSize = size;
//适配viewPage的边距,左右各10dp
viewPageMarginHorizontal = Utils.dp2Px(mContext, viewPageMarginHorizontal);
screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
}
@Override
public void transformPage(@NonNull View view, float position) {
// view.setAlpha(0.5f);
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
int cardViewWidth = view.findViewById(R.id.card_view).getWidth();
final float cardMargin = (pageWidth - cardViewWidth) / 2f;
TextView mTvPosition = view.findViewById(R.id.tv_position);
int viewIndex = Integer.parseInt(mTvPosition.getText().toString());
view.setPivotY(pageHeight / 2f);
view.setPivotX(pageWidth / 2f);
// Log.i("YinTest_", "transformPage position=" + position + ",pageWidth = " + pageWidth + ",viewIndex = "+viewIndex);
if (viewIndex == leftMostPageIndex) {
transformMostLeftPage(view, position, cardMargin, cardViewWidth, pageWidth);
} else if (viewIndex == leftPageIndex) {
transformLeftPage(view, position, cardMargin, cardViewWidth, pageWidth);
} else if (viewIndex == currentPageIndex) {
transformCenterPage(view, position, cardMargin, cardViewWidth, pageWidth);
} else if (viewIndex == rightPageIndex) {
transformRightPage(view, position, cardMargin, cardViewWidth, pageWidth);
} else if (viewIndex == rightMostPageIndex) {
transformMostRightPage(view, position, cardMargin, cardViewWidth, pageWidth);
}
}
public boolean isOutLimit(float initPosition, float position) {
if (position > initPosition + 1 || position < initPosition - 1) {
return true;
}
return false;
}
private void transformMostLeftPage(View view, float position, float cardMargin, int cardViewWidth, int pageWidth) {
if (isOutLimit(-2, position)) {
return;
}
float scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale;
//view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
float anchorLeft = cardMargin + cardViewWidth;//左页左边的锚点
float startPosition = pageWidth * 2;
view.setTranslationZ(position);
view.setPivotX(0);
//初始状态position=-2.0
if (position == -2) {
view.setTranslationX(startPosition);
}
//向右滑动
if (position > -2 && position < -1) {
//startPosition~anchorLeft 逆滑动
float translationX = (-position - 1) * startPosition + (position + 2) * anchorLeft;
view.setTranslationX(translationX);
}
//向左滑动
if (position < -2 && position > -3) {
//startPosition~anchorLeft 保持其实际位置不变,不影响其他页面翻转
// Log.i("YinTest_", " 最左页 向左滑动 position=" + position + ",translationX = " + (-position - 1));
view.setTranslationX(startPosition + (-(position + 2)) * pageWidth);
}
//变为右页(相对于起始位置)
if (position == -1) {
view.setTranslationX(anchorLeft);
}
//变为左页(相对于起始位置)
if (position == -3) {
//向左滑动保持不变,但变为左页后跳转到正常显示位置
view.setTranslationX(0);
}
}
private void transformLeftPage(View view, float position, float cardMargin, int cardViewWidth, int pageWidth) {
if (isOutLimit(-1, position)) {
return;
}
// Log.i("YinTest_", " position=" + position + ",cardMargin = " + cardMargin);
//初始状态position=-1.0,viewIndex = 0
float scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale;
//view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
float anchorLeft = cardMargin + cardViewWidth;//左页左边的锚点
view.setTranslationZ(position);
view.setPivotX(0);
// view.setAlpha(0.5f);
if (position == -1) {
//初始状态 position == -1
view.setTranslationX(anchorLeft);
}
if (position < -1 && position > -2) {
//向左滑动 anchorLeft ~ pageWidth*2
view.setTranslationX((position+2)*anchorLeft + (-2*position-2) * pageWidth);
}
//向右滑动
if (position > -1 && position < 0) {
//anchorLeft ~ 0
view.setTranslationX((-position) * anchorLeft);
}
//变为左页(相对于起始位置)
if (position == -2) {
view.setTranslationX(pageWidth*2);
}
//变为右叶(相对于起始位置)
if (position == 0) {
//左页变为当前页 position =0.0
view.setTranslationX(0);
}
}
private void transformCenterPage(View view, float position, float cardMargin, int cardViewWidth, int pageWidth) {
if (isOutLimit(0, position)) {
return;
}
float anchorLeft = cardMargin + cardViewWidth;
//初始状态 position=0.0,viewIndex = 1
//向左滑动
if (position > -1 && position < 0) {
//0 ~ anchorLeft
view.setTranslationX(-position * anchorLeft);
float scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale;
// view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
view.setPivotX(0);
view.setTranslationZ(position);
}
//变为左页(相对于起始位置)
if (position == -1) {
view.setTranslationX(anchorLeft);
}
float anchorRight = -(cardMargin + cardViewWidth);
//向右滑动
if (position < 1 && position > 0) {
//0~anchorRight
view.setTranslationX(position * anchorRight);
float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale;
// view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
view.setPivotX(pageWidth);
view.setTranslationZ(-position);
}
//变为右页(相对于起始位置)
if (position == 1) {
view.setTranslationX(anchorRight);
}
}
private void transformRightPage(View view, float position, float cardMargin, int cardViewWidth, int pageWidth) {
if (isOutLimit(1, position)) {
return;
}
// Log.i("YinTest_", "右页 position=" + position + ",cardMargin = " + cardMargin);
//初始状态 position=1.0,viewIndex = 2
float anchorRight = -(cardMargin + cardViewWidth);//右页右边的锚点
view.setTranslationZ(-position);
view.setPivotX(0);
float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale;
//view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
if (position == 1) {
//初始状态
view.setTranslationX(anchorRight);
}
//向左滑动
if (position < 1 && position > 0) {
//anchorRight ~ 0
view.setTranslationX((position) * anchorRight);
}
//变为当左页(相对于起始位置)
if (position == 0) {
view.setTranslationX(0);
}
//向右滑动
if (position > 1 && position < 2) {
// anchorRight ~ -pageWidth*2
view.setTranslationX((2-position)*anchorRight + (2*position-2) * -pageWidth);
}
//变为右页(相对于起始位置)
if (position == 2) {
view.setTranslationX(-pageWidth*2);
}
}
private void transformMostRightPage(View view, float position, float cardMargin, int cardViewWidth, int pageWidth) {
if (isOutLimit(2, position)) {
return;
}
float startPosition = -pageWidth * 2;
// Log.i("YinTest_", "最右页 position=" + position + ",cardMargin = " + cardMargin);
//初始状态 position=2.0
float anchorRight = -(cardMargin + cardViewWidth);//右页右边的锚点
view.setTranslationZ(-position);
view.setPivotX(0);
float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale;
//view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
//初始状态position=-2.0
if (position == 2) {
view.setTranslationX(startPosition);
}
//向左滑动 2~1
if (position < 2 && position > 1) {
//逆滑动 startPosition ~ anchorRight
// Log.i("YinTest_", " 最右页 向左滑动 position=" + position + ",translationX = " + (-position - 1));
float translationX = (position - 1) * startPosition - (position - 2) * anchorRight;
view.setTranslationX(translationX);
}
//变为左页(相对于起始位置)
if (position == 1) {
view.setTranslationX(anchorRight);
}
//向右滑动
if (position > 2 && position < 3) {
//startPosition~anchorLeft 保持其实际位置不变,不影响其他页面翻转
// Log.i("YinTest_", " 最左页 向左滑动 position=" + position + ",translationX = " + (-position - 1));
view.setTranslationX(startPosition - (position - 2) * pageWidth);
}
//变为右页(相对于起始位置)
if (position == 3) {
//向右滑动保持不变,但变为右页后跳转到正常显示位置
view.setTranslationX(0);
}
}
public void setCurrentPageIndex(int index) {
int currentPageIndex = index % dataSize;
this.leftMostPageIndex = checkIndex(currentPageIndex, -2);
this.leftPageIndex = checkIndex(currentPageIndex, -1);
this.currentPageIndex = currentPageIndex;
this.rightPageIndex = checkIndex(currentPageIndex, 1);
this.rightMostPageIndex = checkIndex(currentPageIndex, 2);
// Log.i("YinTest_", "setCurrentPageIndex " + leftMostPageIndex+"," + leftPageIndex+"," + currentPageIndex+"," + rightPageIndex+"," + rightMostPageIndex);
}
public int checkIndex(int index, int offset) {
if ((index + offset) < 0) {
return dataSize + index + offset;
} else if ((index + offset) >= dataSize) {
return index + offset - dataSize;
} else {
return index + offset;
}
}
}
完整Demo:
https://download.csdn.net/download/y280903468/89871333