launcher修改--页面标记实现原理(代码追踪)

         大家看这篇文章的时候,可能已经看过在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" />

引用了这个文件,但是他真正在代码中是如何实现的哪,在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();
    }

这就是其实现的基本过程。



  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值