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);
}
}

浙公网安备 33010602011771号