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

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

背景

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

文末将附上源码链接

首先看设计图:
在这里插入图片描述
可以看到,是一个卡片堆叠的效果,关于这种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直接设置右边距,那不就得了吗?


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


    @Override
    public 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--------------------------------------------------------------------------------------------------

目录
相关文章
|
7月前
|
安全 API Android开发
Android网络和数据交互: 解释Retrofit库的作用。
Android网络和数据交互: 解释Retrofit库的作用。
75 0
|
2月前
|
Java Linux Android开发
移动应用开发与操作系统的交互:深入理解Android和iOS
在数字时代,移动应用成为我们日常生活的一部分。本文将深入探讨移动应用开发的核心概念、移动操作系统的工作原理以及它们如何相互作用。我们将通过实际代码示例,展示如何在Android和iOS平台上创建一个简单的“Hello World”应用,并解释其背后的技术原理。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和知识。
|
6月前
|
Android开发 容器
35. 【Android教程】视频页面:ViewPager
35. 【Android教程】视频页面:ViewPager
64 3
|
7月前
|
JSON Android开发 数据格式
android与Web服务器交互时的cookie使用-兼谈大众点评数据获得(原创)
android与Web服务器交互时的cookie使用-兼谈大众点评数据获得(原创)
95 2
|
4月前
|
XML Android开发 UED
"掌握安卓开发新境界:深度解析AndroidManifest.xml中的Intent-filter配置,让你的App轻松响应scheme_url,开启无限交互可能!"
【8月更文挑战第2天】在安卓开发中,scheme_url 通过在`AndroidManifest.xml`中配置`Intent-filter`,使应用能响应特定URL启动或执行操作。基本配置下,应用可通过定义特定URL模式的`Intent-filter`响应相应链接。
125 12
|
4月前
|
Android开发
Android使用ViewPager做无限轮播,人为滑动时停止
Android使用ViewPager做无限轮播,人为滑动时停止
94 2
|
4月前
|
JSON Android开发 数据格式
Android项目架构设计问题之实现交互响应的结构化处理如何解决
Android项目架构设计问题之实现交互响应的结构化处理如何解决
21 0
|
6月前
|
JavaScript 前端开发 Android开发
kotlin安卓在Jetpack Compose 框架下使用webview , 网页中的JavaScript代码如何与native交互
在Jetpack Compose中使用Kotlin创建Webview组件,设置JavaScript交互:`@Composable`函数`ComposableWebView`加载网页并启用JavaScript。通过`addJavascriptInterface`添加`WebAppInterface`类,允许JavaScript调用Android方法如播放音频。当页面加载完成时,执行`onWebViewReady`回调。
|
7月前
|
安全 物联网 测试技术
构建未来:Android与IoT设备的无缝交互深入探索软件自动化测试的未来趋势
【5月更文挑战第30天】在物联网(IoT)技术快速发展的当下,Android系统因其开放性和广泛的用户基础成为了连接智能设备的首选平台。本文将探讨如何通过现代Android开发技术实现智能手机与IoT设备的高效、稳定连接,并分析其中的挑战和解决方案。我们将深入挖掘Android系统的底层通信机制,提出创新的交互模式,并通过实例演示如何在Android应用中集成IoT控制功能,旨在为开发者提供一套可行的指导方案,促进IoT生态系统的进一步发展。
|
7月前
|
Android开发
Android使用ViewPager实现图片轮播系列之三:手动滑动 + 左右箭头(1)
Android使用ViewPager实现图片轮播系列之三:手动滑动 + 左右箭头(1)