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. Snap们崛起告诉我们:这个世界太需要悄悄话

    ​ 北京时间3月3日凌晨,"阅后即焚"应用Snapchat母公司Snap在纽约证券交易所上市.开盘价24美元,比其初定的17美元IPO价格高出近41.2%,按照24美元的股价计算, ...

  2. ConcurrentHashMap源码探究 (JDK 1.8)

    很早就知道在多线程环境中,HashMap不安全,应该使用ConcurrentHashMap等并发安全的容器代替,对于ConcurrentHashMap也有一定的了解,但是由于没有深入到源码层面,很多理 ...

  3. 【快速上手】Git的使用教程

    创建Git仓库 git init 查看当前仓库情况 git status 添加修改 git add (file) or git add . 查看未提交的修改 git diff 撤销提交操作 git r ...

  4. 对BFC的深层理解

    BFC(Block Formatting Context)块级格式化上下文 注意:BFC首先是块,其次需要具备下面的条件之一才可以(通俗来说,BFC就好比一所985或者211的高校,想要成为985或者 ...

  5. C++走向远洋——47(第十二周、运算符重载基础程序、阅读)

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

  6. Selenium 实现自动下载文件(FirefoxOptions,FirefoxProfile) - 根据Selenium Webdriver3实战宝典

    Firefox 版本是72geckodriver 是 0.24selenium 是3.14 代码中注释有关于FirefoxOptions,FirefoxProfile的解释,请各位寻找一下,不做另外解 ...

  7. sql的练习题

    表名和字段 –1.学生表 Student(s_id,s_name,s_birth,s_sex) --学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_i ...

  8. 自己动手用java写一个hashMap

    入坑java很多年了,现在总结一下自己学到的东西. 1.首先我们先来聊聊什么是HashMap? 什么是hash?hash用中文的说法就叫做“散列”,通俗的讲就是把任意长度的字符串输入,经过hash计算 ...

  9. HTML img标签的width height ismap usemap title alt 属性

    前言 img 元素向网页中嵌入一幅图像 今天特地对 img 的几个属性做了一下测试,在这里做一个笔记. 1. img 元素的width属性和height属性. (1)不设置 width 和 和 hei ...

  10. 玩转 React(五)- 组件的内部状态和生命周期

    文章标题总算是可以正常一点了-- 通过之前的文章我们已经知道:在 React 体系中所谓的 "在 JavaScript 中编写 HTML 代码" 指的是 React 扩展了 Jav ...