首页 > 代码库 > 如果写一个android桌面滑动切换屏幕的控件(二)

如果写一个android桌面滑动切换屏幕的控件(二)

在viewgroup执行:

public void snapToScreen(int whichScreen) {
		whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
		boolean changingScreens = whichScreen != mCurrentScreen;


		mNextScreen = whichScreen;
		int mScrollX = this.getScrollX();
		final int newX = whichScreen * getWidth();
		final int delta = newX - mScrollX;
		System.out.println("====snapToScreen delta="+delta);
		<strong>mScroller.startScroll(mScrollX, 0, delta, 0, Math.abs(delta) * 2); //这个含义是从x坐标mScrollX的位置滑动delta距离</strong>
		//invalidate非常重要,不然你移动一点页面不能回复原状
		invalidate();
	}


为了使这个动画有效果,我们必须重载computeScroll
@Override
	public void computeScroll() {
		if (<strong>mScroller.computeScrollOffset()</strong>) {
			<strong>scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
		     postInvalidate();</strong>
		} else if (mNextScreen != -1) { <strong>//这个是滑动完成后执行的,这个时候必须set当前的view</strong>
			setCurrentScreen(Math.max(0,
					Math.min(mNextScreen, getChildCount() - 1)));
			mNextScreen = -1;


		}
	}


如果这个viewgroup一次性加载太多子控件,会造成性能的很大影响,为了解决这个问题,我们应该在显示当前的控件,其他的应该visible置为空

这样来处理:

void setCurrentScreen(int index) {
		mCurrentScreen = index;
		resetVisibilityForChildren();
	}
	
	private void resetVisibilityForChildren() {
	    int count = getChildCount();
	    for (int i = 0; i < count; i++) {
	        View child = getChildAt(i);
	        if (Math.abs(mCurrentScreen - i) <= 0) {
	            child.setVisibility(View.VISIBLE);
	        } else {
	            child.setVisibility(View.INVISIBLE);
	        }
	    }
	}

为了滑动的时候能显示下一页,我们必须重写dispatchDraw

@Override
	protected void dispatchDraw(Canvas canvas) {
		int childCount = getChildCount();
		if (childCount == 0) {
			return;
		}


		boolean restore = false;
		int restoreCount = 0;

		final long drawingTime = getDrawingTime();
		final float scrollPos = (float) getScrollX() / getWidth();
		final int leftScreen = (int) scrollPos;
		final int rightScreen = leftScreen + 1;
		if (leftScreen >= 0 && leftScreen < childCount) {
			<strong>drawChild(canvas, getChildAt(leftScreen), drawingTime); //这个会使leftScreen由gone的状态显示出来</strong>
		}
		if  (rightScreen < getChildCount()) {
			drawChild(canvas, getChildAt(rightScreen), drawingTime);
		}

		if (restore) {
			canvas.restoreToCount(restoreCount);
		}

	}

下面来说如何在这个界面上加入dot,来表示当前滑动哪个界面:

在myGroup类里加入:

	public void setmListener(OnViewChangedListener mListener) {
		this.mListener = mListener;
	}
	
	public interface OnViewChangedListener {
	    /**
	     * When view changed.
	     * @param viewIndex index.
	     */
		void onViewChanged(int viewIndex);
	}
    private static final int DEFAULT_POINT_MARGIN = 5;

	/**
     * 更新点点的状态,包括总数和当前位置。
     * @param dotsLayout 用来放置点点的layout.
     * @param total 总数。
     * @param current 当前位置。
     * @param state Bundle,参数扩展,可以为null.
     */
    public static void updateDots(ViewGroup dotsLayout, int total, int current, Bundle state) {
        
        if (total < 0) {
            total = 0;
        }
        
        int lastIndex = -1;
        Object tag = dotsLayout.getTag(R.id.dots_current);
        if (tag != null) {
            lastIndex = (Integer) tag;
        }
        
        int margin = DEFAULT_POINT_MARGIN;
        if (state != null) {
            margin = state.getInt(KEY_POINT_MARGIN, margin);
        }
        
        int childrenNum = dotsLayout.getChildCount();
        
        for (int i = childrenNum; i < total; i++) {
            ImageView pointView = new ImageView(dotsLayout.getContext());
            pointView.setImageResource(R.drawable.dot);
            dotsLayout.addView(pointView);
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) pointView.getLayoutParams();
            params.leftMargin = margin;
            params.rightMargin = margin;
        }
        
        for (int i = childrenNum - 1; i >= total; i--) {
            dotsLayout.removeViewAt(i);
        }
        
        if (current == lastIndex) {
            return;
        }
        
        if (lastIndex >= 0 && lastIndex < total) {
            ImageView pointView = (ImageView) dotsLayout.getChildAt(lastIndex);
            pointView.setImageResource(R.drawable.dot);
        }
        
        if (current >= 0 && current < total) {
            ImageView pointView = (ImageView) dotsLayout.getChildAt(current);
            pointView.setImageResource(R.drawable.dot_current);
        }
        
        dotsLayout.setTag(R.id.dots_current, current);
    }
    
	public interface WorkspaceSnapListener {
	    
		void onSnapToScreen(MyGroup workspace, int whichScreen);
	}

	public void setSnapListener(WorkspaceSnapListener listener) {
		snapListener = listener;
	}

@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			
		} else if (mNextScreen != -1) {
	
			<strong>if (mListener != null) {
				mListener.onViewChanged(mCurrentScreen);
			}</strong>
		}
	}
public void snapToScreen(int whichScreen) {
		
		
		<strong>if (snapListener != null) {
			snapListener.onSnapToScreen(this, whichScreen);
		}</strong>
	}


在MainActivity的layout中加入:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/MainRoot"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

    <com.ringcentral.android.utils.ui.widget.MyGroup
       android:background="@drawable/help_background_selector"
        android:id="@+id/workspace"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />
    
     <LinearLayout android:id="@+id/dots_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="28dip"
        android:layout_gravity="bottom|center_horizontal"
        android:orientation="horizontal"/>

</FrameLayout>

点的画法:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" >
    <size android:width="6dip" android:height="6dip"/>
    <solid android:color="#7fffffff"/>
</shape>


oncreate:

@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
        final ViewGroup dotsLayout = (ViewGroup) findViewById(R.id.dots_layout);

		final int[] images = new int[]{R.drawable.help_01,R.drawable.help_02,R.drawable.help_03};
		final MyGroup myGroup = (MyGroup) findViewById(R.id.workspace);
		
		final Bundle dotsState = new Bundle();
		int margin = getResources().getDimensionPixelSize(R.dimen.workspace_dot_margin);
		dotsState.putInt(MyGroup.KEY_POINT_MARGIN, margin);
		MyGroup.updateDots(dotsLayout, images.length, 0, dotsState);

	        
		for (int i = 0; i < 3; i++) {
			final View item = getLayoutInflater().inflate(
					R.layout.introduction_item_test, null);

			myGroup.addView(item);
			final ImageView imageView = (ImageView) item
					.findViewById(R.id.introduction_image_view);
			try {
				imageView.setImageResource(images[i]);
			} catch (OutOfMemoryError e) {
			}

		}
        
		myGroup.setmListener(new OnViewChangedListener() {

            @Override
            public void onViewChanged(int viewIndex) {
                myGroup.updateDots(dotsLayout, images.length, viewIndex, dotsState);
            }
        });
		
		myGroup.setSnapListener(new WorkspaceSnapListener() {

			@Override
			public void onSnapToScreen(MyGroup workspace, int whichScreen) {
				myGroup.updateDots(dotsLayout, images.length, whichScreen, dotsState);

				
			}
		});
	}

效果图:



代码:http://download.csdn.net/detail/baidu_nod/7731855