到此,就能編譯Launcher進行安裝了。 html
注意:安裝最好找一個原生的系統調試,第三方改過的系統,會把launcher請求的一些原生信息改了,這樣會致使launcher報錯。好比我就遇到過這個問題: java
final Cursor c = contentResolver.query(LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);//這個地飯去請求launcher的默認配置,在huawei的系統上面請求這個,獲得的c是null
<resources> <style name="Theme"> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowShowWallpaper">true</item> </style> </resources>這兩套方案實際是同樣的,都達到在Activity後面顯示桌面背景的效果。
private void updateWallpaperOffset(int scrollRange) { IBinder token = getWindowToken(); if (token != null) { mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 ); mWallpaperManager.setWallpaperOffsets(getWindowToken(), Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0); } }
這個方法會在onTouchEvent事件中調用,也就是說,當手勢操做了事後,就調用這個方法來更新壁紙的偏移量,這樣就達到了壁紙滾動的效果。 android
完了,Launcher的獲取壁紙的邏輯就清晰了,首先配置Activity爲透明,並配置Activity的後面顯示桌面背景(android:windowShowWallpaper = true的做用,這並非在後面顯示桌面哦,是配置activity的背景爲桌面背景),當Activity的控件滑動的時候,調用WallpaperManager平移壁紙,就完成壁紙的滾動。 git
有一哥們,感受Launcher的刷動效果很不錯,因而把這一塊摳了出來,摳得很漂亮,而且加上了桌面背景效果,下載戳這https://github.com/sevenler/ScrollLayout_From_Launcher.git github
這個哥們也寫了相關Launcher的幾篇博客:http://blog.csdn.net/yao_guet/article/details/6572739 app
//計算每一個子CellLayout的佈局大小 框架
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // ..... // The children are given the same width and height as the scrollLayout final int count = getChildCount(); for (int i = 0; i < count; i++) { getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); } scrollTo(mCurScreen * width, 0); }
//將CellLayout順序地佈局起來 佈局
protected void onLayout(boolean changed, int l, int t, int r, int b) { //..... int childLeft = 0; final int childCount = getChildCount(); for (int i=0; i<childCount; i++) { final View childView = getChildAt(i); if (childView.getVisibility() != View.GONE) { final int childWidth = childView.getMeasuredWidth(); childView.layout(childLeft, 0, childLeft+childWidth, childView.getMeasuredHeight()); childLeft += childWidth; } } updateWallpaperOffset(); }佈局完成以後,重點來了,監聽手勢來滑動。代碼集中在下面兩個方法中:
public boolean onInterceptTouchEvent(MotionEvent ev) { 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; //判斷Scroller滾動狀態設置滾動狀態 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; }
public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub //用於計算手勢的滑動偏移量 if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); final int action = event.getAction(); final float x = event.getX(); final float y = event.getY(); switch (action) { ..... case MotionEvent.ACTION_MOVE://使用scroller來滾動 int deltaX = (int)(mLastMotionX - x); mLastMotionX = x; scrollBy(deltaX, 0); updateWallpaperOffset(); break; case MotionEvent.ACTION_UP://根據手勢滑動的偏移量來肯定是滾動到下一頁仍是上一頁,或者是滾動回當前頁 Log.e(TAG, "event : up"); final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000); 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) { mVelocityTracker.recycle(); mVelocityTracker = null; } mTouchState = TOUCH_STATE_REST; break; case MotionEvent.ACTION_CANCEL: mTouchState = TOUCH_STATE_REST; break; } return true; }
//使用下面這幾句話讀取應用列表 final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); final PackageManager packageManager = mContext.getPackageManager(); List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0); //將應用列表排序 Collections.sort(apps, new ResolveInfo.DisplayNameComparator(packageManager));
Launcher分析相關的一些博客 ui
http://www.cnblogs.com/Hwangroid/archive/2011/12/08/2281286.html spa
http://blog.csdn.net/aomandeshangxiao/article/category/888680