3D画廊

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

此项目下载地点:https://github.com/qySvip/3D-gallery

下面的指示器是使用的一大神的第三方库,会在文章下方简单讲述一下。

效果图

3D画廊的实现

首先是布局文件

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clipChildren="false"
android:background="@android:color/black"
android:id="@+id/frame_layout"> <android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_gravity="center"
android:id="@+id/gallery"
android:clipChildren="false"
android:layout_marginLeft="85dp"
android:layout_marginRight="85dp" /> <com.lwj.widget.viewpagerindicator.ViewPagerIndicator
android:id="@+id/indicator_circle_line"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:background="#efefef"
app:vpi_default_color="#FF239AF5"
app:vpi_distance="60dp"
app:vpi_distanceType="BY_LAYOUT"
app:vpi_indicatorType="CIRCLE_LINE"
app:vpi_radius="10dp"
app:vpi_selected_color="#FF239AF5"
/> </FrameLayout>

代码中的ViewPagerIndicator是用于实现下方的指示器,这个我们在最后在进行解释;

首先布局使用帧布局,内部用到ViewPager控件,注意在ViewPager控件的父布局中我们要添加android:clipChildren="false"属性,它的作用是定义它的子控件是否要在它应有的边界内进行绘制,默认值为true。我们这里要用false。

然后在ViewPager中用到android:layout_marginLeft和android:layout_marginRight属性,值不能太大,过大会导致看不到两边的图像,具体根据自己满意进行调整。高度属性为图片和倒影的加起来的高度,自己进行调整。

GalleryPageTransformer类

 package sample.sdk.qy.com.demo;

 import android.support.v4.view.ViewPager;
import android.view.View; public class GalleryPageTransformer implements ViewPager.PageTransformer {
private static final float MAX_ROTATION=20.0f;
private static final float MIN_SCALE=0.75f;
private static final float MAX_TRANSLATE=20.0f; @Override
public void transformPage(View page, float position) {
if(position<-1) {
page.setTranslationX(MAX_TRANSLATE);
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
page.setRotationY(-MAX_ROTATION);
}
else if(position<=0) {
page.setTranslationX(-MAX_TRANSLATE*position);
float scale=MIN_SCALE+(1-MIN_SCALE)*(1.0f+position);
page.setScaleX(scale);
page.setScaleY(scale);
page.setRotationY(MAX_ROTATION*position);
}
else if(position<=1) {
page.setTranslationX(-MAX_TRANSLATE*position);
float scale=MIN_SCALE+(1-MIN_SCALE)*(1.0f-position);
page.setScaleX(scale);
page.setScaleY(scale);
page.setRotationY(MAX_ROTATION*position);
}
else {
page.setTranslationX(-MAX_TRANSLATE);
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
page.setRotationY(MAX_ROTATION);
}
}
}

PageTransformer是ViewPager内部定义的接口,这个接口主要用于控制ViewPager中item view的滑动效果。

  • setTranslationX     设置view相对原始位置的水平偏移量
  • setScaleX              设置水平缩放的基准点
  • setScaleY              设置竖直缩放的基准点
  • setRotationY          设置竖直的选择的基准点

ImageUtils类

 package sample.sdk.qy.com.demo;

 import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader; public class ImageUtils {
public static Bitmap getReverseBitmapById(Context context, int resId, float percent) {
// get the source bitmap
Bitmap srcBitmap= BitmapFactory.decodeResource(context.getResources(), resId);
// get the tow third segment of the reverse bitmap
Matrix matrix=new Matrix();
matrix.setScale(1, -1);
Bitmap rvsBitmap=Bitmap.createBitmap(srcBitmap, 0, (int) (srcBitmap.getHeight()*(1-percent)),
srcBitmap.getWidth(), (int) (srcBitmap.getHeight()*percent), matrix, false);
// combine the source bitmap and the reverse bitmap
Bitmap comBitmap=Bitmap.createBitmap(srcBitmap.getWidth(),
srcBitmap.getHeight()+rvsBitmap.getHeight()+20, srcBitmap.getConfig());
Canvas gCanvas=new Canvas(comBitmap);
gCanvas.drawBitmap(srcBitmap, 0, 0, null);
gCanvas.drawBitmap(rvsBitmap, 0, srcBitmap.getHeight()+20, null);
Paint paint=new Paint();
LinearGradient shader=new LinearGradient(0, srcBitmap.getHeight()+20, 0, comBitmap.getHeight(),
Color.BLACK, Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
gCanvas.drawRect(0, srcBitmap.getHeight()+20, srcBitmap.getWidth(), comBitmap.getHeight(), paint);
return comBitmap;
}
}

这是做图片倒影的方法,内部使用了Canvas和Bitmap类,这些后面会进行讲述。

ViewAdapter类

 package sample.sdk.qy.com.demo;

 import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup; import java.util.List; public class ViewAdapter extends PagerAdapter {
private List<View> datas; public ViewAdapter(List<View> list) {
datas=list;
} @Override
public int getCount() {
return datas.size();
} @Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
} @Override
public Object instantiateItem(ViewGroup container, int position) {
View view=datas.get(position);
container.addView(view);
return view;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(datas.get(position));
}
}

适配器类,这里的适配方式为图片和倒影一同进行适配。

MainActivity类

 package sample.sdk.qy.com.demo;

 import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView; import com.lwj.widget.viewpagerindicator.ViewPagerIndicator; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List; public class MainActivity extends Activity { private List<View> pages;
private FrameLayout layout;
private ViewPager pager;
private ViewPagerIndicator mIndicatorCircleLine; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); pages=getPages();
pager=(ViewPager) findViewById(R.id.gallery);
PagerAdapter adapter=new ViewAdapter(pages);
pager.setAdapter(adapter);
pager.setPageMargin(20);
pager.setOffscreenPageLimit(3);
pager.setPageTransformer(true, new GalleryPageTransformer()); layout=(FrameLayout) findViewById(R.id.frame_layout);
layout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return pager.dispatchTouchEvent(event);
}
}); mIndicatorCircleLine = (ViewPagerIndicator) findViewById(R.id.indicator_circle_line);
mIndicatorCircleLine.setViewPager(pager,9);
} private List<View> getPages() {
List<View> pages=new ArrayList<>();
Field[] fields=R.drawable.class.getDeclaredFields();
try {
for (Field field : fields) {
if (field.getName().startsWith("page")) {
ImageView view = new ImageView(this);
view.setImageBitmap(ImageUtils.getReverseBitmapById(this, field.getInt(null), 0.5f));
pages.add(view);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return pages;
}
}

主界面方法,主要用于填充入图片、适配器适配。这里填充图片的方法为在drawable文件中查找以page开头的图片进行填充。

到这里3D画廊就完成了。。。。。。。。。

指示器

下面来说一下指示器的做法,用的是网上一大神的第三方类。

使用方法:

1、在 project的build.gradle 添加:

allprojects { repositories { ... maven { url "https://jitpack.io" } } }

2、在module的build.gradle 添加:

dependencies { implementation  'com.github.LinweiJ:ViewPagerIndicator:0.1.0' }

注意这里要用implementation,compile现在已被废弃,官方显示将在2018年年底删除。

3、将ViewPagerIndicator控件添加到布局文件。

属性:

  • app:vpi_selected_color
  • app:vpi_default_color (如果 indicatorType=CIRCLE_LINE default_color 为指示器唯一颜色 ,selected_color 不起作用)
  • app:vpi_radius (点的大小,在indicatorType= CIRCLE_LINE 的情况下 radius 是点的高)
  • app:vpi_length (只作用在 indicatorType=CIRCLE_LINE 的情况下,为 指示器点的长度)
  • app:vpi_distance (只作用在 distanceType=BY_DISTANCE 的情况下)
  • app:vpi_num
  • app:vpi_indicatorType (LINE; CIRCLE; CIRCLE_LINE; BEZIER;SPRING)LINE:线 ; CIRCLE:圆点(默认) ; CIRCLE_LINE:圆角矩形; BEZIER:弹性球 ; SPRING: 弹簧粘性球
  • app:vpi_distanceType (BY_RADIUS; BY_DISTANCE ; BY_LAYOUT )BY_RADIUS:3倍radius ; BY_DISTANCE :定义固定距离 ;BY_LAYOUT :根据layout_width均分得到距离
  • app:vpi_animation(默认为true:动画开启 ; false:关闭动画)

4、在java文件中初始化该控件

使用mIndicatorCircleLine.setViewPager(pager,9);,第一个参数为适配器,第二个参数为图片的个数。

3D画廊的更多相关文章

  1. Android ViewPager打造3D画廊

    本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发. 网上有很多关于使用Gallery来打造3D画廊的博客,但是在关于Gallery的官方说法中表明: This cl ...

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

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

  3. CSS3D写3d画廊滚动

    CSS样式表 *{ margin: 0; padding: 0; } .wrapper{ width: 800px; height: 600px; background: #87CEEB; margi ...

  4. 一款基于jQuery和CSS3炫酷3D旋转画廊特效插件

    这是一款效果炫酷的jQuery和CSS3 3D旋转画廊特效插件.该3D画廊插件可以通过前后导航按钮来切换图片,效果就像旋转木马一样.它还带有点击放大图片,显示图片标题和用键盘操作等功能. 在线预览   ...

  5. 某技术大牛的帖子(android项目总结)

    1. 一般性控件需要设置onclick事件才会有点击效果(selector). 2.  <item android:drawable=”@drawable/btn_ct_green” /> ...

  6. Android ViewPager用法小结

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

  7. 一站式学习Wireshark(转载)

    一站式学习Wireshark(一):Wireshark基本用法 2014/06/10 · IT技术 · 4 评论 · WireShark 分享到: 115 与<YII框架>不得不说的故事— ...

  8. 【每日Scrum】第五天(4.15) TD学生助手Sprint1站立会议

    TD学生助手Sprint1站立会议(4.15) 任务看板 站立会议内容 组员 昨天 今天 困难 签到 刘铸辉 (组长) 今天和静姐,娇哥把图片3D画廊效果的功能实现了,GPS功能没什么进展,所以只能继 ...

  9. 【每日Scrum】第四天(4.14) TD学生助手Sprint1站立会议

    TD学生助手Sprint1站立会议(4.14) 任务看板 站立会议内容 组员 昨天 今天 困难 签到 刘铸辉 (组长) 今天早晨静姐调整了下界面和配色,下午和宝月兄一起做了GPS功能显示,暂时只能显示 ...

随机推荐

  1. CSS中怎么设置元素水平垂直居中?

    记录怎么使用text-align与vertical-align属性设置元素在容器中垂直居中对齐.text-align与vertical-align虽然都是设置元素内部对齐方式的,但两者的用法还是有略微 ...

  2. ASP制作建议留言板

    <html>  <head>  <meta http-equiv="Content-Type" content="text/html;cha ...

  3. 微信小程序入门讲解

    微信小程序 注册 由于发文限制,请自行到微信公众平台注册 项目结构 project.config.json 配置文件(不需要动) app.json(用户配置) 路由pages window 整个程序样 ...

  4. python爬虫-MongoDB安装配置

    MongoDB安装配置: 在安装配置MongoDB的过程中遇到了很多问题,现在重新梳理一遍安装流程.遇到的问题及其解决方法 系统版本:Windows 10 MongoDB版本:4.2.1 1.下载地址 ...

  5. Go-数据类型以及变量,常量,函数,包的使用

    Go-数据类型以及变量,常量,函数,包的使用 一.数据类型 1.字符串类型 string -双引号包裹的:"xxx" -反引号包裹,可以换行, 注意: 区别于python,是没有单 ...

  6. JavaScript,ajax与springboot之间的传参方式

    Springboot:@PostMapping("/mDelTest")public String mDelTest (@RequestBody List<String> ...

  7. JS基础入门篇(十八)—日期对象

    1.日期对象 日期对象: 通过new Date()就能创建一个日期对象,这个对象中有当前系统时间的所有详细信息. 以下代码可以获取当前时间: <script> var t = new Da ...

  8. 最适合初学者的一篇 Ribbon 教程

    什么是 Ribbon Ribbon 是一个基于 HTTP 和 TCP 的 客服端负载均衡工具,它是基于 Netflix Ribbon 实现的. 它不像 Spring Cloud 服务注册中心.配置中心 ...

  9. Pycharm IDE安装及注册激活笔记(1)

    一.Windows 下的安装及激活. 1.首先去Pycharm官网,或者直接输入网址:http://www.jetbrains.com/pycharm/download/#section=window ...

  10. Java8 内置的函数式接口

    1.Java8 内置的四大核心函数式接口 (1)Consumer<T> : 消费型接口         void accept(T t); (2)Supplier<T> : 供 ...