本案例主要是模仿android launcher 实现加载应用程序,横向滚动屏幕,点击启动应用,可以拟补Gridview不能横向滚动缺陷
源码下载地址:点击打开链接
效果图:
项目目录:
主要代码:
package com.sample.launcher.home; import java.util.Collections; import java.util.List; import android.app.Activity; import android.app.SearchManager; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.GridView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; public class LauncherHomeActivity extends Activity { private ScrollLayout mScrollLayout; private static final float APP_PAGE_SIZE = 16.0f; private Context mContext; private PointView pv; private final BroadcastReceiver mWallpaperReceiver = new WallpaperIntentReceiver(); private final BroadcastReceiver mApplicationsReceiver = new ApplicationsIntentReceiver(); private int PageCount; private List<ResolveInfo> apps; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER); mContext = this; setContentView(R.layout.main); loadApps(); bindApps(); registerIntentReceivers(); } private void loadApps() { final PackageManager packageManager = getPackageManager(); final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); // get all apps apps = packageManager.queryIntentActivities(mainIntent, 0); Collections.sort(apps, new ResolveInfo.DisplayNameComparator(packageManager)); // the total pages PageCount = (int)Math.ceil(apps.size()/APP_PAGE_SIZE); } private void bindApps(){ pv=(PointView)findViewById(R.id.PointLayput); mScrollLayout = (ScrollLayout)findViewById(R.id.LauncherLayout); pv.setPageCount(PageCount); mScrollLayout.setPointView(pv); for (int i=0; i<PageCount; i++) { GridView appPage = new GridView(this); // get the "i" page data appPage.setAdapter(new AppAdapter(this, apps, i)); appPage.setNumColumns(4); appPage.setOnItemClickListener(listener); // LayoutParams params=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); mScrollLayout.addView(appPage); } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, Menu.FIRST, 0, "Setting").setIntent(new Intent(android.provider.Settings.ACTION_SETTINGS)); menu.add(0, Menu.FIRST+1, 0, "unstall Apps"); menu.add(0, Menu.FIRST+2, 0, "Aboat Phone").setIntent(new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS)); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case Menu.FIRST+1: Intent intent = new Intent("/"); ComponentName cm = new ComponentName("com.android.settings","com.android.settings.ManageApplications"); intent.setComponent(cm); intent.setAction("android.intent.action.VIEW"); startActivity(intent); return true; } return super.onOptionsItemSelected(item); } /** * Registers various intent receivers. The current implementation registers * only a wallpaper intent receiver to let other applications change the * wallpaper. */ private void registerIntentReceivers() { IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); registerReceiver(mWallpaperReceiver, filter); filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); registerReceiver(mApplicationsReceiver, filter); } private OnItemClickListener listener = new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ResolveInfo appInfo = (ResolveInfo)parent.getItemAtPosition(position); Intent mainIntent = mContext.getPackageManager() .getLaunchIntentForPackage(appInfo.activityInfo.packageName); mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { // launcher the package mContext.startActivity(mainIntent); } catch (ActivityNotFoundException noFound) { Toast.makeText(mContext, "Package not found!", Toast.LENGTH_SHORT).show(); } } }; /** * Receives intents from other applications to change the wallpaper. */ private class WallpaperIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { getWindow().setBackgroundDrawable(new ClippedDrawable(getWallpaper())); } } /** * Receives notifications when applications are added/removed. */ private class ApplicationsIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { loadApps(); bindApps(); } } /** * When a drawable is attached to a View, the View gives the Drawable its dimensions * by calling Drawable.setBounds(). In this application, the View that draws the * wallpaper has the same size as the screen. However, the wallpaper might be larger * that the screen which means it will be automatically stretched. Because stretching * a bitmap while drawing it is very expensive, we use a ClippedDrawable instead. * This drawable simply draws another wallpaper but makes sure it is not stretched * by always giving it its intrinsic dimensions. If the wallpaper is larger than the * screen, it will simply get clipped but it won't impact performance. */ private class ClippedDrawable extends Drawable { private final Drawable mWallpaper; public ClippedDrawable(Drawable wallpaper) { mWallpaper = wallpaper; } @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); // Ensure the wallpaper is as large as it really is, to avoid stretching it // at drawing time mWallpaper.setBounds(left, top, left + mWallpaper.getIntrinsicWidth(), top + mWallpaper.getIntrinsicHeight()); } public void draw(Canvas canvas) { mWallpaper.draw(canvas); } public void setAlpha(int alpha) { mWallpaper.setAlpha(alpha); } public void setColorFilter(ColorFilter cf) { mWallpaper.setColorFilter(cf); } public int getOpacity() { return mWallpaper.getOpacity(); } } @Override protected void onDestroy() { unregisterReceiver(mWallpaperReceiver); unregisterReceiver(mApplicationsReceiver); super.onDestroy(); } }
package com.sample.launcher.home; import android.app.WallpaperManager; import android.content.Context; import android.os.IBinder; 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对手势进行分析处理,以及分屏显示,移动壁纸操作 * @author Andy * */ 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; private WallpaperManager mWallpaperManager; PointView pv; int lastScreen; public ScrollLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ScrollLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mWallpaperManager = WallpaperManager.getInstance(context); mScroller = new Scroller(context); mCurScreen = mDefaultScreen; mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } public void setPointView(PointView pv){ this.pv=pv; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.e(TAG, "onLayout"); // if (changed) { 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(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.e(TAG, "onMeasure"); super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int width = 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!"); } // 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); } // Log.e(TAG, "moving to screen "+mCurScreen); scrollTo(mCurScreen * width, 0); } /** * According to the position of current layout * scroll to the destination page. */ public void snapToDestination() { final int screenWidth = getWidth(); final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth; snapToScreen(destScreen); } public void snapToScreen(int whichScreen) { // get the valid layout page 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(); // Redraw the layout } } 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; } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); updateWallpaperOffset(); postInvalidate(); } } @Override public boolean onTouchEvent(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); final int action = event.getAction(); final float x = event.getX(); lastScreen=mCurScreen; switch (action) { case MotionEvent.ACTION_DOWN: Log.e(TAG, "event down!"); if (!mScroller.isFinished()){ mScroller.abortAnimation(); } mLastMotionX = x; break; case MotionEvent.ACTION_MOVE: int deltaX = (int)(mLastMotionX - x); mLastMotionX = x; scrollBy(deltaX, 0); updateWallpaperOffset(); break; case MotionEvent.ACTION_UP: Log.e(TAG, "event : up"); // if (mTouchState == TOUCH_STATE_SCROLLING) { 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; if(mCurScreen>lastScreen){ pv.fromRighttoLeft(); } else if(mCurScreen<lastScreen){ pv.fromLefttoRight(); } break; case MotionEvent.ACTION_CANCEL: mTouchState = TOUCH_STATE_REST; break; } return true; } @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; } private void updateWallpaperOffset() { int scrollRange = getChildAt(getChildCount() - 1).getRight() - getWidth(); IBinder token = getWindowToken(); if (token != null) { mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 ); mWallpaperManager.setWallpaperOffsets(getWindowToken(), Math.max(0.f, Math.min(getScrollX()/(float)scrollRange, 1.f)), 0); } } }
package com.sample.launcher.home; import java.security.acl.LastOwnerException; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.provider.MediaStore; import android.util.AttributeSet; import android.util.Log; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.ViewFlipper; import android.widget.FrameLayout.LayoutParams; import android.view.GestureDetector; import android.view.Gravity; import android.view.MotionEvent; import android.view.GestureDetector.OnGestureListener; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; public class PointView extends FrameLayout{ // private int width,height; private int index=0,PageCount=0; private Context mContext; private Bitmap NormalPoint,SelectPoint; private LinearLayout layout; private ImageView lastsel,currentsel; // private ImageView[] points=new ImageView[15]; public PointView(Context context, AttributeSet attrs) { super(context, attrs); setView(); } public PointView(Context c) { super(c); setView(); } public void setPageCount(int PageCount) { this.PageCount = PageCount; if(layout==null) layout=(LinearLayout)findViewById(R.id.ContainerLayput); for (int j = 0; j < PageCount; j++) { ImageView p=(ImageView)findViewById(R.id.point1+j); p.setVisibility(View.VISIBLE); if (j == 0) { p.setImageBitmap(SelectPoint); } else { p.setImageBitmap(NormalPoint); } } /*// 将点点动态加入Linerlayout. for (int j = 0; j < PageCount; j++) { ImageView imageview = new ImageView(mContext); if (j == 0) { imageview.setImageBitmap(SelectPoint); } else { imageview.setImageBitmap(NormalPoint); } RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); layout.addView(imageview, params); } addView(layout);*/ } private void setView(){ mContext = getContext(); /*// width = getResources().getDisplayMetrics().widthPixels; layout = new LinearLayout(mContext); layout.setGravity(Gravity.CENTER_HORIZONTAL);//Gravity.BOTTOM|*/ NormalPoint= BitmapFactory.decodeResource(getResources(), R.drawable.page_off); SelectPoint = BitmapFactory.decodeResource(getResources(), R.drawable.page_on); } private boolean IsLeftEnable=false; private boolean IsRightEnable=true; private void isEnd(){ Log.d("msg", "index= "+index); if(index<=0){ IsRightEnable=true; IsLeftEnable=false; }else if(index>=PageCount-1){ IsRightEnable=false; IsLeftEnable=true; } // Log.d("msg", "IsRightEnable= "+IsRightEnable+" IsLeftEnable "+IsLeftEnable); } public void fromLefttoRight() { isEnd(); if (IsLeftEnable){ lastAnim(); index--; nextAnim(); } } public void fromRighttoLeft() { isEnd(); if (IsRightEnable){ lastAnim(); index++; nextAnim(); } } private void lastAnim() { // Log.e("msg", "layout= "+layout); lastsel = (ImageView) layout.getChildAt(index); } private void nextAnim() { // Log.e("msg", "curindex"+index); currentsel = (ImageView) layout.getChildAt(index); currentsel.setImageBitmap(SelectPoint); lastsel.setImageBitmap(NormalPoint); } }