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的边距,左右各10dpviewPageMarginHorizontal = Utils.dp2Px(mContext, viewPageMarginHorizontal);screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;}@Overridepublic 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.0if (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 = 0float 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 == -1view.setTranslationX(anchorLeft);}if (position < -1 && position > -2) {//向左滑动 anchorLeft ~ pageWidth*2view.setTranslationX((position+2)*anchorLeft + (-2*position-2) * pageWidth);}//向右滑动if (position > -1 && position < 0) {//anchorLeft ~ 0view.setTranslationX((-position) * anchorLeft);}//变为左页(相对于起始位置)if (position == -2) {view.setTranslationX(pageWidth*2);}//变为右叶(相对于起始位置)if (position == 0) {//左页变为当前页 position =0.0view.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 ~ anchorLeftview.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~anchorRightview.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 = 2float 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 ~ 0view.setTranslationX((position) * anchorRight);}//变为当左页(相对于起始位置)if (position == 0) {view.setTranslationX(0);}//向右滑动if (position > 1 && position < 2) {// anchorRight ~ -pageWidth*2view.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.0float anchorRight = -(cardMargin + cardViewWidth);//右页右边的锚点view.setTranslationZ(-position);view.setPivotX(0);float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale;//view.setScaleX(scaleFactor);view.setScaleY(scaleFactor);//初始状态position=-2.0if (position == 2) {view.setTranslationX(startPosition);}//向左滑动 2~1if (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.xdnf.cn/news/1560042.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【element-tiptap】如何引进系统中的字体?

源码地址&#xff1a; https://github.com/Leecason/element-tiptap 源码中给出的字体如下 可以看到&#xff0c;咱们日常需要的黑体、微软雅黑等都没有&#xff0c;所以这篇文章来探索一下怎么加字体。 另外呢&#xff0c;肯定有小伙伴发现&#xff0c;这个按钮点击的时候&am…

NVM下载、安装、配置

一、下载 nvm在win系统下载链接 https://github.com/coreybutler/nvm-windows/releases zip版本已上传到资源文件中&#xff0c;链接 https://download.csdn.net/download/m0_46613429/89870864 二、安装 1、双击exe文件 2、选择 accept 3、选择nvm安装位置 4、选择nodejs安…

无线费控智能水表:智能生活的守护者

在当今智能化日益普及的时代&#xff0c;无线费控智能水表作为一项重要的技术创新&#xff0c;正在逐步改变我们的生活方式。它不仅能够实现远程抄表&#xff0c;自动计费&#xff0c;还能有效监控用水情况&#xff0c;促进水资源的合理利用&#xff0c;是现代城市智慧化管理不…

骨传导耳机哪个牌子最好?五大爆品骨传导耳机全维度拆解推荐!

随着科技的不断进步&#xff0c;消费者对电子产品的需求也在日益增长&#xff0c;特别是在音频领域&#xff0c;骨传导耳机作为一项革新性的技术&#xff0c;正逐渐成为市场的新宠。不同于传统的空气传导耳机&#xff0c;骨传导耳机通过振动颅骨直接将声音传递至内耳&#xff0…

LINUX 系统管理操作

基础编辑 Tab 单击一次补全 双击列举候选 CTRL U 删除光标前 K 删除光标后 L 清屏&#xff08;只剩新命令行&#xff09; C 取消当前操作 反斜杠“\” 在需要转行的时候输入反斜杠 “\”回车 在>后继续输入 帮助命令 help 命令 大部分内建命令 格式&#xff1a;h…

目标检测中的损失函数

损失函数是用来衡量模型与数据的匹配程度的&#xff0c;也是模型权重更新的基础。计算损失产生模型权重的梯度&#xff0c;随后通过反向传播算法&#xff0c;模型权重得以更新进而更好地适应数据。一般情况下&#xff0c;目标损失函数包含两部分损失&#xff0c;一个是目标框分…

一个月学会Java 第9天 构造器与访问修饰符

Day9 构造器与访问修饰符 本来其实是想在Day8里面把这个构造器给讲掉的&#xff0c;但是发现篇幅有点长的&#xff0c;后面的内容也是稍微有一点点超纲了&#xff0c;所以就先把这个留着&#xff0c;现在再讲。 第一章 构造器 构造器&#xff0c;我们之前在讲类的时候其实是说过…

代码随想录 (三)—— 哈希表部分刷题

当我们想使用哈希法来解决问题的时候&#xff0c;我们一般会选择如下三种数据结构。 数组set &#xff08;集合&#xff09;map(映射) 在java中有就是&#xff0c;hashmap, LinkedHashMap, TreeMap &#xff0c;HashTable 等 总结一下&#xff0c;当我们遇到了要快速判断一个…

系统开发基础错题解析二【软考】

目录 前言1.人机界面设计2.架构设计2.1管道过滤器体系2.2仓库风格 3.软件测试相关概念4.白盒测试用例4.14.2 5.测试分类与阶段任务划分6.软件维护类型7.软件质量保证8.软件过程改进 前言 本文专门用来记录本人在做软考中有关系统开发基础的错题&#xff0c;我始终认为教学相长…

利用特征点采样一致性改进icp算法点云配准方法

1、index、vector 2、kdtree和kdtreeflann 3、if kdtree.radiusSearch(。。。) > 0)

平板外壳高精度标签粘贴应用

电子平板、手机等产品的外壳的上常会贴有各式各样的标签&#xff0c;这是电子设备制造业中不可或缺的环节&#xff0c;它不仅关乎产品信息的准确传达&#xff0c;还承载着品牌宣传、防伪追溯等多重功能。通过贴标&#xff0c;设备制造商能够清晰地标注设备的型号、序列号、生产…

通过AI技术克服自动化测试难点(上)

本文我们一起分析一下AI技术如何解决现有的自动化测试工具的不足和我们衍生出来的新的测试需求。 首先我们一起看一下计算机视觉的发展历史&#xff0c;在上世纪70年代&#xff0c;处于技术萌芽期&#xff0c;由字符的识别技术慢慢进行演化&#xff0c;发展到现在&#xff0c;人…

Microbiome | 嫁接植物微生态大揭秘:抗病研究的新思路

在现代农业中&#xff0c;嫁接技术作为一种有效的植物改良方法&#xff0c;已被广泛应用于瓜果种植。然而&#xff0c;嫁接技术背后的微生物学奥秘却鲜为人知。今天&#xff0c;我们将通过一篇《Microbiome》的文章带您深入探讨嫁接西瓜的根际微生物群&#xff0c;了解它们如何…

DMA 详解

目录 一、简介二、STM32 中的 DMA1、DMA 框图1.1 传输方式1.2 仲裁器1.3 数据流1.4 指针递增模式1.5 存储器到存储器模式1.6 DMA 中断 2、DMA 配置 一、简介 DMA&#xff08;Direct Memory Access&#xff0c;直接存储器访问&#xff09;顾名思义&#xff0c;就是绕开 CPU 直接…

美国1米DEM地形瓦片数据免费分享(4)-新泽西州

一、简要介绍 新泽西州(英语:State of New Jersey)位于美国中大西洋地区&#xff0c;其命名源自位于英吉利海峡中的泽西岛&#xff0c;昵称为“花园州”。新泽西州亦为美国东部的一个州&#xff0c;北接纽约州&#xff0c;东面大西洋&#xff0c;南向特拉华州&#xff0c;西临…

OpenEBS 实现 PV 动态持久化存储安装

什么是 OpenEBS OpenEBS 将 Kubernetes 工作节点可用的任何存储转换为本地或复制的 Kubernetes 持久卷。OpenEBS 可帮助应用程序和平台团队轻松部署需要快速、高持久性、可靠且可扩展的容器原生存储的Kubernetes 有状态工作负载。 安装OpenEBS 1.所有节点安装iSCSI启动器 yu…

生成式专题的第二节课--DCGAN

一、DCGAN基础概念 DCGAN&#xff08;Deep Convolutional Generative Adversarial Network&#xff0c;即深度卷积生成对抗网络&#xff09;&#xff0c;于2016年提出&#xff0c;是一种深度学习模型&#xff0c;是生成对抗网络&#xff08;GAN&#xff09;的一种变体&#xf…

HarmonyOS NEXT应用元服务开发按钮标注场景

对于用户可点击等操作的任何按钮&#xff0c;如果不是文本类控件&#xff0c;则须通过给出标注信息&#xff0c;包括用户自定义的控件中的虚拟按钮区域&#xff0c;否则可能会导致屏幕朗读用户无法完成对应的功能。 此类控件在进行标注时&#xff0c;标注文本不要包含控件类型、…

干部管理系统:全面提升干部管理效能

数字化浪潮下&#xff0c;干部管理系统作为管理利器&#xff0c;日益凸显其核心价值。该系统全面实现干部信息的数据化&#xff0c;涵盖从基础档案到教育、工作、培训及考核等全方位细节&#xff0c;信息详尽且条理清晰。这不仅极大提升了干部信息查询与更新的效率&#xff0c;…

商标恶意维权形式及应对策略

在商业领域&#xff0c;商标恶意维权的现象时有出现&#xff0c;给正常的市场秩序和企业经营带来了不良影响。以下将介绍其常见形式及应对方法。 一、商标恶意维权的形式1、囤积商标后恶意诉讼。一些人或企业大量注册与知名品牌相似或具有一定通用性的商标&#xff0c;并非用于…