Android 3D滑动菜单实现及源代码

上传人:suij****uang 文档编号:133403504 上传时间:2022-08-10 格式:DOCX 页数:20 大小:94.98KB
收藏 版权申诉 举报 下载
Android 3D滑动菜单实现及源代码_第1页
第1页 / 共20页
Android 3D滑动菜单实现及源代码_第2页
第2页 / 共20页
Android 3D滑动菜单实现及源代码_第3页
第3页 / 共20页
资源描述:

《Android 3D滑动菜单实现及源代码》由会员分享,可在线阅读,更多相关《Android 3D滑动菜单实现及源代码(20页珍藏版)》请在装配图网上搜索。

1、Android 3D滑动菜单完全解析,实现推拉门式的立体特效在上一篇文章中,我们学习了 Camera的基本用法,并借助它们编写了一个例子,实现了类似于API Demos里的图片中轴旋转功能。不过那个例子的核心代码是来自于API Demos中带有的 Rotate3dAnimation这个类,是它帮助我们完成了所有的三维旋转操作,所有Matrix和Camera相关 的代码也是封装在这个类中。这样说来的话,大家心里会不会痒痒的呢?虽然学习了 Camera的用法,但却没有按照自己的理解来 实现一套非常炫酷的3D效果。不要着急,今天我就带着大家一起来实现一种3D推拉门式的滑动菜 单,而且完全不会借助任何

2、API Demos里面的代码。当然如果你还不是很了解Camera的使用方式,可以先去阅读我的上一篇文章Android中轴旋转特 效实现,制作别样的图片浏览器关于滑动菜单的文章我也已经写过好几篇了,相信看过的朋友对滑动菜单的实现方式应该都已经比较 熟悉了,那么本篇文章的重点就在于,如何在传统滑动菜单的基础上加入推拉门式的立体效果。还不 了解滑动菜单如何实现的朋友,可以去翻一翻我之前的文章。说到这里我必须要吐槽一下了,最近发 现有不少的网站和个人将我的文章恶意转走,而且还特意把第一行的原文地址信息去除掉。更可气的 是,在百度上搜索我文章的标题时,竟然先找到的是那些转载我文章的网站。唉,伤心了,看来

3、还是 谷歌比较正常。因此今天我也是在这里特别申明一下,我所写的所有文章均是首发于CSDN博客, 如果你阅读这篇文章时是在别的网站,那么你将无法找到我前面所写的关于传统滑动菜单的文章,而 且你的疑问和留言也将得不到解答。下面还是回到正题,首先来讲一下这次的实现原理吧,其实传统的滑动菜单功能就是把菜单部分放在 了下面,主布局放在了上面,然后根据手指滑动的距离来偏移主布局,让菜单部分得以显示出来就行 了。不过我们这次既然要做推拉门式的立体效果,就需要将传统的思维稍微转变一下,可以先让菜单 部分隐藏掉,但却复制一个菜单的镜像并生成一张图片,然后在手指滑动的时候对这张图片进行三维 操作,让它产生推拉门式

4、的效果,等滑动操作结束的时候,才让真正的菜单显示出来,然后将这个图 片隐藏。原理示意图如下所示:那么下面我们就开始动手实现吧,首先新建一个Android项目,起名叫做ThreeDSlidingLayoutDemo。然后新建一个Image3dView类继承自View,用于生成镜像图片,以及完成三维操作,代码如下所示: java view plaincopy1. public class Image3dView extends View 2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18./*源视图,用于生成图片对象。*/private View SourceVi

5、ew;/*根据传入的源视图生成的图片对象。*/private Bitmap sourceBitmap;/*源视图的宽度。*/private float sourceWidth;/*19.* Matrix对象,用于对图片进行矩阵操作。20.*/21.22.private Matrix matrix = new Matrix();23./*24.* Camera对象,用于对图片进行三维操作。25.*/26.27.private Camera camera = new Camera();28./*29.* Image3dView的构造函数30.*31.* param context32.* para

6、m attrs33.*/34.public Image3dView(Context context, AttributeSet attrs) 35.super(context, attrs);36.37.38./*39.*提供外部接口,允许向Image3dView传入源视图。40.*41.* param view42.*传入的源视图43.*/44.public void setSourceView(View view) 45.SourceView = view;46.sourcewidth = sourceView.getWidth();47.48.49./*50.*清除掉缓存的图片对象。51

7、.*/52.public void clearSourceBitmap() 53.if (sourceBitmap != null) 54.sourceBitmap = null;55.56.57.58.Override59.protected void onDraw(Canvas canvas) 60.super.onDraw(canvas);61.if (sourceBitmap = null) 62.getSourceBitmap();63. 64. /计算图片需要旋转的角度65. float degree = 90 - (90 / sourcewidth) * getWidth();6

8、6. 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 v

9、oid getSourceBitmap() 80.if (sourceView != null) 81.sourceView.setDrawingCacheEnabled(true);82.sourceView.layout(0, 0, sourceView.getWidth();83.sourceView.buildDrawingCache();84.sourceBitmap = sourceView.getDrawingCache();85.86.87.88. sourceView.getHeight()可以看到,Image3dView中提供了一个setSourceView()方法,用于传

10、递源视图进来,我们稍后复制 镜像就是对它进行复制。然后在onDraw()方法里对sourceBitmap进行判断,如果为空,则去调用 getSourceBitmap()方法来生成一张镜像图片,getSourceBitmap()方法的细节大家自己去看。在获得 了镜像图片之后,接下来就是要计算图片的旋转角度了,这里根据Image3dView当前的宽度和源视 图的总宽度进行对比,按比例算出旋转的角度。然后调用Camera的rotateY()方法,让图片团练Y 轴进行旋转,并将旋转的中心点移动到屏幕左边缘的中间位置,这几行代码我们在上篇文章中已经见 过了,算是挺熟悉了吧!最后调用Canvas的draw

11、Bitmap()方法把图片绘制出来。完成了 Image3dView之后,接着我们要开始编写滑动菜单部分的代码,其实这次的代码和之前的滑 动菜单代码大同小异,看过我前面文章的朋友,这次理解起来一定会轻而易举。新建ThreeDSlidingLayout类,代码如下所示:javaview plaincopy1. public class ThreeDSlidingLayout extends RelativeLayout implements OnTouchListene r 2.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.

12、26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45./*滚动显示和隐藏左侧布局时,手指滑动需要达到的速度。*/public static final int SNAP_VELOCITY = 200;/*滑动状态的一种,表示未进行任何滑动。*/public static final int DO_NOTHING = 0;/*滑动状态的一种,表示正在滑出左侧菜单。*/public static final int SHOW_MENU = 1;/*滑动状态的一种,表示正在隐藏左侧菜单。*/public static final in

13、t HIDE_MENU = 2;/*记录当前的滑动状态*/private int slideState;/*屏幕宽度值。*/private int screenWidth;/*右侧布局最多可以滑动到的左边缘。*/private int leftEdge = 0;/*右侧布局最多可以滑动到的右边缘。*/private int rightEdge = 0;/*在被判定为滚动之前用户手指可以移动的最大值。*/46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.71.72.73.74.75.76.77.7

14、8.79.80.81.82.83.84.85.86.87.88.89.private int touchslop;/*记录手指按下时的横坐标。*/private float xDown;/*记录手指按下时的纵坐标。*/private float yDown;/*记录手指移动时的横坐标。*/private float xMove;/*记录手指移动时的纵坐标。*/private float yMove;/*记录手机抬起时的横坐标。*/private float xUp;/*左侧布局当前是显示还是隐藏。只有完全显示或隐藏时才会更改此值,滑动过程中此值无效。*/private boolean isLe

15、ftLayoutVisible;/*是否正在滑动。*/private boolean isSliding;/*是否已加载过一次layout,这里onLayout中的初始化只需加载一次*/private boolean loadOnce;/*左侧布局对象。90.*/91.92.private View leftLayout;93./*94.*右侧布局对象。95.*/96.97.private View rightLayout;98./*99.*在滑动过程中展示的3D视图100.*/101.102.private Image3dView image3dView;103./*104.*用于监听侧滑事

16、件的View。105.*/106.107.private View mBindView;108./*109.*左侧布局的参数,通过此参数来重新确定左侧布局的宽度,以及更改leftMargin的值。110.*/111.112.private MarginLayoutParams leftLayoutParams;113./*114.*右侧布局的参数,通过此参数来重新确定右侧布局的宽度。115.*/116.117.private MarginLayoutParams rightLayoutParams;118./*119.* 3D视图的参数,通过此参数来重新确定3D视图的宽度。120.*/121.

17、122.private ViewGroup.LayoutParams image3dViewParams;123./*124.*用于计算手指滑动的速度。125.*/126.127.private VelocityTracker mVelocityTracker;128./*129.*重写SlidingLayout的构造函数,其中获取了屏幕的宽度。130.*131.* param context132.* param attrs133.*/134. public ThreeDSlidingLayout(Context context, AttributeSet attrs) 135. super

18、(context, attrs);136. WindowManager wm = (WindowManager) context.getSystemService(Context.WIN DOW_SERVICE);137. screenWidth = wm.getDefaultDisplay().getWidth();138. touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();139. 140.140. /*141. *绑定监听侧滑事件的View,即在绑定的View进行滑动才可以显示和隐藏左侧布局。142. *143

19、. * param bindView144. *需要绑定的View对象。145. */146. public void setScrollEvent(View bindView) 147. mBindView = bindView;148. mBindView.setOnTouchListener(this);149. 151.150. /*151. *将屏幕滚动到左侧布局界面,滚动速度设定为10.152. */153. public void scrollToLeftLayout() 154. image3dView.clearSourceBitmap();155. new ScrollTa

20、sk().execute(-10);156. 159.157. /*158. *将屏幕滚动到右侧布局界面,滚动速度设定为-10.159. */160. public void scrollToRightLayout() 161. image3dView.clearSourceBitmap();162. new ScrollTask().execute(10);163. 167.164. /*165. *左侧布局是否完全显示出来,或完全隐藏,滑动过程中此值无效。166. *167. *return左侧布局完全显示返回true,完全隐藏返回false。168. */169. public bool

21、ean isLeftLayoutVisible() 170. return isLeftLayoutVisible;171. 176.177./*178.*在onLayout中重新设定左侧布局和右侧布局的参数。179.*/180.Override181.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 = findV

22、iewById(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 = scr

23、eenWidth;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.Override202.public boolean onTouch(View v, MotionEvent event)

24、203.createVelocityTracker(event);204.switch (event.getAction() 205.case MotionEvent.ACTION_DOWN:206./手指按下时,记录按下时的横坐标207.xDown = event.getRawX();208.yDown = event.getRawY();209.slideState = DO_NOTHING;210.break;211.case MotionEvent.ACTION_MOVE:212./手指移动时,对比按下时的横坐标,计算出移动的距离,来调整右侧布局的leftMargin值,从而显示和隐藏

25、左侧布局213.xMove = event.getRawX();214.yMove = event.getRawY();215.int moveDistanceX = (int) (xMove - xDown);216.int moveDistanceY = (int) (yMove - yDown);217.checkSlideState(moveDistanceX, moveDistanceY);218.switch (slideState) 219.case SHOW_MENU:220.rightLayoutParams.rightMargin = -moveDistanceX;221.

26、onSlide();222.break;223.case HIDE_MENU:224.rightLayoutParams.rightMargin = rightEdge - moveDistanceX;225.onSlide();226.break;227.default:228.break;229.230.break;231.case MotionEvent.ACTION_UP:232.xUp = event.getRawX();233.int upDistanceX = (int) (xUp - xDown);234.if (isSliding) 235./手指抬起时,进行判断当前手势的意

27、图236.switch (slideState) 237.case SHOW_MENU:238.if (shouldScrollToLeftLayout() 239.scrollToLeftLayout();240. else 241.scrollToRightLayout();242.243.break;244.case HIDE_MENU:245.if (shouldScrollToRightLayout() 246.scrollToRightLayout();247. else 248.scrollToLeftLayout();249.250.break;251.default:252.

28、break;253.254. else if (upDistanceX = touchSlop & moveDista nceX = touchSlop & moveDistanceX 0303.& Math.abs(moveDistanceY) leftEdge) 314.rightLayoutParams.rightMargin = leftEdge;315. else if (rightLayoutParams.rightMargin leftLayoutParams.width / 2 | getScrollVelocity() SNAP_VELOCITY;328.329.330./*

29、331.*判断是否应该滚动将右侧布局展示出来。如果手指移动距离加上leftLayoutPadding大于 屏幕的1/2,332.*或者手指移动速度大于SNAP_VELOCITY,就认为应该滚动将右侧布局展示出来。333.*334.* return如果应该滚动将右侧布局展示出来返回true,否则返回false。335.*/336.private boolean shouldScrollToRightLayout() 337.return xDown - xUp leftLayoutParams.width / 2 | getScrollVelocity() SNAP_VELOCITY;338.3

30、39.340./*341.*创建VelocityTracker对象,并将触摸事件加入到VelocityTracker当中。342.*343.* param event344.*右侧布局监听控件的滑动事件345.*/346.private void createVelocityTracker(MotionEvent event) 347.if (mVelocityTracker = null) 348.mVelocityTracker = VelocityTracker.obtain();349.350.mVelocityTracker.addMovement(event);351.352.35

31、3./*354.*获取手指在右侧布局的监听View上的滑动速度。355.*356.* return滑动速度,以每秒钟移动了多少像素值为单位。357.*/358.private int getScrollVelocity() 359.mVelocityTputeCurrentVelocity(1000);360.int velocity = (int) mVelocityTracker.getXVelocity();361.return Math.abs(velocity);362.363.364./*365.* 回收 VelocityTracker 对象。366.*/367.private v

32、oid recycleVelocityTracker() 368.mVelocityTracker.recycle();369.mVelocityTracker = null;370.371.372./*373.*使用可以获得焦点的控件在滑动的时候失去焦点。374.*/375.private void unFocusBindView() 376.if (mBindView != null) 377.mBindView.setPressed(false);378.mBindView.setFocusable(false);379.mBindView.setFocusablelnTouchMode

33、(false);380.381.382.383./*384.*保证此时让左侧布局不可见,3D视图可见,从而让滑动过程中产生3D的效果。385.*/386.private void showImage3dView() 387.if (image3dView.getVisibility() != View.VISIBLE) 388.image3dView.setVisibility(View.VISIBLE);389.390.if (leftLayout.getVisibility() != View.INVISIBLE) 391.leftLayout.setVisibility(View.INV

34、ISIBLE);392.393. 394.395. class ScrollTask extends AsyncTask 396.397.Override398.protected Integer doInBackground(Integer. speed) 399.int rightMargin = rightLayoutParams.rightMargin;400./根据传入的速度来滚动界面,当滚动到达左边界或右边界时,跳出循环。401.while (true) 402.rightMargin = rightMargin + speed0;403.if (rightMargin leftE

35、dge) 408.rightMargin = leftEdge;409.break;410.411.publishProgress(rightMargin);412.滚动动画。413./为了要有滚动效果产生,每次循环使线程睡眠5毫秒,这样肉眼才能够看到 sleep(5);414.415.if (speed0 0) 416.isLeftLayoutVisible = false;417. else 418.isLeftLayoutVisible = true;419.420.isSliding = false;421.return rightMargin;422.423.424.Override

36、425.protected void onProgressUpdate(Integer. rightMargin) 426.rightLayoutParams.rightMargin = rightMargin0;427.rightLayout.setLayoutParams(rightLayoutParams);428.image3dViewParams = image3dView.getLayoutParams();429.image3dViewParams.width = -rightLayoutParams.rightMargin;430.431.432.433.434.435.436

37、.437.438.439.440.441.442.443.444.445.446.447.448.449.450.451.452.453.454.455.456.457.458.459.460.461.462.463. image3dView.setLayoutParams(image3dViewParams); showImage3dView();unFocusBindView();Overrideprotected void onPostExecute(Integer rightMargin) rightLayoutParams.rightMargin = rightMargin; rig

38、htLayout.setLayoutParams(rightLayoutParams); image3dViewParams = image3dView.getLayoutParams(); image3dViewParams.width = -rightLayoutParams.rightMargin; image3dView.setLayoutParams(image3dViewParams); if (isLeftLayoutVisible) /保证在滑动结束后左侧布局可见,3D视图不可见。 image3dView.setVisibility(View.INVISIBLE); leftL

39、ayout.setVisibility(View.VISIBLE);/*使当前线程睡眠指定的毫秒数。* param millis* 指定当前线程睡眠多久,以毫秒为单位*/private void sleep(long millis) try Thread.sleep(millis); catch (InterruptedException e) e.printStackTrace();代码比较长,我还是带着大家来理一下思路。首先在onLayout方法中,我们分别初始化了左侧布局 对象、右侧布局对象和Image3dView对象,这三个对象稍后都要配置到Activity布局里面的。在 onLayo

40、ut()方法的最后,调用了 Image3dView的setSourceView()方法,并将左侧布局对象传了进去, 说明我们后面就要对它进行镜像复制。当手指在界面上拖动来显示左侧布局的时候,就会进入到。nTouch()方法中,这里会调用 checkSlideState()方法来检查滑动的状态,以判断用户是想要显示左侧布局还是隐藏左侧布局,然后 根据手指滑动的距离对右侧布局进行偏移,就可以实现基本的滑动效果了。接下来是重点内容,这里会根据右侧布局的偏移量来改变Image3dView的宽度,当Image3dView大小发生改变时,当然会调 用onDraw()方法来进行重绘,此时我们编写的三维旋转逻

41、辑就可以得到执行了,于是就会产生立体 的推拉门式效果。注意,在整个的滑动过程中,真正的左侧布局一直都是不可见的,我们所看到的只 是它的一张镜像图片。当手指离开屏幕后,会根据当前的移动距离来决定是显示左侧布局还是隐藏左侧布局,并会调用 scrollToLeftLayout()方法或scrollToRightLayout()方法来完成后续的滚动操作。当整个滚动操作完成 之后,才会将真正的左侧布局显示出来,再把镜像图片隐藏掉,这样用户就可以点击左侧布局上按钮 之类的东西了。接着我们需要在Activity的布局文件当中去引用这个三维滑动菜单框架,打开或新建activity_main.xml 作为程序的

42、主布局文件,代码如下所示:html view plaincopy1. 6.6. 14.13. 20.18. 28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.可以看到,在最外层的ThreeDSlidingLayout布局里面,我们放入了三个直接子布局,第一个RelativeLayout也就是左侧布局了,里面简单地放了一个TextView和一个按钮。第二个LinearLayout是右侧布局,里面放入了一个按钮

43、和一个ListView,都是用于显示左侧布局而准备的。第三个是 Image3dView,当然是用于在滑动过程中显示左侧布局的镜像图片了。最后,打开或新建MainActivity作为程序的主Activity,在里面加入如下代码: java view plaincopy1. public class MainActivity extends Activity 2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27./*侧滑布局对象,用于通过手指滑动将左侧的菜单布局进行显示或隐藏。*/private ThreeDSl

44、idingLayout slidingLayout;/* menu按钮,点击按钮展示左侧布局,再点击一次隐藏左侧布局。*/private Button menuButton;/*放在content布局中的ListView。*/private ListView contentListView;/*作用于contentListView的适配器。*/private ArrayAdapter contentListAdapter;/*用于填充contentListAdapter的数据源。*/private String contentItems = Content Item 1”, Content I

45、tem 2”, Conten t Item 3,Content Item 4, Content Item 5, Content Item 6, Content Item 725. Content Item 8, Content Item 9, Content Item 10”, Content Item 11,26. Content Item 12, Content Item 13”, Content Item 14”, Content Ite m 15”,27. Content Item 16 ;31.32.33.34.Overrideprotected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);35.36.37.38.39.lesetContentView(R.layout.activity_main);slidingLayout = (ThreeDSlidingLayout) findViewById(R.id.slidingLayout);menuBut

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!