正文  UI设计 > Launcher >

launcher修改--页面标记实现原理

使用一个imageView显示不同的图片,看一下android里面launcher2里面源代码的实现,在drawable文件夹里面,可以找到一个home_arrows_left.xml的文件,内容如下:<?xml version="1.0" encoding="utf-8"?> <leve......

使用一个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" <span style="white-space: pre;">                                            
        </span>android:layout_height="@dimen/button_bar_height"  
        android:layout_gravity="bottom|left" <span style="white-space: pre;">  
                </span>android:layout_marginLeft="6dip"  
        android:scaleType="center" <span style="white-space: pre;">  
                </span>android:src="@drawable/home_arrows_left"  
        android:onClick="previousScreen"  <span style="white-space: pre;">  
                </span>android:focusable="true"  
        android:clickable="true" />  
 
引用了这个文件,但是他真正在代码中是如何实现的哪,在launcher.java中的setupViews()方法中,有一下代码:
 
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();  
    }  
 
这就是其实现的基本过程。