本文已授权微信公众号:鸿洋hongyangAndroid)在微信公众号平台原创首发。

网上有很多关于使用Gallery来打造3D画廊的博客,但是在关于Gallery的官方说法中表明:

This class was deprecated in API level 16.
This widget is no longer supported. Other horizontally scrolling widgets include HorizontalScrollView and ViewPager from the support library.(来自:https://developer.android.com/reference/android/widget/Gallery.html)

于是我就在想,既然如此,那就用ViewPager来写一个吧,于是就有了这篇博客!

进入正题:

要实现如下图的功能,需要以下几点:

  1.   使用ViewPager
  2. 设置PageTransformer
  3. 获取图片倒影

一、ViewPager的使用

ViewPager是来自android.support.v4的API

来自官方的介绍:

  Layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows.

  渣翻:ViewPager是一种允许用户左右翻动页面浏览数据的布局管理器,通过应用一个实现了PagerAdapter的实现类来生成展示页面。(翻译渣,有错请提醒,谢谢)

通过上面的解释可以知道,对于ViewPager的使用,和ListView类似,也是需要Adapter来管理每个ITEM的。

让我们来了解一下PagerAdapter的使用

要实现PagerAdapter,必须至少实现以下四个方法:

  (1)public int getCount()

  (2)public Object instantiateItem(ViewGroup container, int position)

  (3)public void destroyItem(ViewGroup container, int position, Object object)

  (4)public boolean isViewFromObject(View view, Object object)

 

方法解释: 

  第一个方法就不用说了,实现过BaseAdapter的童鞋应该知道的,就是用来放回当前List中的Page数量的。

 

  (2)public Object instantiateItem(ViewGroup container, int position)

  先从第二个方法说起,这个方法是负责向ViewGroup也就是ViewPager中添加新的页面,并返回一个继承自Object的key,这个key将会在第三个方法destroyItem和第四个方法isViewFromObject中作为参数调用。

  代码可以写成这样:

  

  1. @Override
  2. public Object instantiateItem(ViewGroup container, int position) {
  3. ImageView imageView=imageViewList.get(position);
  4. container.addView(imageView,position);
  5. return imageView;
  6. }

  (3)public void destroyItem(ViewGroup container, int position, Object object)

  该方法负责从ViewGroup中移除对应position中的page

  代码:

 

  1. @Override
  2. public void destroyItem(ViewGroup container, int position, Object object) {
  3. container.removeView(imageViewList.get(position));
  4. }

  (4)public boolean isViewFromObject(View view, Object object)

  确定instantiateItem返回的特定key 对象是否与page View有关联。由于instantiateItem中可以以自身page为key返回,所以在这里就可以这样写:

  1. @Override
  2. public boolean isViewFromObject(View view, Object object) {
  3. return view==object;
  4. }

ViewPager作为布局管理器,非常强大,也可以用来展示Fragment,当然adapter需要使用FragmentPagerAdapter或者FragmentStatePagerAdapter

二、设置PageTransformer

  PageTransformer是ViewPager的一个公共成员接口,用于设置当一个页面滑入和滑出的过度特效,当然,由于是通过属性动画来设置的,所以设置的pagetransformer在Android3.0以下会被忽略。

关于实现该接口,只需要实现一个方法即可:

  public void transformPage(View page, float position);


对于参数position,需要好好说明一下:

position的取值有如下说明:

position是指的是页面相对于中间页面的位置参数,根据位置不同,0的时候在中间最前面,1的时候页面完全在右边,-1的时候页面完全在左边。如下图所示:

关于该接口的更多知识可以看鸿洋大大的这篇博客:http://blog.csdn.net/lmj623565791/article/details/40411921/

那么要实现上面的效果要怎么做呢?

代码如下:

MyTransformation.java

  1. public class MyTransformation implements ViewPager.PageTransformer {
  2.  
  3. private static final float MIN_SCALE=0.85f;
  4. private static final float MIN_ALPHA=0.5f;
  5. private static final float MAX_ROTATE=30;
  6. private Camera camera=new Camera();
  7. @Override
  8. public void transformPage(View page, float position) {float scaleFactor=Math.max(MIN_SCALE,1-Math.abs(position));
  9. float rotate=20*Math.abs(position);
  10. if (position<-1){
  11.  
  12. }else if (position<0){
  13. page.setScaleX(scaleFactor);
  14. page.setScaleY(scaleFactor);
  15. page.setRotationY(rotate);
  16. }else if (position>=0&&position<1){
  17. page.setScaleX(scaleFactor);
  18. page.setScaleY(scaleFactor);
  19. page.setRotationY(-rotate);
  20. }
  21. else if (position>=1) {
  22. page.setScaleX(scaleFactor);
  23. page.setScaleY(scaleFactor);
  24. page.setRotationY(-rotate);
  25. }
  26. }
  27. }

然后,

  1. viewPager.setPageTransformer(true,new MyTransformation());

效果如下:

诶,和前面给出的效果图不一样啊,为什么呢?一开始我也不明白,后来在网上查阅资料,找到了如下方法:

  (1)为解决不在ViewPager中间页面被剪掉的问题:

  需要在ViewPager和其父容器中设置clipChildren为false

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. xmlns:tools="http://schemas.android.com/tools"
  6. android:orientation="vertical"
  7. android:id="@+id/activity_main"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:clipChildren="false"
  11. android:layerType="software"
  12. android:background="@android:color/black"
  13. tools:context="com.example.evanzeng.viewpagertest.MainActivity">
  14.  
  15. <TextView
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:text="Hello World!"/>
  19. <android.support.v4.view.ViewPager
  20. android:id="@+id/viewPager"
  21. android:layout_width="wrap_content"
  22. android:layout_height="400dp"
  23. android:layout_gravity="center"
  24. android:clipChildren="false"
  25. >
  26. </android.support.v4.view.ViewPager>
  27. </LinearLayout>

  (2)为解决触摸滑动ViewPager左右两边的页面无反应的问题:

  需要为ViewPager的父容器设置OnTouchListener,将触摸事件传递给ViewPager

  1. findViewById(R.id.activity_main).setOnTouchListener(new View.OnTouchListener() {
  2. @Override
  3. public boolean onTouch(View view, MotionEvent motionEvent) {
  4. return viewPager.dispatchTouchEvent(motionEvent);
  5. }
  6. });

效果如下:

三、获取图片倒影

代码如下:

  1. public class ImageUtil {
  2. public static Bitmap getReverseBitmapById(int resId, Context context){
  3. Bitmap sourceBitmap= BitmapFactory.decodeResource(context.getResources(),resId);
  4. Matrix matrix=new Matrix();
  5. matrix.setScale(1,-1);
  6. Bitmap inverseBitmap=Bitmap.createBitmap(sourceBitmap,0,sourceBitmap.getHeight()/2,sourceBitmap.getWidth(),sourceBitmap.getHeight()/3,matrix,false);
  7. Bitmap groupbBitmap=Bitmap.createBitmap(sourceBitmap.getWidth(),sourceBitmap.getHeight()+sourceBitmap.getHeight()/3+60,sourceBitmap.getConfig());
  8. Canvas gCanvas=new Canvas(groupbBitmap);
  9. gCanvas.drawBitmap(sourceBitmap,0,0,null);
  10. gCanvas.drawBitmap(inverseBitmap,0,sourceBitmap.getHeight()+50,null);
  11. Paint paint=new Paint();
  12. Shader.TileMode tileMode= Shader.TileMode.CLAMP;
  13. LinearGradient shader=new LinearGradient(0,sourceBitmap.getHeight()+50,0,
  14. groupbBitmap.getHeight(), Color.BLACK,Color.TRANSPARENT,tileMode);
  15. paint.setShader(shader);
  16. paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
  17. gCanvas.drawRect(0,sourceBitmap.getHeight()+50,sourceBitmap.getWidth(),groupbBitmap.getHeight(),paint);
  18. return groupbBitmap;
  19. }
  20. }

参考自http://blog.csdn.net/lovoo/article/details/51591580

最终效果:

以上代码已上传自GITHUB,地址如下:https://github.com/liberty2015/3DViewPagerGallery

如果您觉得不错的话就点个赞收藏一下,谢谢!

Android ViewPager打造3D画廊的更多相关文章

  1. Android ViewPager 打造炫酷欢迎页

    Android ViewPager 打造炫酷欢迎页 ViewPager是Android扩展v4包中的类,这个类可以让用户切换当前的View.对于这个类的应用场景,稍加修改就可以应用到多个环境下.比如: ...

  2. Android自己定义控件——3D画廊和图像矩阵

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/39932689 1.3D画廊的实现 我们知道android系统已经为我们提供好了一个 ...

  3. Android ViewPager用法小结

    android-support-v4.jar 是谷歌提供给我们的一个兼容低版本号安卓设备的软件包.里面包囊了仅仅有在 Android 3.0 以上可用的API.而 ViewPager 就是当中之中的一 ...

  4. Android ViewPager使用方法小结

    android-support-v4.jar 是谷歌提供给我们的一个兼容低版本安卓设备的软件包,里面包囊了只有在 Android 3.0 以上可用的API.而 ViewPager 就是其中之一.利用它 ...

  5. 3D画廊

    3D画廊 之前我都是写的学习的内容,我在写这些教程时遇到有趣的炫酷的小例子也会专门拿出来写一篇文章,今天就写一个酷炫的小例子,叫3D画廊,它是属于ViewPage的进阶版. 此项目下载地点:https ...

  6. 巧用ViewPager 打造不一样的广告轮播切换效果

    一.概述 如果大家关注了我的微信公众号的话,一定知道我在5月6号的时候推送了一篇文章,文章名为Android超高仿QQ附近的人搜索展示(一),通过该文可以利用ViewPager实现单页显示多个Item ...

  7. Android ViewPager 用法

    Android ViewPager 用法 场景:一般第一次打开应用程序时,程序会有一个提示页来给展现应用程序都有哪些功能:或者程序更新时,又更新哪些新特性,都可以使用ViewPager Demo 描述 ...

  8. Android ViewPager再探:增加滑动指示条

    上一篇:<Android ViewPager初探:让页面滑动起来> ViewPager只是左右滑动有些丑,也不知道当前位于第几页面. 可以在上方加入滑动指示条,来确定当前位置. 只需要修改 ...

  9. Android ViewPager初探:让页面滑动起来

    下一篇:<Android ViewPager再探:增加滑动指示条> ViewPager需要用到适配器PagerAAdapter,以下四个函数需要重写: instantiateItem(Vi ...

随机推荐

  1. UWP中新加的数据绑定方式x:Bind分析总结

    UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...

  2. KMP算法求解

    // KMP.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using namespac ...

  3. Java中的多态

    1.多态:具有表现多种形态的能力的特征 父类: public abstract class Animal {public abstract void Say();} 子类: public class ...

  4. C# Excel导入、导出【源码下载】

    本篇主要介绍C#的Excel导入.导出. 目录 1. 介绍:描述第三方类库NPOI以及Excel结构 2. Excel导入:介绍C#如何调用NPOI进行Excel导入,包含:流程图.NOPI以及C#代 ...

  5. JAVA问题集锦Ⅰ

    1.Java的日期添加: import java.util.Date ; date=new date();//取时间 Calendar calendar = new GregorianCalendar ...

  6. 关于VS2015 ASP.NET MVC添加控制器的时候报错

    调试环境:VS2015 数据库Mysql  WIN10 在调试过程中出现类似下两图的同学们,注意啦. 其实也是在学习的过程中遇到这个问题的,找了很多资料都没有正面的解决添加控制器的时候报错的问题,还是 ...

  7. How those spring enable annotations work--转

    原文地址:http://blog.fawnanddoug.com/2012/08/how-those-spring-enable-annotations-work.html Spring's Java ...

  8. App 审核由于 IPv6 网络问题被拒

    昨天 提交App Store 的时候被拒了 We discovered one or more bugs in your app when reviewed on iPhone running iOS ...

  9. openresty 前端开发入门五之Mysql篇

    openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...

  10. 企业shell面试题:获取51CTO博客列表倒序排序考试题

    #!/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin HTMLFILE=/home/oldboy/ht ...