5秒让你的View变3D,ThreeDLayout使用和实现
来源:互联网 发布:mac finder 打开路径 编辑:程序博客网 时间:2024/04/28 13:15
在很久很久以前,写了一篇自定义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使用和实现
- ThreeDLayout 将 view 放入此 layout,就会出现 3D 效果
- Insta360 Nano让你的iPhone秒变VR直播相机
- Airbnb使用AI技术 让设计图秒变代码
- Java8 Lambda表达式和流操作如何让你的代码变慢5倍
- Java8 Lambda表达式和流操作如何让你的代码变慢5倍
- 让你的浏览器3D起来
- 让菜鸟秒变stm32高手的STM32CubeMX
- 让你秒懂的三级缓存
- 让你的blog外观变漂亮
- 让你的电脑屏幕变变色
- 九个让你变穷的原因
- Android 实现沉浸式状态栏-让你的状态栏变个颜色
- 让一个view变圆
- 30秒让你知道悲观锁和乐观锁的区别
- iOS工程使用cocoaPods。动手让你的工程由xcodeproj变身为.xcworkspace
- 如果你的婚姻让你变丑
- JS 实现3D立体效果的首页轮播图(瞬间让你的网站高大上,逼格满满)
- 如何查看JSTL中自带的TLD文件
- 【VSCode】Windows下VSCode编译调试c/c++
- 《恋狱》
- 实现文件的读写操作举例
- 重修Java——运算符
- 5秒让你的View变3D,ThreeDLayout使用和实现
- 英文名字的昵称(亲切的叫法)
- 杭电oj编码2013
- 堆和栈的区别和联系
- MyBatis SQL在xml中,处理大于小于号的方法
- 天线的基本原理和概念
- php实现等比例生成图片缩略图不失真
- iOS网页-JavaScriptCore
- Activity绑定Service