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. Java版飞机订票系统

    关注微信公众号:Worldhello 回复 飞机订票系统 可获得系统源代码并可加群讨论交流 数据结构课程设计题目:          [飞机订票系统]            通过此系统可以实现如下功能 ...

  2. C++走向远洋——36(数组做数据成员,工资)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:salarly.cpp * 作者:常轩 * 微信公众号:Worl ...

  3. VirtualBox上使用kubeadm安装Kubernetes集群

    之前一直使用minikube练习,为了更贴近生产环境,使用VirtualBox搭建Kubernetes集群. 为了不是文章凌乱,把在搭建过程中遇到的问题及解决方法记在了另一篇文章:安装Kubernet ...

  4. python中excel数据分组处理

    1.场景描述 因文本相似性热度统计(python版)需求中要根据故障类型进行分组统计,需要对excel进行分组后再分词统计,简单记录下,有需要的朋友可以直接拿走,不客气! 2.解决方案 采用panda ...

  5. Python神经网络编程笔记

    神经元 想一想便知道,当一个人捏你一下以至于你会痛得叫起来的力度便是神经元的阈值,而我们构建的时候也是把这种现象抽象成一个函数,叫作激活函数. 而这里便是我们使用sigmoid函数的原因,它是一个很简 ...

  6. Ios/Android h5 唤起本地APP

    纠结两天(浏览器中唤起本地APP),一直找不到解决方案,今天总算基本搞定. ps:吐槽一下 魔窗那篇文章,为什么就不直接把js代码开源开源,混淆后的代码看得我好恼火 参考文章:魔窗解决方案.京东解决方 ...

  7. 使用contenteditable+div模拟textarea文本域实现高度自适应

    使用contenteditable+div模拟textarea文本域实现高度自适应 开发过程中由于需要在发送消息的时候需要有一个可以高度自适应的文本域,一开始是使用textarea并搭配auto-si ...

  8. 一块小饼干(Cookie)的故事-下篇

    上篇介绍了注册的基本流程,下篇简单的讲讲登录的流程以及Cookie的出现 实现登录的小功能 当你在浏览器的输入框里输入localhost:8080/sign_in的时候,会发起GET请求,去访问sig ...

  9. input type="file"使用

    问题: 在实际开发过程中,会遇到上传文件的一些需求.但是使用原生的<input type="file" />在使用中存在一些问题 在未上传文件时,显示"no ...

  10. 关于integer overflow错误

    前端突然报了integer overflow错误,int类型溢出也就是数字超过了int类型,一看很懵逼,查看后台日期发现是在Math.toIntExact()方法报错 那么我们看下方法内部代码: /* ...