大家看这篇文章的时候,可能已经看过在launcher 2.1上实现2.2的屏幕标记(http://gqdy365.iteye.com/blog/897636),使用一个imageView显示不同的图片,看一下android里面launcher2里面源代码的实现,在drawable文件夹里面,可以找到一个home_arrows_left.xml的文件,内容如下:
<?xml version="1.0" encoding="utf-8"?> <level-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:maxLevel="0" android:drawable="@android:color/transparent" /> <item android:maxLevel="1" android:drawable="@drawable/home_arrows_left_1" /> <item android:maxLevel="2" android:drawable="@drawable/home_arrows_left_2" /> <item android:maxLevel="3" android:drawable="@drawable/home_arrows_left_3" /> <item android:maxLevel="4" android:drawable="@drawable/home_arrows_left_4" /> </level-list>
同时,在launcher.xml文件中,
<ImageView android:id="@+id/previous_screen" android:layout_width="93dip" android:layout_height="@dimen/button_bar_height" android:layout_gravity="bottom|left" android:layout_marginLeft="6dip" android:scaleType="center" android:src="@drawable/home_arrows_left" android:onClick="previousScreen" android:focusable="true" android:clickable="true" />
mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen); mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen); Drawable previous = mPreviousView.getDrawable(); Drawable next = mNextView.getDrawable(); mWorkspace.setIndicators(previous, next);
通过代码获取这个两旁的图片,然后我们再看一看在workspace.java里面的setIndicator()方法,
void setIndicators(Drawable previous, Drawable next) { mPreviousIndicator = previous; mNextIndicator = next; previous.setLevel(mCurrentScreen); next.setLevel(mCurrentScreen); }让我们找到mCurrentScreen这个参数的定义(73行):
private int mCurrentScreen;
定义的一个整数,对应着home_arrows_left.xml里面的maxLevel,不同的参数ImageView上面显示不同的图片,用以标记页面。
在上面的launcher代码中,有android:onClick="previousScreen" 注册了imageView的点击相应事件,在launcher.java中,对应的代码如下:
@SuppressWarnings({"UnusedDeclaration"}) public void previousScreen(View v) { if (!isAllAppsVisible()) { mWorkspace.scrollLeft(); } } @SuppressWarnings({"UnusedDeclaration"}) public void nextScreen(View v) { if (!isAllAppsVisible()) { mWorkspace.scrollRight(); } }我们继续追踪,在workspace.java代码中的scrollLeft和scrollRight()方法的代码:
public void scrollLeft() { clearVacantCache(); if (mScroller.isFinished()) { if (mCurrentScreen > 0) snapToScreen(mCurrentScreen - 1); } else { if (mNextScreen > 0) snapToScreen(mNextScreen - 1); } } public void scrollRight() { clearVacantCache(); if (mScroller.isFinished()) { if (mCurrentScreen < getChildCount() -1) snapToScreen(mCurrentScreen + 1); } else { if (mNextScreen < getChildCount() -1) snapToScreen(mNextScreen + 1); } }先判断是否滑动到头,然后跳转到目标屏,snapToScreen()方法代码也在workspace中,代码如下:
private void snapToScreen(int whichScreen, int velocity, boolean settle) { //if (!mScroller.isFinished()) return; whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); clearVacantCache(); enableChildrenCache(mCurrentScreen, whichScreen); mNextScreen = whichScreen; mPreviousIndicator.setLevel(mNextScreen); mNextIndicator.setLevel(mNextScreen); enableDragLayerChildrenCache(); View focusedChild = getFocusedChild(); if (focusedChild != null && whichScreen != mCurrentScreen && focusedChild == getChildAt(mCurrentScreen)) { focusedChild.clearFocus(); } final int screenDelta = Math.max(1, Math.abs(whichScreen - mCurrentScreen)); final int newX = whichScreen * getWidth(); final int delta = newX - mScrollX; int duration = (screenDelta + 1) * 100; if (!mScroller.isFinished()) { mScroller.abortAnimation(); } if (settle) { mScrollInterpolator.setDistance(screenDelta); } else { mScrollInterpolator.disableSettle(); } velocity = Math.abs(velocity); if (velocity > 0) { duration += (duration / (velocity / BASELINE_FLING_VELOCITY)) * FLING_VELOCITY_INFLUENCE; } else { duration += 100; } awakenScrollBars(duration); mScroller.startScroll(mScrollX, 0, delta, 0, duration*2/3); invalidate(); }