在很久很久以前,写了一篇自定义3d view的博客。但是只是讲了如何实现,实现起来还是比较耗时,所以本着平易近人的心态,把他封装成了一个ViewGroup,只需要在你的view或者布局外面包裹一层ThreeDLayout 即可实现3D效果(毕竟:没有什么比拿来直接用更爽的时期)。本文同步自博主的私人博客wing的地方酒馆

ThreeDLayout的项目地址:https://github.com/githubwing/ThreeDLayout


效果预览

3D触摸效果,旋转效果,和用旋转效果实现的特效


如何导入ThreeDLayout

方式一

在gralde下加入compile('com.wingsofts.threedlayout:1.0.0')(还没上传到远程仓库,会于近日上传)

方式二

将项目地址依赖库 :threedlayout文件夹下ThreeDLayout.java拷贝至你的项目中,即可使用。

如何使用

以Demo中天气Activity为例。

在xml中加入一个TextView,来显示大温度,下面一个RecyclerView,来显示每天的温度。

<LinearLayout

    android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/threeDLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wingsofts.myapplication.WeatherActivity"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/textView"
android:text="30℃"
android:textColor="#fff"
android:gravity="center"
android:textSize="80sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/> <com.wingsofts.myapplication.MyRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/> </LinearLayout>
</LinearLayout>

这就是一个最基本的界面实现。如何让大温度显示旋转起来呢?只需要用ThreeDlayout将其包裹。

<com.wingsofts.threedlayout.ThreeDLayout
android:background="@color/colorPrimary"
android:id="@+id/td_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
> <TextView
android:id="@+id/textView"
android:text="30℃"
android:textColor="#fff"
android:gravity="center"
android:textSize="80sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</com.wingsofts.threedlayout.ThreeDLayout>

在代码中获取到该layout,并且设置触摸模式,即可实现:


ThreeDLayout layout = (ThreeDLayout) findViewById(R.id.td_header);
//开启触摸模式
layout.setTouchable(true);
//设置模式为X,Y轴旋转
layout.setTouchMode(ThreeDLayout.MODE_BOTH_X_Y);

接下来讲解item动画实现,可以看到其实item是一个接一个延迟旋转,在ThreeDLayout中提供了翻转动画的方法:

//开启水平翻转动画
startHorizontalAnimate(long duration) //延迟开启水平翻转动画 startHorizontalAnimate(long duration,long delayed)

所以Item动画其实是一个for循环,让他们依次执行动画即可~~(当然item要使用ThreeDLayout包裹):

  for(int i = 0;i<list.size();i++){
((ThreeDLayout)recyclerView.getChildAt(i)).startHorizontalAnimateDelayed(100*i,1000);
}

到这里,ThreeDLayout的使用已经介绍完了,是不是很简单呢。如果你感兴趣,可以继续往下阅读,会介绍ThreeDLayout是如何实现的。


ThreeDLayout如何实现

在很久的一篇博客里,我介绍了如何实现一个3Dview,这里就不重复讲解。手把手带你撸一个3D view

这里主要讲解如何把每次都要写的代码封装起来。 我的初始思路就是直接包裹成一个ViewGroup,重写onDraw()方法即可。= = 没错就是这么简单。

所以我把之前3D view的代码搬运过来了,然后重写了一下onDraw()。

@Override protected void onDraw(Canvas canvas) {
mMatrix.reset();
mCamera.save();
mCamera.getMatrix(mMatrix);
mCamera.restore();
mMatrix.preTranslate(-mCenterX, -mCenterY);
mMatrix.postTranslate(mCenterX, mCenterY);
canvas.concat(mMatrix);
super.onDraw(canvas);
}

大概是这样就能完成3D的效果了,但是运行起来没卵用。因为viewgroup的onDraw()一般是不会调用的。怎么解决呢?其实让viewgroup参与draw的过程就好啦,于是我在构造器里给他添加了个背景色。有了背景色他就会调用onDraw了。

  public ThreeDLayout(Context context, AttributeSet attrs, int defStyleAttr) {

    super(context, attrs, defStyleAttr);

    //set a default background to make sure onDraw() dispatch
if (getBackground() == null) {
setBackgroundColor(Color.parseColor("#ffffff"));
}
mCamera = new Camera();
mMatrix = new Matrix();
}

不过事情没有这么简单,还要解决测量问题,于是这里我就取巧,让ThreeDLayout只有一个子view,这样就可以把大小设置成子view的大小,免去测量的过程,所以onMeasure()是这样的:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (getChildCount() != 1) {
throw new IllegalStateException("ThreeDLayout can only have one child");
}
View child = getChildAt(0);
measureChild(child, widthMeasureSpec, heightMeasureSpec); //only one child view,so give the same size
setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight());
}

为了提供不同的需求,所以扩展一下,用户可以自己设置是否开启触摸模式,并且可以设置X,Y,所以在onDraw()里进行一些判断:

    if (mMode == MODE_Y || mMode == MODE_BOTH_X_Y) {
mCamera.rotateX(mCanvasRotateX);
}
if (mMode == MODE_X || mMode == MODE_BOTH_X_Y) {
mCamera.rotateY(mCanvasRotateY);
}

现在一个ThreeDLayout就完成了。可是为了让他更好用呢,要添加一个动画效果,就是水平翻转动画,这样实用性更高,就可以实现天气Activity类似效果。所以在onDraw()里要多加一层旋转角度控制.


@Override protected void onDraw(Canvas canvas) {
mMatrix.reset();
mCamera.save();
if (mMode == MODE_Y || mMode == MODE_BOTH_X_Y) {
mCamera.rotateX(mCanvasRotateX);
}
if (mMode == MODE_X || mMode == MODE_BOTH_X_Y) {
mCamera.rotateY(mCanvasRotateY);
} mCamera.rotateY(mDegreeY);
mCamera.rotateX(mDegreeX);
}

然后提供一个动画开始的方法,顺便当动画完成的时候,使degree变为0,这样就会处于不翻转状态:

  public void startHorizontalAnimate(long duration){
ValueAnimator animator = ValueAnimator.ofFloat(-180f,0f);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
mDegreeY = (float) animation.getAnimatedValue();
invalidate();
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) {
mDegreeY = 0;
animator.removeAllUpdateListeners();
} @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { }
});
animator.setDuration(duration);
animator.start(); }

然后再提供一个延迟动画的方法,内部开一个线程计时,然后去执行动画方法即可:

 public void startHorizontalAnimateDelayed(final long delayed, final long duration){

    new Thread(new Runnable() {
@Override public void run() {
try {
Thread.sleep(delayed);
} catch (InterruptedException e) {
e.printStackTrace();
}
post(new Runnable() {
@Override public void run() {
startHorizontalAnimate(duration);
}
}); }
}).start(); }

好啦,大功告成,以上就是ThreeDLayout的实现啦,如果你觉得效果比较cool,或者该控件比较实用,欢迎star一下~ 如果你喜欢我的博客,欢迎评论以及关注我~

ThreeDLayout的项目地址:https://github.com/githubwing/ThreeDLayout

5秒让你的View变3D,ThreeDLayout使用和实现的更多相关文章

  1. [翻译] JFDepthView 给view提供3D景深

    JFDepthView 给view提供3D景深 https://github.com/atljeremy/JFDepthView This is an iOS project for presenti ...

  2. MugLife静态照片变3D动画算法研究

    原文:MugLife静态照片变3D动画算法研究 MugLife app是一款可以将静态照片变成3D动画的手机应用,如下效果图所示: 大家可以看到,这个静态图具有了类3D的动画特效,是不是很好玩? 这种 ...

  3. 下载一个应用程序,华硕手机秒变3D扫描仪

    近日,新奥尔良的3D开发先锋Scandy对外发布消息称,其取得了一个重大的突破.这次使用的是硬件巨头华硕的智能手机.该公司新的Android设备(华硕ZenFone AR)被Scandy变成一个借助开 ...

  4. android自定义View之3D索引效果

    效果图: 我的小霸王太卡了. 最近工作比较忙,今天搞了一下午才搞出来这个效果,这种效果有很多种实现方式,最常见的应该是用贝塞尔曲线实现的.今天我们来看另一种不同的实现方式,只需要用到 canvas.s ...

  5. android高级页面效果集锦

    程序员界有个神奇的网站,那就是github,这个网站集合了一大批优秀的开源框架,极大地节省了开发者开发的时间,在这里我进行了一下整理,这样可以使我们在使用到时快速的查找到,希望对大家有所帮助! 一个强 ...

  6. iOS 3D Touch 适配开发

    3D Touch的主要应用 文档给出的应用介绍主要有两块: 1.A user can now press your Home screen icon to immediately access fun ...

  7. iOS 3D Touch功能 3 -备

    新的触摸体验——iOS9的3D Touch 一.引言 二.在模拟器上学习和测试3D Touch 附.SBShortcutMenuSimulator的安装和使用 三.3D Touch的主要应用 四.3D ...

  8. ORACLE获取SQL绑定变量值的方法总结

      本文总结一下ORACLE数据库中如何获取SQL绑定变量值的方法,在SQL优化调优过程中,经常会用到这方面的知识点.在此梳理.总结一下,方面日后查找.翻阅. 方法1:查询V$SQL V$SQL视图中 ...

  9. 关于ios 3D变换 CGAffineTransformIdentity

    每次做完3D变换以后,重新设置view的frame时,记得用CGAffineTransformIdentity 对3D变换进行还原,否则将会影响frame.当你对view进行3D变换后,重新设置vie ...

随机推荐

  1. Spring源码分析:Spring IOC容器初始化

    概述: Spring 对于Java 开发来说,以及算得上非常基础并且核心的框架了,在有一定开发经验后,阅读源码能更好的提高我们的编码能力并且让我们对其更加理解.俗话说知己知彼,百战不殆.当你对Spri ...

  2. bcrypt对密码加密的一些认识(学习笔记)

    学习nodejs和mongoDB的时候,接触了用户注册和登录的一些知识. 1.关于增强用户密码的安全性 用户的密码肯定不能保存为明文,避免撞库攻击. 撞库攻击:撞库是一种针对数据库的攻击方式,方法是通 ...

  3. equals方法的编写建议

    1.显示参数命名为 otherObject ,稍后需要将其转换成另一个叫做 other 的变量. 2.检测 this 与 otherObject 是否引用同一个对象: //这条语句只是一个优化.计算这 ...

  4. 学习React系列(九)——高阶函数

    定义:高阶组件就是一个函数,且该函数接收一个组件作为参数,并返回一个新的组件. (上一篇已经说过了高阶组件可以用来解决交叉问题) 一.不要改变原始组件,使用组合 class A extends Rea ...

  5. 前端小白想要编写可维护的js

    我是一名前端小白,之前没写过多少代码,心里没有代码质量这个概念,人人都说代码是团队的产物,应该将代码写规范,但是我对具体什么样的代码是可维护的是茫然的. 我没写过多少代码,本来好多东西就不咋会,每次给 ...

  6. [SDOI 2010]外星千足虫

    Description 题库链接 给出 \(m\) 个 \(n\) 元的 \(0,1\) 方程,即系数非 \(0\) 即 \(1\) ,方程的结果为奇偶性. \(1\leq n\leq 1000,1\ ...

  7. [BJOI2006]狼抓兔子

    题目描述 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: ...

  8. 洛谷P1593 因子和

    题目描述 输入两个正整数a和b,求a^b的因子和.结果太大,只要输出它对9901的余数. 输入输出格式 输入格式: 仅一行,为两个正整数a和b(0≤a,b≤50000000). 输出格式: a^b的因 ...

  9. HDU 5723 Abandoned country 最小生成树+搜索

    Abandoned country Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  10. 习题 7-2 uva225(回溯)

    题意:从(0.0)点出发,第一次走一步……第k次走k步,且每次必须转90度,不能走重复的点.求k次后回到出发点的所有情况.按最小字典序从小到大输出. 思路: 把所有坐标+220,保证其是正数,然后搜索 ...