当前位置: 首页 > article >正文

Android实现ViewPager剧中放大效果

效果图

实现方式核心思想是自定义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


http://www.kler.cn/news/342125.html

相关文章:

  • QA对(question-answer pair)、知识库alpha(混合检索策略)、以及知识库kms(召回分值阈值)
  • springboot如何集成mybatis?
  • 喜讯!迈威通信TSN产品通过“时间敏感网络(TSN)产业链名录计划”评测,各项指标名列前茅
  • 使用vscode调试wails项目(golang桌面GUI)
  • Python+PyCharm安装和配置(详细步骤)
  • 【C++】map详解(键值对的概念,与multimap的不同)
  • awk脚本和python脚本版本
  • 打破常规,BD仓储物流的效能提升!
  • python xml的读取和写入
  • 【C++网络编程】(一)Linux平台下TCP客户/服务端程序
  • 学习小课堂
  • ssm基于Javaee的影视创作论坛的设计与实现
  • SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
  • 网络风暴产生原因、危害、预防和解决方法
  • 【书生浦语实战】茴香豆企业级知识库问答工具-搭建Dify问答助手
  • k8s 1.28.2 集群部署 MinIO 分布式存储
  • 路径跟踪之导航向量场——二维导航向量场
  • 实景三维赋能地下管线综合智管应用
  • 构建宠物咖啡馆:SpringBoot框架的实现策略
  • 导师面试题库