- 浏览: 118508 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
瘾心丶Android:
[color=red][/colo[size=large][/ ...
android捕获Home键的方法 -
j086924:
good share!
android Launcher——ui框架 -
m331006:
a、进入cocos2d-x\testandroid\andro ...
Android cocos2d-x开发(三)之创建Android工程和编译 -
sphway:
为什么在布局文件中加入android:layout_gravi ...
自定义控件---滑动按钮的实现 -
chenshijun0101:
LZ,你能把长按home键显示当前任务实现此功能的源码发给我一 ...
长按home键显示当前任务
对于Launcher的桌面滑动大家应该都比较熟悉了,最好的体验应该是可以随着手指的滑动而显示不同位置的桌面。
昨天公司要我实现桌面Launcher这种效果,就是顶部布局不变,中间是一个可以滑动类似桌面Launcher的布局,而底部也是不动的布局。难点主要是中间那个可以实现图片滑动功能的ScrollLayout布局,下面我把实现ScrollLayout布局的代码贴出来,代码也是别人的,我只是注释了一下罢了:
package cn.flyaudio.android.lichunan; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.Scroller; /** * 仿Launcher中的WorkSapce,可以左右滑动切换屏幕的类 * @author 李楚男 * 该类继承ViewGroup容器类以实现自己需要的布局显示 */ public class ScrollLayout extends ViewGroup{ private static final String TAG = "ScrollLayout"; /**用来平滑过渡各个页面之间的切换*/ private Scroller mScroller; /**用来跟踪触摸速度的类*/ private VelocityTracker mVelocityTracker; private int mCurScreen; private int mDefaultScreen = 0; private static final int TOUCH_STATE_REST = 0;//手指离开屏幕状态 private static final int TOUCH_STATE_SCROLLING = 1; private static final int SNAP_VELOCITY = 600; private int mTouchState = TOUCH_STATE_REST;//手指与屏幕是否接触状态 private int mTouchSlop; /**横坐标的最终位置*/ private float mLastMotionX; /**纵坐标的最终位置*/ private float mLastMotionY; public ScrollLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ScrollLayout(Context context) { super(context); } public ScrollLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /**使用缺省的持续时间和动画插入器创建一个Scroller*/ mScroller = new Scroller(context); mCurScreen = mDefaultScreen; /**是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件*/ mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } /** * 为每一个子view指定size和position */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { if (changed) { /**子view离父view左边的距离*/ int childLeft = 0; /**获取子view数目*/ final int childCount = getChildCount(); for (int i=0; i<childCount; i++) { /**获取子view*/ final View childView = getChildAt(i); if (childView.getVisibility() != View.GONE) {//如果子view可见的话 /**获取子view的宽度*/ final int childWidth = childView.getMeasuredWidth(); /**为子view设置大小和位置*/ childView.layout(childLeft, 0, childLeft+childWidth, childView.getMeasuredHeight()); /**左边距自加子view宽度,从而得到下一个子view的x坐标*/ childLeft += childWidth; } } } } /** * 指明控件可获得的空间以及关于这个空间描述的元数据 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.e(TAG, "onMeasure"); super.onMeasure(widthMeasureSpec, heightMeasureSpec); /**int specMode = MeasureSpec.getMode(measureSpec); * int specSize = MeasureSpec.getSize(measureSpec); * 依据specMode的值,如果是AT_MOST,specSize 代表的是最大可获得的空间; * 如果是EXACTLY,specSize 代表的是精确的尺寸; * 如果是UNSPECIFIED,对于控件尺寸来说,没有任何参考意义。 */ final int widthSize = MeasureSpec.getSize(widthMeasureSpec); final int widthMode = MeasureSpec.getMode(widthMeasureSpec); if (widthMode != MeasureSpec.EXACTLY) { throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!"); } final int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (heightMode != MeasureSpec.EXACTLY) { throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!"); } //给每一个子view给予相同的空间 final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); } Log.e(TAG, "moving to screen "+mCurScreen); /**滚动到目标坐标*/ scrollTo(mCurScreen * widthSize, 0); } /** * 根据当前布局的位置,滚动到目的页面 */ public void snapToDestination() { /**获取view的宽度*/ final int screenWidth = getWidth(); Log.i(TAG, "screenWidth: " + screenWidth + " screenWidth/2: " + screenWidth/2); Log.i(TAG, "getScrollX():" + getScrollX()); /** * getScrollX():获得滚动后view的横坐标 */ final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth; snapToScreen(destScreen); } public void snapToScreen(int whichScreen) { // 获取有效页面 whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1)); if (getScrollX() != (whichScreen*getWidth())) { final int delta = whichScreen*getWidth()-getScrollX(); mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta)*2); mCurScreen = whichScreen; invalidate(); // 使view重画 } } public void setToScreen(int whichScreen) { whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1)); mCurScreen = whichScreen; scrollTo(whichScreen*getWidth(), 0); } public int getCurScreen() { return mCurScreen; } /** * 由父视图调用,用于通知子视图在必要时更新 mScrollX 和 mScrollY 的值 * 该操作主要用于子视图使用 Scroller 进行动画滚动时。 */ @Override public void computeScroll() { if (mScroller.computeScrollOffset()) {//返回true,表示动画仍在进行,还没有停止 scrollTo(mScroller.getCurrX(), mScroller.getCurrY());// 滚动到目标坐标 postInvalidate(); //使view重画 } } /** * 触摸监听事件 */ @Override public boolean onTouchEvent(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain();//获取mVelocityTracker实例对象 } /**将当前的移动事件传递给mVelocityTracker对象*/ mVelocityTracker.addMovement(event); /**获取当前触摸动作*/ final int action = event.getAction(); final float x = event.getX(); final float y = event.getY(); switch (action) { case MotionEvent.ACTION_DOWN://当向下按时 Log.e(TAG, "event down!"); if (!mScroller.isFinished()){ mScroller.abortAnimation();//Scrooller停止动画行为 } mLastMotionX = x; break; case MotionEvent.ACTION_MOVE://当手指滑动时 int deltaX = (int)(mLastMotionX - x); mLastMotionX = x; /** * scrollBy是将view的内容移动多大的距离 * deltaX:指移动的距离 */ scrollBy(deltaX, 0); break; case MotionEvent.ACTION_UP: Log.e(TAG, "event : up"); // if (mTouchState == TOUCH_STATE_SCROLLING) { final VelocityTracker velocityTracker = mVelocityTracker; /**计算当前速度*/ velocityTracker.computeCurrentVelocity(1000); /**获取当前x方向的速度*/ int velocityX = (int) velocityTracker.getXVelocity(); Log.e(TAG, "velocityX:"+velocityX); if (velocityX > SNAP_VELOCITY && mCurScreen > 0) { //向右滑动并且手指滑动速度大于指定的速度(此时速度的方向为正) // Fling enough to move left Log.e(TAG, "snap left"); snapToScreen(mCurScreen - 1);//滑到前一个页面 } else if (velocityX < -SNAP_VELOCITY && mCurScreen < getChildCount() - 1) {//向左滑动时并且手指滑动的速度也大于指定的速度(此时速度方向为负) // Fling enough to move right Log.e(TAG, "snap right"); snapToScreen(mCurScreen + 1);//滑到后一个页面 } else { snapToDestination(); } if (mVelocityTracker != null) {//释放VelocityTracker对象 mVelocityTracker.recycle(); mVelocityTracker = null; } // } mTouchState = TOUCH_STATE_REST; break; case MotionEvent.ACTION_CANCEL: mTouchState = TOUCH_STATE_REST; break; } return true; } /** * 该方法是用于拦截手势事件的,每个手势事件都会先调用 * 此方法返回false,则手势事件会向子控件传递 * 返回true,则调用onTouchEvent方法 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.e(TAG, "onInterceptTouchEvent-slop:"+mTouchSlop); final int action = ev.getAction(); if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) { return true; } final float x = ev.getX(); final float y = ev.getY(); switch (action) { case MotionEvent.ACTION_MOVE: final int xDiff = (int)Math.abs(mLastMotionX-x); if (xDiff>mTouchSlop) { mTouchState = TOUCH_STATE_SCROLLING; //视图还在移动状态 } break; case MotionEvent.ACTION_DOWN: mLastMotionX = x; mLastMotionY = y; mTouchState = mScroller.isFinished()? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mTouchState = TOUCH_STATE_REST; break; } return mTouchState != TOUCH_STATE_REST; } }
布局文件:main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="@drawable/bg" android:layout_width="fill_parent" android:layout_height="fill_parent" > <cn.flyaudio.android.lichunan.ScrollLayout android:id="@+id/ScrollLayout" android:layout_width="fill_parent" android:layout_height="fill_parent"> <include layout="@layout/menu_center1"/> <include layout="@layout/menu_center2"/> <include layout="@layout/menu_center3"/> </cn.flyaudio.android.lichunan.ScrollLayout> <ImageButton android:id="@+id/menu_tracklist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:background="@drawable/menu_tracklist_imagebutton"/> <include layout="@layout/menu_bottom"/> </RelativeLayout>
发表评论
-
Android Service学习之AIDL, Parcelable和远程服务
2012-06-26 19:33 725AIDL的作用 由于每 ... -
Android的系统的Binder机制(一)
2012-06-21 19:11 670Android系统的Binder机制之一—— ... -
Android的系统的Binder机制(一)
2012-06-21 19:11 768Android系统的Binder机制之一—— ... -
android中修改framework层代码后怎样操作才能看到修改后的效果?
2012-03-30 10:24 41031.下面方法适合真机:下载android源码,然后编译你修改的 ... -
Ubuntu下常用的快捷键
2012-03-19 09:10 0最常用 win+n切换背景颜色风格 alt+tab=不用说了 ... -
Android中全屏无标题设置
2012-03-06 10:29 2380方法一:在java代码中实现 //取消标题 ... -
如何通过wifi调试android程序
2012-03-06 09:53 3347android手机居然可以通过wifi进行程序的调试,太好 ... -
长按home键显示当前任务
2012-03-05 10:33 6350公司给我的任务就是怎么长按home键显示当前任务,刚开始我还以 ... -
android捕获Home键的方法
2012-03-05 10:08 2403Level5以上(包含)中,Activity类中有如下方法: ... -
在32位Ubuntu10.04上编译Android2.3
2012-02-18 11:23 01.安装JDK6 对于Android2.3系统,不要安 ... -
自定义控件---滑动按钮的实现
2012-02-11 16:27 2643package cn.flyaudio.android; ... -
滑动按钮
2012-02-10 19:09 739http://blog.csdn.net/luoyuhhy/a ... -
Android 支持多屏幕机制
2012-02-10 09:20 683在Android上进行开发, ... -
Android UI开发专题
2012-02-06 09:36 923Android UI开发专题 (一) ... -
Launcher(一)关于使用Eclipse调试Launcher的完美解决方法
2012-02-02 19:21 1263由于在Android源码中,很多方法、成员、类、包都被打上@h ... -
android Launcher——ui框架
2012-01-31 22:25 1139android Launcher——ui框架 分 ... -
为程序员量身定制的12个目标
2012-01-15 15:01 619ugmbbc发布于 2012-01-15 ... -
Ubuntu Linux中连接Android真机调试
2012-01-14 14:50 1204首先确保用数据线链接后能识别设备,输入:lsusb,可以看 ... -
如何成为一名Android开发高手
2012-01-04 16:42 1874下面是成为一名真正的Android高手必须掌握和遵循的一些准则 ... -
android GestureDetector功能和使用
2011-12-26 15:36 875android为了增加用户体验 ...
相关推荐
工作区的左右滑动效果是Android Launcher的一个核心功能,让用户能够轻松地在不同的主屏幕之间切换,访问更多的应用程序和小部件。本文将深入解析如何在自定义的Launcher应用中实现这一特性。 首先,我们要了解...
本教程将详细讲解如何修改Launcher,实现左右循环滑动的效果,以及壁纸平滑过渡的功能。 首先,我们关注的是"循环滑动"这一特性。在原生的Android Launcher中,屏幕通常是线性的,用户只能前后滑动,无法实现循环。...
功能是循环滑动界面,同时实现左右循环和上下循环。 关键技术是理解清楚“onInterceptTouchEvent和onTouchEvent”的关系,以及computeScroll和dispatchDraw等。 可以在百度中搜索关键词获取答案。
提取Launcher中的WorkSapce,可以左右滑动切换屏幕页面的类,相应的源码说明可以参考文章:http://blog.csdn.net/Yao_GUET/archive/2011/05/04/6393962.aspx
首先,Android界面的左右滑动切换通常是通过`ViewPager`组件实现的,它允许用户通过横向滑动来浏览多个页面。如果我们想要禁止这种行为,我们需要对`ViewPager`进行定制。以下是一种可能的方法: 1. **自定义...
在Android开发中,实现类似Launcher的左右滑动效果是一项常见的需求,这通常涉及到视图的切换、手势识别以及页面的滚动管理。以下我们将详细探讨如何实现这样的功能。 首先,理解"Android 类似launcher左右滑动...
根据gmailToyou大虾的指点,我修改了workspace的代码,已经成功实现了Launcher的循环滑动,这里将代码共享,以供参考,特别感谢gmailToyou的帮助!
android源代码 http://blog.csdn.net/aomandeshangxiao/article/details/6940670#reply讲解所用部分
在这个实例中,我们可能会用到ViewPager来实现左右滑动的效果。但是,由于题目提到的是“实例一”,可能意味着还有其他非ViewPager的方法,所以我们也需要考虑自定义布局的可能性。 1. 自定义ViewGroup:如果不想...
"MT8788-Android12 Launcher3去掉抽屉实现左右滑动"这个项目就是针对这种需求进行的定制。 首先,我们要理解“去掉抽屉”的含义。在原生Android中,应用抽屉是用户存放和访问所有应用的地方,通常可以通过滑动主...
本文将深入探讨如何实现Android 4.0(ICS,Ice Cream Sandwich)中的Launcher界面循环滑动功能,通过代码分享和解析,帮助开发者更好地理解和实现这一特性。 首先,理解Launcher的工作原理至关重要。Launcher是一个...
搭建步骤: 1 下载代码,导入到myEclipse项目里,发现很多错误。 ...为了访问因此成员,需要改变类搜索顺序,选择项目属性->Java Build Path->Order and Export,把所建立的User Libraries移到Android SDK的上面。...
"launcher3切屏动态效果"是Android系统启动器的核心组件之一,主要负责用户界面的切换与动画呈现。在Android系统中,launcher3是默认的主屏幕应用,它提供了桌面图标、小部件以及应用抽屉等功能。这个源码着重关注的...
下面的这个例子也是从网上找来的,不是自己写的,一直想学习下,但是一直没有写,以前也研究研究的是launcher的页面跳转,launcher修改--左右滑动屏幕切换源码追踪说实话,那个代码有点复杂,所以理解的也不是很透彻...
在Launcher3中,屏幕切换动画可能涉及到View的TranslationX和TranslationY属性的改变,以实现左右滑动切换屏幕的效果。此外,可能还会用到Alpha属性来控制视图的透明度,增加动画的层次感。 接下来,我们关注源码包...
安卓4.4 launcher3源码桌面无法循环滚动,修改pagedView实现
在Android开发中,ViewPager是一个非常重要的组件,常用于实现页面间的滑动切换效果,比如在应用启动器(launcher)中,用户通常会通过左右滑动来浏览不同的屏幕。本篇文章将详细探讨如何利用ViewPager实现类似...
加载Workspace入口在/packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java,想了解Launcher app的启动流程,可以先看看这篇文章,https://www.jianshu.com/p/0b273112cd7e 1、Workspace加载...
为了将所有应用摆在 launcher 第一层,我们需要在 Workspace.java 文件中进行修改。具体来说,我们需要在 removeAllWorkspaceScreens 方法中清空所有工作台屏幕,并将应用程序图标摆放在 launcher 的第一层。 4. ...