Android 3D滑动菜单实现及源代码.docx
- 文档编号:6618223
- 上传时间:2023-01-08
- 格式:DOCX
- 页数:27
- 大小:482.70KB
Android 3D滑动菜单实现及源代码.docx
《Android 3D滑动菜单实现及源代码.docx》由会员分享,可在线阅读,更多相关《Android 3D滑动菜单实现及源代码.docx(27页珍藏版)》请在冰豆网上搜索。
Android3D滑动菜单实现及源代码
Android3D滑动菜单完全解析,实现推拉门式的立体特效
在上一篇文章中,我们学习了Camera的基本用法,并借助它们编写了一个例子,实现了类似于APIDemos里的图片中轴旋转功能。
不过那个例子的核心代码是来自于APIDemos中带有的Rotate3dAnimation这个类,是它帮助我们完成了所有的三维旋转操作,所有Matrix和Camera相关的代码也是封装在这个类中。
这样说来的话,大家心里会不会痒痒的呢?
虽然学习了Camera的用法,但却没有按照自己的理解来实现一套非常炫酷的3D效果。
不要着急,今天我就带着大家一起来实现一种3D推拉门式的滑动菜单,而且完全不会借助任何APIDemos里面的代码。
当然如果你还不是很了解Camera的使用方式,可以先去阅读我的上一篇文章 Android中轴旋转特效实现,制作别样的图片浏览器 。
关于滑动菜单的文章我也已经写过好几篇了,相信看过的朋友对滑动菜单的实现方式应该都已经比较熟悉了,那么本篇文章的重点就在于,如何在传统滑动菜单的基础上加入推拉门式的立体效果。
还不了解滑动菜单如何实现的朋友,可以去翻一翻我之前的文章。
说到这里我必须要吐槽一下了,最近发现有不少的网站和个人将我的文章恶意转走,而且还特意把第一行的原文地址信息去除掉。
更可气的是,在XX上搜索我文章的标题时,竟然先找到的是那些转载我文章的网站。
唉,伤心了,看来还是谷歌比较正常。
因此今天我也是在这里特别申明一下,我所写的所有文章均是首发于CSDN博客,如果你阅读这篇文章时是在别的网站,那么你将无法找到我前面所写的关于传统滑动菜单的文章,而且你的疑问和留言也将得不到解答。
下面还是回到正题,首先来讲一下这次的实现原理吧,其实传统的滑动菜单功能就是把菜单部分放在了下面,主布局放在了上面,然后根据手指滑动的距离来偏移主布局,让菜单部分得以显示出来就行了。
不过我们这次既然要做推拉门式的立体效果,就需要将传统的思维稍微转变一下,可以先让菜单部分隐藏掉,但却复制一个菜单的镜像并生成一张图片,然后在手指滑动的时候对这张图片进行三维操作,让它产生推拉门式的效果,等滑动操作结束的时候,才让真正的菜单显示出来,然后将这个图片隐藏。
原理示意图如下所示:
那么下面我们就开始动手实现吧,首先新建一个Android项目,起名叫做ThreeDSlidingLayoutDemo。
然后新建一个Image3dView类继承自View,用于生成镜像图片,以及完成三维操作,代码如下所示:
[java] viewplaincopy
1.public class Image3dView extends View {
2.
3. /**
4. * 源视图,用于生成图片对象。
5. */
6. private View sourceView;
7.
8. /**
9. * 根据传入的源视图生成的图片对象。
10. */
11. private Bitmap sourceBitmap;
12.
13. /**
14. * 源视图的宽度。
15. */
16. private float sourceWidth;
17.
18. /**
19. * Matrix对象,用于对图片进行矩阵操作。
20. */
21. private Matrix matrix = new Matrix();
22.
23. /**
24. * Camera对象,用于对图片进行三维操作。
25. */
26. private Camera camera = new Camera();
27.
28. /**
29. * Image3dView的构造函数
30. *
31. * @param context
32. * @param attrs
33. */
34. public Image3dView(Context context, AttributeSet attrs) {
35. super(context, attrs);
36. }
37.
38. /**
39. * 提供外部接口,允许向Image3dView传入源视图。
40. *
41. * @param view
42. * 传入的源视图
43. */
44. public void setSourceView(View view) {
45. sourceView = view;
46. sourceWidth = sourceView.getWidth();
47. }
48.
49. /**
50. * 清除掉缓存的图片对象。
51. */
52. public void clearSourceBitmap() {
53. if (sourceBitmap !
= null) {
54. sourceBitmap = null;
55. }
56. }
57.
58. @Override
59. protected void onDraw(Canvas canvas) {
60. super.onDraw(canvas);
61. if (sourceBitmap == null) {
62. getSourceBitmap();
63. }
64. // 计算图片需要旋转的角度
65. float degree = 90 - (90 / sourceWidth) * getWidth();
66. camera.save();
67. camera.rotateY(degree);
68. camera.getMatrix(matrix);
69. camera.restore();
70. // 将旋转的中心点移动到屏幕左边缘的中间位置
71. matrix.preTranslate(0, -getHeight() / 2);
72. matrix.postTranslate(0, getHeight() / 2);
73. canvas.drawBitmap(sourceBitmap, matrix, null);
74. }
75.
76. /**
77. * 获取源视图对应的图片对象。
78. */
79. private void getSourceBitmap() {
80. if (sourceView !
= null) {
81. sourceView.setDrawingCacheEnabled(true);
82. sourceView.layout(0, 0, sourceView.getWidth(), sourceView.getHeight());
83. sourceView.buildDrawingCache();
84. sourceBitmap = sourceView.getDrawingCache();
85. }
86. }
87.
88.}
可以看到,Image3dView中提供了一个setSourceView()方法,用于传递源视图进来,我们稍后复制镜像就是对它进行复制。
然后在onDraw()方法里对sourceBitmap进行判断,如果为空,则去调用getSourceBitmap()方法来生成一张镜像图片,getSourceBitmap()方法的细节大家自己去看。
在获得了镜像图片之后,接下来就是要计算图片的旋转角度了,这里根据Image3dView当前的宽度和源视图的总宽度进行对比,按比例算出旋转的角度。
然后调用Camera的rotateY()方法,让图片团练Y轴进行旋转,并将旋转的中心点移动到屏幕左边缘的中间位置,这几行代码我们在上篇文章中已经见过了,算是挺熟悉了吧!
最后调用Canvas的drawBitmap()方法把图片绘制出来。
完成了Image3dView之后,接着我们要开始编写滑动菜单部分的代码,其实这次的代码和之前的滑动菜单代码大同小异,看过我前面文章的朋友,这次理解起来一定会轻而易举。
新建ThreeDSlidingLayout类,代码如下所示:
[java] viewplaincopy
1.public class ThreeDSlidingLayout extends RelativeLayout implements OnTouchListener {
2.
3. /**
4. * 滚动显示和隐藏左侧布局时,手指滑动需要达到的速度。
5. */
6. public static final int SNAP_VELOCITY = 200;
7.
8. /**
9. * 滑动状态的一种,表示未进行任何滑动。
10. */
11. public static final int DO_NOTHING = 0;
12.
13. /**
14. * 滑动状态的一种,表示正在滑出左侧菜单。
15. */
16. public static final int SHOW_MENU = 1;
17.
18. /**
19. * 滑动状态的一种,表示正在隐藏左侧菜单。
20. */
21. public static final int HIDE_MENU = 2;
22.
23. /**
24. * 记录当前的滑动状态
25. */
26. private int slideState;
27.
28. /**
29. * 屏幕宽度值。
30. */
31. private int screenWidth;
32.
33. /**
34. * 右侧布局最多可以滑动到的左边缘。
35. */
36. private int leftEdge = 0;
37.
38. /**
39. * 右侧布局最多可以滑动到的右边缘。
40. */
41. private int rightEdge = 0;
42.
43. /**
44. * 在被判定为滚动之前用户手指可以移动的最大值。
45. */
46. private int touchSlop;
47.
48. /**
49. * 记录手指按下时的横坐标。
50. */
51. private float xDown;
52.
53. /**
54. * 记录手指按下时的纵坐标。
55. */
56. private float yDown;
57.
58. /**
59. * 记录手指移动时的横坐标。
60. */
61. private float xMove;
62.
63. /**
64. * 记录手指移动时的纵坐标。
65. */
66. private float yMove;
67.
68. /**
69. * 记录手机抬起时的横坐标。
70. */
71. private float xUp;
72.
73. /**
74. * 左侧布局当前是显示还是隐藏。
只有完全显示或隐藏时才会更改此值,滑动过程中此值无效。
75. */
76. private boolean isLeftLayoutVisible;
77.
78. /**
79. * 是否正在滑动。
80. */
81. private boolean isSliding;
82.
83. /**
84. * 是否已加载过一次layout,这里onLayout中的初始化只需加载一次
85. */
86. private boolean loadOnce;
87.
88. /**
89. * 左侧布局对象。
90. */
91. private View leftLayout;
92.
93. /**
94. * 右侧布局对象。
95. */
96. private View rightLayout;
97.
98. /**
99. * 在滑动过程中展示的3D视图
100. */
101. private Image3dView image3dView;
102.
103. /**
104. * 用于监听侧滑事件的View。
105. */
106. private View mBindView;
107.
108. /**
109. * 左侧布局的参数,通过此参数来重新确定左侧布局的宽度,以及更改leftMargin的值。
110. */
111. private MarginLayoutParams leftLayoutParams;
112.
113. /**
114. * 右侧布局的参数,通过此参数来重新确定右侧布局的宽度。
115. */
116. private MarginLayoutParams rightLayoutParams;
117.
118. /**
119. * 3D视图的参数,通过此参数来重新确定3D视图的宽度。
120. */
121. private ViewGroup.LayoutParams image3dViewParams;
122.
123. /**
124. * 用于计算手指滑动的速度。
125. */
126. private VelocityTracker mVelocityTracker;
127.
128. /**
129. * 重写SlidingLayout的构造函数,其中获取了屏幕的宽度。
130. *
131. * @param context
132. * @param attrs
133. */
134. public ThreeDSlidingLayout(Context context, AttributeSet attrs) {
135. super(context, attrs);
136. WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
137. screenWidth = wm.getDefaultDisplay().getWidth();
138. touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
139. }
140.
141. /**
142. * 绑定监听侧滑事件的View,即在绑定的View进行滑动才可以显示和隐藏左侧布局。
143. *
144. * @param bindView
145. * 需要绑定的View对象。
146. */
147. public void setScrollEvent(View bindView) {
148. mBindView = bindView;
149. mBindView.setOnTouchListener(this);
150. }
151.
152. /**
153. * 将屏幕滚动到左侧布局界面,滚动速度设定为10.
154. */
155. public void scrollToLeftLayout() {
156. image3dView.clearSourceBitmap();
157. new ScrollTask().execute(-10);
158. }
159.
160. /**
161. * 将屏幕滚动到右侧布局界面,滚动速度设定为-10.
162. */
163. public void scrollToRightLayout() {
164. image3dView.clearSourceBitmap();
165. new ScrollTask().execute(10);
166. }
167.
168. /**
169. * 左侧布局是否完全显示出来,或完全隐藏,滑动过程中此值无效。
170. *
171. * @return 左侧布局完全显示返回true,完全隐藏返回false。
172. */
173. public boolean isLeftLayoutVisible() {
174. return isLeftLayoutVisible;
175. }
176.
177. /**
178. * 在onLayout中重新设定左侧布局和右侧布局的参数。
179. */
180. @Override
181. protected void onLayout(boolean changed, int l, int t, int r, int b) {
182. super.onLayout(changed, l, t, r, b);
183. if (changed && !
loadOnce) {
184. // 获取左侧布局对象
185. leftLayout = findViewById(R.id.menu);
186. leftLayoutParams = (MarginLayoutParams) leftLayout.getLayoutParams();
187. rightEdge = -leftLayoutParams.width;
188. // 获取右侧布局对象
189. rightLayout = findViewById(R.id.content);
190. rightLayoutParams = (MarginLayoutParams) rightLayout.getLayoutParams();
191. rightLayoutParams.width = screenWidth;
192. rightLayout.setLayoutParams(rightLayoutParams);
193. // 获取3D视图对象
194. image3dView = (Image3dView) findViewById(R.id.image_3d_view);
195. // 将左侧布局传入3D视图中作为生成源
196. image3dView.setSourceView(leftLayout);
197. loadOnce = true;
198. }
199. }
200.
201. @Override
202. public boolean onTouch(View v, MotionEvent event) {
203. createVelocityTracker(event);
204. switch (event.getAction()) {
205. case MotionEvent.ACTION_DOWN:
206. // 手指按下时,记录按下时的横坐标
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 3D滑动菜单实现及源代码 滑动 菜单 实现 源代码