- 浏览: 106345 次
- 性别:
- 来自: 深圳
最新评论
-
ysc123shift:
给的东西,稍微欠完整。对于初学者,参考意义不大。
music player:一(歌词显示,LyricView,Canvas)---自动滚动 -
sunny09290:
楼主,请问当歌词太长,需要换行该怎么处理呢
music player:一(歌词显示,LyricView,Canvas)---自动滚动 -
zhongyuanceshi:
博主,GraphicsActivity这个类是你自己写的吧,T ...
music player:一(歌词显示,LyricView,Canvas)---自动滚动 -
huxinli:
汉语词典开发-assets,raw的InputStream数据流操作(文件分割合并) -
w1048499078:
能给我源代码 学习么 我邮箱是274633305@qq.c ...
android播放器(music player)源码分析5(在线播放功能)
从现有方法来讲为了实现桌面的3D转屏效果主要是通过Launcher中的workspace实现(现有的有源码的方法),具体实现见:
http://www.eoeandroid.com/viewthread.php?tid=27079&extra=&page=1 (写这篇文章也是为了“报答”该作者开源的贡献,共同学习)
不过该方法存在以下几个问题:
- 不同机器的分辨率和内存大小不同,从而使用cache保持截图的方法很有可能会出现内存方面的错误
- 界面上面的变化,例如图标增加和删除,需要程序对应做出很多修改,用以保证整体效果的统一。其根本原因就是修改的模块位置在Launcher中过于考上
- 图标变形和覆盖(我在2.2源码上总是搞不出来,╮(╯▽╰)╭)
转载请注明http://ishelf.iteye.com/admin/blogs/836929
依据以上问题本文从每个屏的dispatchDraw入手,修改CellLayout的dispatchDraw方法,这篇文章先给出2D的实现方式(利用Matrix实现):
由于代码过多,本文只给出做过修改的代码
///CellLayout.java @Override public void dispatchDraw(Canvas canvas) { long start_time = System.currentTimeMillis(); startRotate(canvas, currentX, canvas.getWidth(), canvas.getHeight()); super.dispatchDraw(canvas); canvas.restore(); long end_time = System.currentTimeMillis(); Log.d("CellLayout" + currentScrenn, (end_time - start_time) + " ms"); } // 上面的Log信息是用来对比用opengl实现两者效率 //startRotate使用来计算该屏显示的位置以及显示的大小,xCor是手指移动的位置大小 public void startRotate(Canvas mCanvas, float xCor, int width, int height) { boolean flag = true; if (isCurrentScrenn && xCor < 0) { xCor = width + xCor; flag = false; } else if (isCurrentScrenn && xCor >= 0) { // xCor = width - xCor; } else if (!isCurrentScrenn && xCor < 0) { xCor = width + xCor; } else if (!isCurrentScrenn && xCor >= 0) { flag = false; } final float SPAN = 0.000424f; float f = xCor - 10; if (f <= 0) { f = 0; xCor = 10; }// the maximum left float value = f * SPAN; if (f > width) { xCor = width - 10; value = 0.127225f; }// the maximum right if (isBorder) { doDraw(mCanvas, new float[] { 0, 0, width, 0, width, height, 0, height }, new float[] { 0, 0, width, 0, width, height, 0, height }); } else if (!flag) { doDraw(mCanvas, new float[] { 0, 0, width, 0, width, height, 0, height }, new float[] { 0, 0, xCor, height * (1 / 7.0f - value), xCor, height * (6 / 7.0f + value), 0, height }); } else { doDraw(mCanvas, new float[] { 0, 0, width, 0, width, height, 0, height }, new float[] { xCor, height * (1 / 30.0f + value), width, 0, width, height, xCor, height * (29 / 30.0f - value) }); } } private Matrix mMatrix = new Matrix(); private int currentScrenn; private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private boolean isBorder; //doDraw使用计算该屏如何变形,这里使用matrix的polyToPoly来实现,具体描述见APIDemo private void doDraw(Canvas canvas, float src[], float dst[]) { canvas.save(); mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); canvas.concat(mMatrix); switch (currentScrenn) { case 0: mPaint.setColor(Color.RED); break; case 1: mPaint.setColor(Color.BLUE); break; case 2: mPaint.setColor(Color.YELLOW); break; case 3: mPaint.setColor(Color.CYAN); break; case 4: mPaint.setColor(Color.GREEN); break; } mPaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawRect(0, 0, src[4], src[5], mPaint); }
以下是workspace,该类主要是要传给cellLayout移动的参数
// 该方法用来画屏 protected void dispatchDraw(Canvas canvas) { boolean restore = false; int restoreCount = 0; // ViewGroup.dispatchDraw() supports many features we don't need: // clip to padding, layout animation, animation listener, disappearing // children, etc. The following implementation attempts to fast-track // the drawing dispatch by drawing only what we know needs to be drawn. boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN; Log.d("Scroller","dispatchDraw"+mScrollX); // If we are not scrolling or flinging, draw only the current screen if (fastDraw) { ((CellLayout) getChildAt(mCurrentScreen)).setPara(mCurrentScreen, (mCurrentScreen - mCurrentScreen) >= 0 ? true : false, true, mChangeMotionX - mLastMotionX); drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime()); } else { final long drawingTime = getDrawingTime(); final float scrollPos = (float) mScrollX / getWidth(); final int leftScreen = (int) scrollPos; final int rightScreen = leftScreen + 1; if (leftScreen >= 0) { ((CellLayout) getChildAt(leftScreen)).setPara(leftScreen, (leftScreen - mCurrentScreen) >= 0 ? true : false, scrollPos == leftScreen, mChangeMotionX - mLastMotionX); drawChild(canvas, getChildAt(leftScreen), drawingTime); } if (scrollPos != leftScreen && rightScreen < getChildCount()) { ((CellLayout) getChildAt(rightScreen)).setPara(rightScreen, mCurrentScreen - rightScreen >= 0 ? true : false, scrollPos == leftScreen, mChangeMotionX - mLastMotionX); drawChild(canvas, getChildAt(rightScreen), drawingTime); } } if (restore) { canvas.restoreToCount(restoreCount); } } @Override public boolean onTouchEvent(MotionEvent ev) { if (mLauncher.isWorkspaceLocked()) { return false; // We don't want the events. Let them fall through to // the all apps view. } if (mLauncher.isAllAppsVisible()) { // Cancel any scrolling that is in progress. if (!mScroller.isFinished()) { mScroller.abortAnimation(); } snapToScreen(mCurrentScreen); return false; // We don't want the events. Let them fall through to // the all apps view. } if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(ev); final int action = ev.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: /* * If being flinged and user touches, stop the fling. isFinished * will be false if being flinged. */ if (!mScroller.isFinished()) { mScroller.abortAnimation(); } // Remember where the motion event started mLastMotionX = ev.getX(); mChangeMotionX = mLastMotionX; mActivePointerId = ev.getPointerId(0); if (mTouchState == TOUCH_STATE_SCROLLING) { enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1); } break; case MotionEvent.ACTION_MOVE: if (mTouchState == TOUCH_STATE_SCROLLING) { // Scroll to follow the motion event final int pointerIndex = ev.findPointerIndex(mActivePointerId); final float x = ev.getX(pointerIndex); final float deltaX = mLastMotionX - x; mLastMotionX = x; if (deltaX < 0) { if (mTouchX > 0) { mTouchX += Math.max(-mTouchX, deltaX); mSmoothingTime = System.nanoTime() / NANOTIME_DIV; invalidate(); } } else if (deltaX > 0) { final float availableToScroll = getChildAt(getChildCount() - 1).getRight() - mTouchX - getWidth(); if (availableToScroll > 0) { mTouchX += Math.min(availableToScroll, deltaX); mSmoothingTime = System.nanoTime() / NANOTIME_DIV; invalidate(); } } else { awakenScrollBars(); } } break; case MotionEvent.ACTION_UP: if (mTouchState == TOUCH_STATE_SCROLLING) { final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); final int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId); final int screenWidth = getWidth(); final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth; final float scrolledPos = (float) mScrollX / screenWidth; mChangeMotionX = mLastMotionX; if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) { // Fling hard enough to move left. // Don't fling across more than one screen at a time. final int bound = scrolledPos < whichScreen ? mCurrentScreen - 1 : mCurrentScreen; snapToScreen(Math.min(whichScreen, bound), velocityX, true); } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) { // Fling hard enough to move right // Don't fling across more than one screen at a time. final int bound = scrolledPos > whichScreen ? mCurrentScreen + 1 : mCurrentScreen; snapToScreen(Math.max(whichScreen, bound), velocityX, true); } else { snapToScreen(whichScreen, 0, true); } if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } } mTouchState = TOUCH_STATE_REST; mActivePointerId = INVALID_POINTER; break; case MotionEvent.ACTION_CANCEL: mTouchState = TOUCH_STATE_REST; mActivePointerId = INVALID_POINTER; break; case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; } return true; } //修改该方法主要目的是记录滑动的距离 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final boolean workspaceLocked = mLauncher.isWorkspaceLocked(); final boolean allAppsVisible = mLauncher.isAllAppsVisible(); if (workspaceLocked || allAppsVisible) { return false; // We don't want the events. Let them fall through to // the all apps view. } /* * This method JUST determines whether we want to intercept the motion. * If we return true, onTouchEvent will be called and we do the actual * scrolling there. */ /* * Shortcut the most recurring case: the user is in the dragging state * and he is moving his finger. We want to intercept this motion. */ final int action = ev.getAction(); if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) { return true; } if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(ev); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_MOVE: { /* * mIsBeingDragged == false, otherwise the shortcut would have * caught it. Check whether the user has moved far enough from * his original down touch. */ /* * Locally do absolute value. mLastMotionX is set to the y value * of the down event. */ final int pointerIndex = ev.findPointerIndex(mActivePointerId); final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); final int xDiff = (int) Math.abs(x - mLastMotionX); final int yDiff = (int) Math.abs(y - mLastMotionY); final int touchSlop = mTouchSlop; boolean xMoved = xDiff > touchSlop; boolean yMoved = yDiff > touchSlop; if (xMoved || yMoved) { if (xMoved) { // Scroll if the user moved far enough along the X axis mTouchState = TOUCH_STATE_SCROLLING; mLastMotionX = x; mTouchX = mScrollX; mSmoothingTime = System.nanoTime() / NANOTIME_DIV; enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1); } // Either way, cancel any pending longpress if (mAllowLongPress) { mAllowLongPress = false; // Try canceling the long press. It could also have been // scheduled // by a distant descendant, so use the mAllowLongPress // flag to block // everything final View currentScreen = getChildAt(mCurrentScreen); currentScreen.cancelLongPress(); } } break; } case MotionEvent.ACTION_DOWN: { final float x = ev.getX(); final float y = ev.getY(); // Remember location of down touch mLastMotionX = x; mChangeMotionX = x; mLastMotionY = y; mActivePointerId = ev.getPointerId(0); mAllowLongPress = true; /* * If being flinged and user touches the screen, initiate drag; * otherwise don't. mScroller.isFinished should be false when * being flinged. */ mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (mTouchState != TOUCH_STATE_SCROLLING) { final CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen); if (!currentScreen.lastDownOnOccupiedCell()) { getLocationOnScreen(mTempCell); // Send a tap to the wallpaper if the last down was on // empty space final int pointerIndex = ev.findPointerIndex(mActivePointerId); mWallpaperManager.sendWallpaperCommand(getWindowToken(), "android.wallpaper.tap", mTempCell[0] + (int) ev.getX(pointerIndex), mTempCell[1] + (int) ev.getY(pointerIndex), 0, null); } } // Release the drag clearChildrenCache(); mTouchState = TOUCH_STATE_REST; mActivePointerId = INVALID_POINTER; mAllowLongPress = false; if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } break; case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; } /* * The only time we want to intercept motion events is if we are in the * drag mode. */ return mTouchState != TOUCH_STATE_REST; }
这些类的修改特别是变换时一定要注意canvas的save和restore方法,不清楚的先百度一下,不然很容易就变形了。下篇讨论使用openGL实现的方法
评论
14 楼
烧伤的火柴
2012-02-20
ishelf 写道
setPara
你查看一下1.6的Launcher源码,这个是在1.6上开发的,早了
烧伤的火柴 写道
setPara函数是做什么用的呢?
你查看一下1.6的Launcher源码,这个是在1.6上开发的,早了
谢谢大师指点
13 楼
ishelf
2012-02-13
setPara
你查看一下1.6的Launcher源码,这个是在1.6上开发的,早了
烧伤的火柴 写道
setPara函数是做什么用的呢?
你查看一下1.6的Launcher源码,这个是在1.6上开发的,早了
12 楼
烧伤的火柴
2012-02-09
setPara函数是做什么用的呢?
11 楼
烧伤的火柴
2012-02-03
手动拖才翻一下 根本不是真正
10 楼
jackshen118
2011-12-20
setPara函数是做什么用的呢?
9 楼
cheng330301560
2011-12-19
setPara方法没找到
8 楼
sadsnow19840713
2011-12-02
对呀,有些变量没有定义和赋值,能贴得更全吗?
7 楼
ishelf
2011-11-30
liu7se7en 写道
liu7se7en 写道
老大我有一个问题 就是在使用该代码实现了3D之后有个问题 就是在拖动的过程中 有时不一定出现3D效果 而且 整个屏幕发生位移
求老大指点啊
应该是你对canvas的操作不对,你写一个小demo测试一下,怎么平移和旋转。 尤其是旋转地中心点要确认一下在什么地方。 多打Log
6 楼
liu7se7en
2011-11-28
liu7se7en 写道
老大我有一个问题 就是在使用该代码实现了3D之后有个问题 就是在拖动的过程中 有时不一定出现3D效果 而且 整个屏幕发生位移
求老大指点啊
5 楼
liu7se7en
2011-11-28
老大我有一个问题 就是在使用该代码实现了3D之后有个问题 就是在拖动的过程中 有时不一定出现3D效果 而且 整个屏幕发生位移
4 楼
zgcypjhf
2011-11-24
请问startRotate(canvas, currentX, canvas.getWidth(), canvas.getHeight());
if (isCurrentScrenn && xCor < 0) {
xCor = width + xCor;
flag = false;
}
变量currentX 和 isCurrentScrenn都没定义, 想请问一下是在哪定义并给它赋值的,谢谢了!
if (isCurrentScrenn && xCor < 0) {
xCor = width + xCor;
flag = false;
}
变量currentX 和 isCurrentScrenn都没定义, 想请问一下是在哪定义并给它赋值的,谢谢了!
3 楼
anita315
2011-11-02
很有幫助 ! 感謝您的提供 .
2 楼
ishelf
2011-08-02
zhmeup 写道
假的,手动拖才翻一下 根本不是真正的3D
这个哥们很给力,顶你一个。
的确要做真正的3D就需要用opengl来做(GLSurfaceView),市面上有一个叫SPB的Launcher,这个是真正的3D,代价是要完全实现一套widget机制,也就是重写Launcher,你可以试试。
1 楼
zhmeup
2011-08-01
假的,手动拖才翻一下 根本不是真正的3D
相关推荐
在实现Launcher桌面的滑动效果时,我们可以将每个主屏幕看作ViewPager的一个页面,通过滑动来切换不同的主屏幕。 1. **ViewPager的基本使用** - 首先,我们需要在布局文件中添加ViewPager,并为其指定适配器。...
本压缩包文件"安卓Launcher桌面相关-实现类似桌面的单屏效果.rar"提供的内容可能包含了创建一个自定义桌面样式的源代码,帮助开发者了解和学习如何构建具有类似桌面单屏效果的应用。 首先,我们要理解"单屏效果"。...
"launcher 3D旋转参考实例"是一个关于如何在Android上实现3D旋转效果的示例项目,它展示了如何通过Eclipse IDE来创建一个具有动态旋转效果的启动器界面。这种特效可以提升用户体验,为应用程序增添视觉吸引力。 ...
赠送jar包:junit-platform-launcher-1.8.0-M1.jar; 赠送原API文档:junit-platform-launcher-1.8.0-M1-javadoc.jar; 赠送源代码:junit-platform-launcher-1.8.0-M1-sources.jar; 赠送Maven依赖信息文件:junit-...
"安卓Launcher桌面相关-Android实现图标拖拽"这个压缩包文件似乎包含了一些关于如何在Android Launcher中实现图标拖放功能的源代码或示例项目。下面将详细介绍Android Launcher桌面的原理以及实现图标拖拽的相关知识...
本压缩包“安卓Launcher桌面相关-android桌面拖拽效果.rar”可能包含了一些实现Android Launcher中拖拽效果的源代码和资源文件。由于描述中提到无法逐一验证所有内容,以下将详细解释Android Launcher中拖拽效果的...
junit-platform-launcher-1.7.0.jarjunit-platform-launcher-1.7.0.jar
launcher 3D旋转参考实例.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
junit-platform-launcher-1.6.2.jarjunit-platform-launcher-1.6.2.jarjunit-platform-launcher-1.6.2.jar
赠送jar包:junit-platform-launcher-1.8.0-M1.jar; 赠送原API文档:junit-platform-launcher-1.8.0-M1-javadoc.jar; 赠送源代码:junit-platform-launcher-1.8.0-M1-sources.jar; 赠送Maven依赖信息文件:junit-...
在Android系统中,Launcher是用户与手机交互的入口,它是一个桌面应用程序,负责展示应用程序快捷方式、小部件以及管理屏幕工作区。这个压缩包提供的"Android Launcher 桌面分页滑动代码"是一个适用于学生毕业设计的...
通过深入理解这份代码,你可以了解到Android桌面启动器的实现机制,尤其是分页滑动的效果。 1. **Android Launcher基本结构**: Android Launcher是基于Activity构建的,通常继承自`android.app.LauncherActivity`...
包含客户端 Launcher3 修改 包含服务端 OverlayScreen(可替换成你自己客需定制负一屏View) 基于android11.0 绝对好用,网上目前最...实现效果图 <img src="https://i.postimg.cc/g2phQy6y/Screen.gif" border="0" />
1. **ViewPager**:ViewPager 是 Android SDK 中一个用于在多个页面间滑动切换的控件,常用于实现类似轮播图或选项卡的效果。在 Launcher 开发中,ViewPager 可以用来创建一个可以左右滑动的桌面界面,每个页面代表...
【Android Launcher 桌面开发详解】 在 Android 系统中,Launcher 是用户与设备交互的重要入口,它作为系统的桌面,展示着应用快捷方式、小部件以及桌面图标等元素。本教程将基于 Eclipse 开发环境,讲解如何创建一...
安卓超酷 3D 桌面 Next Launcher 3D Shell 中文版安卓超酷 3D 桌面 Next Launcher 3D Shell 中文版 告别平面背景、平面图标、平面体验,此刻开始,畅享全3D桌面旅程!加入百万用户,领先潮流,体验独特的操作和出色...
开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ant-launcher-1.9.6开发工具 ...
【Android项目源码-安卓Launcher原生桌面源码】是一个深入了解Android系统启动器(Launcher)工作原理的重要资源。源码提供了Android操作系统中的主屏幕和应用抽屉的实现细节,这对于Android开发者尤其是系统定制者...
### 修改Launcher让图标不显示在桌面或主菜单中的方法 #### 概述 在Android 2.3系统中,可以通过自定义Launcher应用来控制应用程序图标是否显示在桌面或主菜单中。这一操作对于定制化系统界面、提升用户体验等方面...
在Android系统中,Launcher是用户与设备交互的主要入口,它负责显示桌面、应用程序快捷方式以及小部件。在Android 6.0(Marshmallow)版本中,开发者对Launcher3进行了重大改进,其中包括引入了新的屏幕切换动画,...