关于安卓viewpager实现堆叠卡片交互

news/2024/11/30 3:36:55/

背景

长江后浪推前浪,无聊的需求一浪接一浪。
最近做到一个关于卡片堆叠的需求,觉得挺有意思,所以特此记录一下。

文末将附上源码链接

首先看设计图:
在这里插入图片描述
可以看到,是一个卡片堆叠的效果,关于这种UI的实现,方法有很多,例如用recyclerview,viewpager,甚至说自定义view都可以实现,本文将讲述如何使用viewpager实现这种效果。

开发环境

win10
jdk 8
as 4+

实现效果

在这里插入图片描述
由于是demo的演示,所以就不用过多在意颜色,基础功能实现即可。

问题

1、如何修改viewpager的一个卡片堆叠位置
2、如何在滑动的过程中,动态去修改卡片的宽高

思路

对于viewpager中,有个ViewPager.PageTransformer的属性,这个属性是用来干嘛的?
看一下源码的描述:

    /*** A PageTransformer is invoked whenever a visible/attached page is scrolled.* This offers an opportunity for the application to apply a custom transformation* to the page views using animation properties.** <p>As property animation is only supported as of Android 3.0 and forward,* setting a PageTransformer on a ViewPager on earlier platform versions will* be ignored.</p>*/public interface PageTransformer {/*** Apply a property transformation to the given page.** @param page Apply the transformation to this page* @param position Position of page relative to the current front-and-center*                 position of the pager. 0 is front and center. 1 is one full*                 page position to the right, and -1 is one page position to the left.*/void transformPage(@NonNull View page, float position);}

简单来讲,就是控制页面的进出场的,简单的你可以用该类实现一些viewpager页面切换进出场的效果,复杂一点的,可以动态计算viewpager滑动过程中,相关view的一个控件属性,等等。

通过继承方式,继承PageTransformer实现一个子类,重写其中的
void transformPage(@NonNull View page, float position);方法。
该方法中,第一个参数就是滑动中的view对象。第二参数,就是view的相对滑动位置。这里要注意,不是view在viewpager中的位置,仅仅是一个滑动位置,简单粗暴地可以理解为是
“负右正左零中间”。当position为0的时候,就是当前显示view,同样地-1,就是0的左边,1就是0的右边。如下图
在这里插入图片描述
这里的0,就是相对于position等于0的情况。

以上就是关于transformPage方法中,参数回调情况的描述。

---------------------------------分割线-------------------------------------

既然有了view对象,有了position左右滑动的回调,那么,就可以做很多事情了。首先position的数值,是受viewpager左右滑动影响,右滑为负数,左滑为正数。这个时候,可以根据左右滑动,做一些控件大小的转换!
注意,在数据处理的过程中,position的正负值影响。

实现

1、实现viewpager的卡片堆叠
通过setTranslationX,可以设置view的x位置!
通过LayoutParams,可以设置view的右侧边距!


设想一下,通过setTranslationX设置一个负值,是不是可以吧viewpager第二个位置的view直接放到第一个view的位置?只不过说,放完以后还是会被第一个view遮挡,导致看不到而已如此类推,就完成了一个viewpager中,view的位置摆放了。


再到LayoutParams,那不是送分题?根据position直接设置右边距,那不就得了吗?


说到这里,相信大部分人都已经懂了。
不懂的也没有关系,可以看下下面的代码:

@Overridepublic void transformPage(@NonNull View view, float position) {int pagerWidth = boundViewPager.getWidth();LogUtil.d("transformPage tag: " + view.hashCode() + " pos: " + position + " pagerWidth: " + pagerWidth);float scaleWidth = pagerWidth * CENTER_PAGE_SCALE;float widthInterval = (pagerWidth - scaleWidth) / 2;view.setScaleX(CENTER_PAGE_SCALE);view.setScaleY(CENTER_PAGE_SCALE);//设置间距----------------------------------------------------------------------ViewGroup llRoot = view.findViewById(R.id.llRoot);if (llRoot != null) {ViewGroup.LayoutParams layoutParams = llRoot.getLayoutParams();if (layoutParams instanceof RelativeLayout.LayoutParams) {((RelativeLayout.LayoutParams) layoutParams).setMarginEnd((int) ((2 - Math.abs(position)) * endInterval));((RelativeLayout.LayoutParams) layoutParams).topMargin = (int) (Math.abs(position) * verticalInterval);((RelativeLayout.LayoutParams) layoutParams).bottomMargin = (int) (Math.abs(position) * verticalInterval);llRoot.setLayoutParams(layoutParams);} else if (layoutParams instanceof CardView.LayoutParams) {((FrameLayout.LayoutParams) layoutParams).setMarginEnd((int) ((2 - Math.abs(position)) * endInterval));((FrameLayout.LayoutParams) layoutParams).topMargin = (int) (Math.abs(position) * verticalInterval);((FrameLayout.LayoutParams) layoutParams).bottomMargin = (int) (Math.abs(position) * verticalInterval);llRoot.setLayoutParams(layoutParams);}}//设置偏移量----------------------------------------------------------------------if (position >= 0) {view.setTranslationX(-pagerWidth * position);}if (position > -1 && position < 0) {view.setAlpha((position * position * position + 1));} else if (position > offscreenPageLimit - 1) {view.setAlpha((float) (1 - position + Math.floor(position)));} else {view.setAlpha(1);}}
}

简洁明了,两个方法,即可实现。
好了,实现了交互,那么,还有一个“无限循环”的问题!
方案无非是两种,一种是adapter getCount设置为无限大,一种是通过前后补数据给用户做一个视觉差。但是具体到我们这里的实现,明显是第一种方法比较合适。这里也不过多叙述了。


最后,源码地址:代码地址
搜索VPTestActivity类

that’s all--------------------------------------------------------------------------------------------------


http://www.ppmy.cn/news/183461.html

相关文章

美图秀秀自建贴纸手机存储

此电脑\realme X2 Pro\内部共享存储空间\Android\data\com.mt.mtxx.mtxx\files\material\1012 在这个地址下的各个文件夹中&#xff0c;以png形式保存

~109美图手机官网移动端

1、主页 2、less 3、效果 到达断点后&#xff1a;

美图秀秀怎么去水印-美图秀秀怎么去水印图片教程

一.美图秀秀 有很多小伙伴在需要编辑图片的时候&#xff0c;都会通过美图秀秀来帮我们美化&#xff0c;但是大家知道吗&#xff0c;如果我们想要去掉图片上的水印时&#xff0c;我们就可以通过美图秀秀来帮我们完成这样的操作。 ​消除笔 我们可以将需要去水印的图片添加到网…

值得收藏 | 脑机交互作用研究

神经损伤和疾病对许多人的生活产生了巨大的影响&#xff0c;导致了许多运动障碍和日常任务无法独立完成。皮质假体系统通过脑机接口&#xff08;BCI&#xff09;接收一个动作命令来执行所需的位置&#xff0c;从而使得经历神经损伤的人能够实现部分功能恢复。BCI技术可以在侵入…

管家婆服务器备份在哪个文件夹,管家婆财务软件备份以及恢复方法

管家婆财务软件备份以及恢复方法 管家婆软件安装好之后一般默认为每天自动备份一次&#xff0c;自动备份周期在软件的系统配置里修改。如果重装系统或者防止数据丢失&#xff0c;可以自己手动备份。下面是yjbys小编为大家带来的关于管家婆财务软件备份以及恢复方法的知识&#…