3D画廊
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画廊的更多相关文章
- Android ViewPager打造3D画廊
本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发. 网上有很多关于使用Gallery来打造3D画廊的博客,但是在关于Gallery的官方说法中表明: This cl ...
- Android自己定义控件——3D画廊和图像矩阵
转载请注明出处:http://blog.csdn.net/allen315410/article/details/39932689 1.3D画廊的实现 我们知道android系统已经为我们提供好了一个 ...
- CSS3D写3d画廊滚动
CSS样式表 *{ margin: 0; padding: 0; } .wrapper{ width: 800px; height: 600px; background: #87CEEB; margi ...
- 一款基于jQuery和CSS3炫酷3D旋转画廊特效插件
这是一款效果炫酷的jQuery和CSS3 3D旋转画廊特效插件.该3D画廊插件可以通过前后导航按钮来切换图片,效果就像旋转木马一样.它还带有点击放大图片,显示图片标题和用键盘操作等功能. 在线预览 ...
- 某技术大牛的帖子(android项目总结)
1. 一般性控件需要设置onclick事件才会有点击效果(selector). 2. <item android:drawable=”@drawable/btn_ct_green” /> ...
- Android ViewPager用法小结
android-support-v4.jar 是谷歌提供给我们的一个兼容低版本号安卓设备的软件包.里面包囊了仅仅有在 Android 3.0 以上可用的API.而 ViewPager 就是当中之中的一 ...
- 一站式学习Wireshark(转载)
一站式学习Wireshark(一):Wireshark基本用法 2014/06/10 · IT技术 · 4 评论 · WireShark 分享到: 115 与<YII框架>不得不说的故事— ...
- 【每日Scrum】第五天(4.15) TD学生助手Sprint1站立会议
TD学生助手Sprint1站立会议(4.15) 任务看板 站立会议内容 组员 昨天 今天 困难 签到 刘铸辉 (组长) 今天和静姐,娇哥把图片3D画廊效果的功能实现了,GPS功能没什么进展,所以只能继 ...
- 【每日Scrum】第四天(4.14) TD学生助手Sprint1站立会议
TD学生助手Sprint1站立会议(4.14) 任务看板 站立会议内容 组员 昨天 今天 困难 签到 刘铸辉 (组长) 今天早晨静姐调整了下界面和配色,下午和宝月兄一起做了GPS功能显示,暂时只能显示 ...
随机推荐
- bzoj1603: [Usaco2008 Oct]打谷机 (纱布题)
Description Input Output Sample Input Sample Output Time Limit: 5 Sec Memory Limit: 64 MB Submit: 7 ...
- create view and switch view
pageView扩展backbone cAbstractApp定义view加载.切换.回退.跳转-webApp/cWebViewApp/hybirdApp为其子类 1.cWebApp扩展了父类的bin ...
- 2020年JAVA大厂笔经面经
个人简介 Java后台开发方向. 非计算机专业硕士,专业涉及到一些开发. 实验室项目主要是Java Web系统,挖掘小亮点. 无实习经验. 闲话唠嗑 回顾这几个月,宛若梦一场. 一开始心态不好 ...
- 死磕Lambda表达式(二):Lambda的使用
城市就是森林,每一个男人都是猎手,每一个女人都是陷阱.--<三体> 在哪使用Lambda表达式? 在上一篇文章(传送门)中介绍了Lambda表达式的基本语法,其中的举了一个Lambda表达 ...
- Newman+Jenkins实现接口自动化测试
目录 一.是什么Newman 二.如何安装 三.如何使用 1.运行本地文件 2.运行在线文件 3.以node.js库运行 4.导出报告 四.命令行测试真实接口 1.导出collection文件 2.导 ...
- Mac中使用brew安装mysql
若不考虑版本直接执行以下命令 brew install mysql 若要选择版本只要加上@版本即可,例如 brew install mysql@5.7 安装完后启动mysql mysql.server ...
- proxyTable的配置
在dev环境下面: proxyTable: { '/api': { target: 'http://api.douban.com/v2', //主域名,以前我都写192.168.2.57:80,这里跨 ...
- Asp.Net Core IdentityServer4 中的基本概念
一.前言 这篇文章可能大家会觉得很空洞,没有实际的实战东西,主要是自己整理出来的IdentityServer4 的一些概念性的东西:如果你对IdentityServer4有过一定的实战经验,可以跳过不 ...
- JZOJ 5235. 【NOIP2017模拟8.7A组】好的排列
5235. [NOIP2017模拟8.7A组]好的排列 (File IO): input:permutation.in output:permutation.out Time Limits: 1000 ...
- node代理遇到的坑记
在进行前端mock地址代理时候,进行了webpack的node反向代理: 实际mock地址是:http://10.118.183.10/mock/hb/startwork/openredpacket ...