android 横向滚动屏幕实现(2)

本案例主要是模仿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);
	}

}















posted @ 2013-03-28 14:20  HappyCode002  阅读(275)  评论(0编辑  收藏  举报