Android客户端Path风格界面实现

一、实现方法

Path风格界面一般由菜单、主界面和附属界面组成,菜单用于导航,导航是通过替换主界面来实现;主界面用于承载核心内容;附属界面用于承载子功能,其布局一般为左中右、左中或中右。高级的Path界面有多个上述布局构成,比如Path主页中点击好友可以进入好友的主页,然后还可以返回,其实这是一个层的概念。

         我们把Path风格界面的组成元素定为Page,用于承载并管理Page的容器定义为PageLayer,然后用类似ActivityManager的PageManager管理PageLayer。

         Page类似Android的Activity,同样有onCreate、onNewIntent、onStart、onResume、onPause、onStop、onDestory等生命周期,并提供setContentView、findViewById、startActivity、startActivityForResult等基本方法。

         PageLayer提供设置、切换Page的功能。

         PageManager提供切换Layer、获取当前Page等公开方法

         PageIntent类似Android的Intent,用于指定Page并传递参数

         PageActivity承载整个Path风格界面,Page的生命周期依赖于PageActivity,初始化PageActivity时要指定默认的第一层PageLayer的左中右Page

        

         PageGroup和LayerGroup为非公开类

         PageGroup用于管理和布局Page的layout,并实现切换、动画等功能。

         LayerGroup用于管理Layer的layout,并实现切换、动画等功能。

二、代码

1、  PageIntent.java

public class PageIntent {

    private Class<? extends Page> cls;

    private Bundle extras;

 

    /**

     *

     * @param cls 要启动的Page

     * @param extras 需要传递的参数

     */

    public PageIntent(Class<? extends Page> cls, Bundle extras) {

       this.cls = cls;

       this.extras = extras;

    }

 

    public void setCls(Class<? extends Page> cls) {

       this.cls = cls;

    }

 

    public Class<? extends Page> getCls() {

       return cls;

    }

 

    public void setExtras(Bundle extras) {

       this.extras = extras;

    }

 

    public Bundle getExtras() {

       return extras;

    }

}

2、Page.java

public class Page {

    private static final String TAG = "Page";

    public static final int POSITION_LEFT = 1;

    public static final int POSITION_CENTER = 2;

    public static final int POSITION_RIGHT = 3;

 

    int mPosition;

    PageManager mPageManager;

    PageLayer mPageLayer;

    Context mContext;

    FrameLayout mDecorView;

 

    public Context getContext() {

       return mContext;

    }

 

    /**

     * page被替换时是否释放,如果不释放,在此切回时重用

     * @return

     */

    public boolean destoryWhenReplace() {

       return true;

    }

 

    public void startActivity(Intent intent) {

       mPageManager.startActivity(intent);

    }

 

    public void startActivityForResult(Intent intent, int requestCode) {

       mPageManager.startActivityForResult(this, intent, requestCode);

    }

 

    void activityResult(int requestCode, int resultCode, Intent data) {

       onActivityResult(requestCode, resultCode, data);

    }

 

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

 

    }

 

    protected final void setContentView(int layoutResId) {

       LayoutInflater inflater = (LayoutInflater) mContext

              .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

       View view = inflater.inflate(layoutResId, null);

       mDecorView.addView(view, LayoutParams.FILL_PARENT,

              LayoutParams.FILL_PARENT);

    }

 

    void create(PageManager pageManager, PageLayer pageLayer, Context context,

           PageIntent intent) {

       mPageManager = pageManager;

       mPageLayer = pageLayer;

       mContext = context;

       mDecorView = new FrameLayout(mContext);

       mDecorView.setBackgroundColor(Color.BLACK);

       Log.d(TAG, "create " + this);

       onCreate(context, intent);

    }

 

    public PageLayer getPageLayer() {

       return mPageLayer;

    }

 

    public View findViewById(int id) {

       return mDecorView.findViewById(id);

    }

 

    public String getString(int resId) {

       return mContext.getString(resId);

    }

 

    public Drawable getDrawable(int resId) {

       return mContext.getResources().getDrawable(resId);

    }

 

    public View getContentView() {

       return mDecorView;

    }

 

    public PageManager getPageManager() {

       return mPageManager;

    }

 

    protected void onCreate(Context context, PageIntent intent) {

 

    }

 

    void newIntent(PageIntent intent) {

       Log.d(TAG, "newIntent " + this);

       onNewIntent(intent);

    }

 

    protected void onNewIntent(PageIntent intent) {

 

    }

 

    void start() {

       Log.d(TAG, "start " + this);

       onStart();

    }

 

    protected void onStart() {

 

    }

 

    void resume() {

       Log.d(TAG, "resume " + this);

       onResume();

    }

 

    protected void onResume() {

 

    }

 

    void pause() {

       Log.d(TAG, "pause " + this);

       onPause();

    }

 

    protected void onPause() {

 

    }

 

    void stop() {

       Log.d(TAG, "stop " + this);

       onStop();

    }

 

    protected void onStop() {

 

    }

 

    void destory() {

       Log.d(TAG, "destory " + this);

       onDestory();

    }

 

    protected void onDestory() {

 

    }

 

    boolean backPressed() {

       return onBackPressed();

    }

 

    /**

     * 当返回键按下是出发

     *

     * @return true表示处理过此事件,底层将不再处理

     */

    protected boolean onBackPressed() {

       return false;

    }

}

3、PageLayer.java

public class PageLayer {

    private PageManager mPageManager;

    PageGroup mPageGroup;

    private boolean mDestoryed;

 

    PageLayer(PageManager pageManager, PageIntent leftIntent,

           PageIntent centerIntent, PageIntent rightIntent, int position) {

       mPageManager = pageManager;

       mDestoryed = false;

       Page leftPage = null;

       if (leftIntent != null) {

           leftPage = createPage(leftIntent);

       }

       Page centerPage = createPage(centerIntent);

       Page rightPage = null;

       if (rightIntent != null) {

           rightPage = createPage(rightIntent);

       }

 

       this.mLeftPages = new ArrayList<Page>(1);

       if (leftPage != null) {

           this.mLeftPages.add(leftPage);

       }

 

       this.mCenterPages = new ArrayList<Page>(5);

       this.mCenterPages.add(centerPage);

 

       this.mRightPages = new ArrayList<Page>(1);

       if (rightPage != null) {

           this.mRightPages.add(rightPage);

       }

 

       this.mPosition = position;

       this.mCurrentLeftPage = leftPage;

       this.mCurrentCenterPage = centerPage;

       this.mCurrentRightPage = rightPage;

       this.mLeftVisible = true;

       this.mRightVisible = true;

       mPageGroup = new PageGroup(pageManager.getContext(), this);

    }

 

    private List<Page> mLeftPages;

    private List<Page> mCenterPages;

    private List<Page> mRightPages;

 

    private Page mCurrentLeftPage;

    private Page mCurrentCenterPage;

    private Page mCurrentRightPage;

    private int mPosition;

    private boolean mLeftVisible;

    private boolean mRightVisible;

 

    /**

     * 获取当前Page的位置

     * @return

     */

    public int getPosition() {

       return mPosition;

    }

 

    /**

     * 获取当前Page

     * @return

     */

    public Page getCurrentPage() {

       return getPage(mPosition);

    }

 

    /**

     * 获取指定位置的Page

     * @param position

     * @return

     */

    public Page getPage(int position) {

       if (position == Page.POSITION_LEFT) {

           return mCurrentLeftPage;

       } else if (position == Page.POSITION_RIGHT) {

           return mCurrentRightPage;

       } else if (position == Page.POSITION_CENTER) {

           return mCurrentCenterPage;

       }

       return null;

    }

 

    private void setPage(int position, Page page) {

       Page oldPage = getPage(position);

       if (oldPage != null) {

           if (mPageManager.mCurrentPageLayer == this

                  && this.mPosition == position) {

              if (mPageManager.mActiving) {

                  oldPage.resume();

              }

              oldPage.stop();

           }

           if (oldPage.destoryWhenReplace()) {

              oldPage.destory();

              if (position == Page.POSITION_LEFT) {

                  mLeftPages.remove(oldPage);

              } else if (position == Page.POSITION_CENTER) {

                  mCenterPages.remove(oldPage);

              } else if (position == Page.POSITION_RIGHT) {

                  mRightPages.remove(oldPage);

              }

           }

       }

       if (position == Page.POSITION_LEFT) {

           mCurrentLeftPage = page;

       } else if (position == Page.POSITION_CENTER) {

           mCurrentCenterPage = page;

       } else if (position == Page.POSITION_RIGHT) {

           mCurrentRightPage = page;

       }

 

       if (mPageManager.mCurrentPageLayer == this

              && this.mPosition == position) {

           page.start();

           if (mPageManager.mActiving) {

              page.resume();

           }

       }

    }

 

    private void putInitPage(int position, Page page) {

       if (position == Page.POSITION_LEFT) {

           mLeftPages.add(page);

       } else if (position == Page.POSITION_CENTER) {

           mCenterPages.add(page);

       } else if (position == Page.POSITION_RIGHT) {

           mRightPages.add(page);

       }

    }

 

    private Page getInitPage(int position, Class<?> cls) {

       if (position == Page.POSITION_LEFT) {

           for (Page page : mLeftPages) {

              if (page.getClass() == cls) {

                  return page;

              }

           }

       } else if (position == Page.POSITION_RIGHT) {

           for (Page page : mRightPages) {

              if (page.getClass() == cls) {

                  return page;

              }

           }

       } else if (position == Page.POSITION_CENTER) {

           for (Page page : mCenterPages) {

              if (page.getClass() == cls) {

                  return page;

              }

           }

       }

       return null;

    }

 

    View getView(int position) {

       if (position == Page.POSITION_LEFT && mCurrentLeftPage != null) {

           return mCurrentLeftPage.getContentView();

       } else if (position == Page.POSITION_CENTER

              && mCurrentCenterPage != null) {

           return mCurrentCenterPage.getContentView();

       } else if (position == Page.POSITION_RIGHT && mCurrentRightPage != null) {

           return mCurrentRightPage.getContentView();

       }

       return null;

    }

 

    void resume() {

       Page page = getPage(mPosition);

       page.resume();

    }

 

    void pause() {

       Page page = getPage(mPosition);

       page.resume();

    }

 

    void start() {

       Page page = getPage(mPosition);

       page.start();

       if (mPageManager.mActiving) {

           page.resume();

       }

    }

 

    void stop() {

       Page page = getPage(mPosition);

       if (mPageManager.mActiving) {

           page.pause();

       }

       page.stop();

    }

 

    void destory() {

       if (mDestoryed) {

           return;

       }

       mDestoryed = true;

       stop();

       for (Page leftPage : mLeftPages) {

           if (leftPage != mCurrentLeftPage) {

              leftPage.destory();

           }

       }

 

       mLeftPages.clear();

       for (Page centerPage : mCenterPages) {

           if (centerPage != mCurrentCenterPage) {

              centerPage.destory();

           }

       }

       mCenterPages.clear();

 

       for (Page rightPage : mRightPages) {

           if (rightPage != mCurrentRightPage) {

              rightPage.destory();

           }

       }

       mRightPages.clear();

 

       if (mCurrentLeftPage != null) {

           mCurrentLeftPage.destory();

       }

       if (mCurrentRightPage != null) {

           mCurrentRightPage.destory();

       }

       if (mCurrentCenterPage != null) {

           mCurrentCenterPage.destory();

       }

    }

 

    /**

     * 设置left page是否可见

     * @param visible

     */

    public void setLeftVisible(boolean visible) {

       if (mLeftVisible == visible) {

           return;

       }

       mLeftVisible = visible;

       if (!mDestoryed && mPosition == Page.POSITION_LEFT) {

           gotoPosition(Page.POSITION_CENTER, true);

       }

    }

 

    /**

     * 获取left page是否可见

     * @return

     */

    public boolean isLeftVisible() {

       return mLeftVisible;

    }

 

    /**

     * 设置right page是否可见

     * @param visible

     */

    public void setRightVisible(boolean visible) {

       if (mRightVisible == visible) {

           return;

       }

       mRightVisible = visible;

       if (!mDestoryed && mPosition == Page.POSITION_RIGHT) {

           gotoPosition(Page.POSITION_CENTER, true);

       }

    }

 

    /**

     * 获取right page是否可见

     * @return

     */

    public boolean isRightVisible() {

       return mRightVisible;

    }

 

    /**

     * 切换到指定位置

     * @param position

     * @return

     */

    public boolean gotoPosition(int position) {

       return gotoPosition(position, true);

    }

 

    /**

     * 切换到指定位置

     * @param position

     * @param animation true表示有切换动画

     * @return

     */

    public boolean gotoPosition(int position, boolean animation) {

       if (mDestoryed) {

           throw new RuntimeException("destoryed");

       }

       if (position == this.mPosition) {

           return false;

       }

       if ((position == Page.POSITION_LEFT && (mCurrentLeftPage == null || !mLeftVisible))

              || (position == Page.POSITION_RIGHT && (mCurrentRightPage == null || !mRightVisible))) {

           return false;

       }

       Page newPage = getPage(position);

       if (newPage == null) {

           return false;

       }

       Page oldPage = getPage(this.mPosition);

       if (oldPage == null) {

           return false;

       }

       mPageGroup.gotoPosition(position, animation);

       this.mPosition = position;

       start();

       return true;

    }

 

    /**

     * 设置指定位置的Page

     * @param position

     * @param intent

     * @return

     */

    public boolean setPage(int position, PageIntent intent) {

       if (mDestoryed) {

           throw new RuntimeException("destoryed");

       }

       if (position != Page.POSITION_LEFT && position != Page.POSITION_RIGHT

              && position != Page.POSITION_CENTER) {

           return false;

       }

       Page currentPage = getPage(position);

       if (currentPage != null && currentPage.getClass() == intent.getCls()) {

           currentPage.newIntent(intent);

           return true;

       }

       Page page = null;

       Page initPage = getInitPage(position, intent.getCls());

       if (initPage != null) {

           initPage.newIntent(intent);

           page = initPage;

       }

       if (page == null) {

           page = createPage(intent);

           putInitPage(position, page);

       }

       setPage(position, page);

       mPageGroup.setView(position, page.mDecorView);

       return true;

    }

 

    boolean backPressed() {

       return getPage(mPosition).backPressed();

    }

 

    private Page createPage(PageIntent intent) {

       Class<?> cls = intent.getCls();

       Page newPage = null;

       try {

           newPage = (Page) cls.newInstance();

       } catch (Exception e) {

           throw new RuntimeException(e);

       }

       newPage.create(mPageManager, this, mPageManager.getContext(), intent);

       return newPage;

    }

}

4、PageManager.java

public class PageManager {

    public static final String TAG = "PageManager";

    public static final int ANIMATION_TIME = 1000;

    public static final int SIDE_WIDTH = 60;

    PageLayer mCurrentPageLayer;

    private List<PageLayer> mPageLayers = new ArrayList<PageLayer>();

 

    boolean mActiving = false;

    private PageActivity mActivity;

    private Context mContext;

    LayerGroup mLayerGroup;

 

    PageManager(PageActivity activity, Context context, PageIntent left,

           PageIntent center, PageIntent right) {

       mContext = context;

       mActivity = activity;

       startLayer(left, center, right);

    }

 

    public Context getContext() {

       return mContext;

    }

 

    /**

     * 获取当前Page

     * @return

     */

    public Page getCurrentPage() {

       if (mCurrentPageLayer == null) {

           return null;

       }

       return mCurrentPageLayer.getCurrentPage();

    }

 

    void startActivity(Intent intent) {

       mActivity.startActivity(intent);

    }

 

    void startActivityForResult(Page page, Intent intent, int requestCode) {

       mActivity.startActivityForResult(page, intent, requestCode);

    }

 

    void activityResult(int requestCode, int resultCode, Intent data) {

    }

 

    void resume() {

       mActiving = true;

       mCurrentPageLayer.resume();

    }

 

    void pause() {

       mActiving = false;

       mCurrentPageLayer.pause();

    }

 

    /**

     * 切换到指定Layer

     * @param left

     * @param center

     * @param right

     */

    public void startLayer(PageIntent left, PageIntent center, PageIntent right) {

       int position = Page.POSITION_CENTER;

       PageLayer layer = new PageLayer(this, left, center, right, position);

       mPageLayers.add(layer);

       PageLayer oldLayer = mCurrentPageLayer;

       if (oldLayer != null) {

           oldLayer.stop();

       }

       mCurrentPageLayer = layer;

       mCurrentPageLayer.start();

       if (mLayerGroup == null) {

           mLayerGroup = new LayerGroup(mContext, mCurrentPageLayer);

       } else {

           mLayerGroup.setLayer(mCurrentPageLayer, true);

       }

    }

 

    /**

     * 返回到上一层

     * @return

     */

    public boolean back() {

       int layers = mPageLayers.size();

       if (layers == 1) {

           return false;

       }

       PageLayer prevLayer = mPageLayers.get(layers - 2);

       mPageLayers.remove(layers - 1);

       mCurrentPageLayer.stop();

       PageLayer oldLayer = mCurrentPageLayer;

       mCurrentPageLayer = prevLayer;

       mCurrentPageLayer.start();

       mLayerGroup.setLayer(mCurrentPageLayer, false);

       return true;

    }

 

    boolean backPressed() {

       if (mLayerGroup != null && mLayerGroup.isSwitching()) {

           return true;

       }

       boolean handled = mCurrentPageLayer.backPressed();

       if (!handled && mPageLayers.size() > 1) {

           back();

           handled = true;

       }

       return handled;

    }

 

    void destory() {

       int size;

       while ((size = mPageLayers.size()) > 0) {

           mPageLayers.get(size - 1).destory();

       }

    }

}

5、PageActivity.java

public abstract class PageActivity extends Activity {

    private PageManager mPageManager;

    private Page mRequestPage;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       mPageManager = new PageManager(this, this,

              getPageIntent(Page.POSITION_LEFT),

              getPageIntent(Page.POSITION_CENTER),

              getPageIntent(Page.POSITION_RIGHT));

       setContentView(mPageManager.mLayerGroup);

    }

 

    protected abstract PageIntent getPageIntent(int position);

 

    void startActivityForResult(Page page, Intent intent, int requestCode) {

       mRequestPage = page;

       super.startActivityForResult(intent, requestCode);

    }

 

    @Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

       if (mRequestPage != null) {

           Page page = mPageManager.getCurrentPage();

           if (mRequestPage == page) {

              mRequestPage.onActivityResult(requestCode, resultCode, data);

           }

       }

       mRequestPage = null;

       super.onActivityResult(requestCode, resultCode, data);

    }

 

    @Override

    public void onBackPressed() {

       if (mPageManager.backPressed()) {

           return;

       }

       super.onBackPressed();

    }

 

    @Override

    protected void onDestroy() {

       super.onDestroy();

       mPageManager.destory();

    }

    @Override

    protected void onResume() {

       mPageManager.resume();

       super.onResume();

    }

 

    @Override

    protected void onPause() {

       mPageManager.pause();

       super.onPause();

    }

}

6、PageGroup.java

class PageGroup extends FrameLayout {

    private static final int SNAP_VELOCITY = 1000;

    private final static int TOUCH_STATE_REST = 0;

    private final static int TOUCH_STATE_SCROLLING = 1;

 

    private PageLayer mPageLayer;

    private Rect mTempRect = new Rect();

 

    private View mLeftView;

    private View mCenterView;

    private View mRightView;

    private Scroller mScroller;

    private VelocityTracker mVelocityTracker;

    private int mTouchState = TOUCH_STATE_REST;

    private float mLastMotionX;

    private float mLastMotionY;

    private float mOffsetX;

    private int mTouchSlop;

    private int mMaximumVelocity;

    private boolean mCanDrag = true;

 

    public PageGroup(Context context, PageLayer pageLayer) {

       super(context);

       mPageLayer = pageLayer;

       mLeftView = mPageLayer.getView(Page.POSITION_LEFT);

       mCenterView = mPageLayer.getView(Page.POSITION_CENTER);

       mRightView = mPageLayer.getView(Page.POSITION_RIGHT);

       mScroller = new Scroller(context, new OvershootInterpolator(1.f));

       final ViewConfiguration configuration = ViewConfiguration

              .get(getContext());

       mTouchSlop = configuration.getScaledTouchSlop();

       mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();

       resetCurrentViews();

    }

 

    private void resetCurrentViews() {

       if (mLeftView != null) {

           removeView(mLeftView);

           addView(mLeftView, LayoutParams.FILL_PARENT,

                  LayoutParams.FILL_PARENT);

       }

       if (mRightView != null) {

           removeView(mRightView);

           addView(mRightView, LayoutParams.FILL_PARENT,

                  LayoutParams.FILL_PARENT);

       }

       removeView(mCenterView);

       addView(mCenterView, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);

       resetCurrentViewPosition();

    }

 

    private void resetCurrentViewPosition() {

       if (mLeftView != null) {

           mLeftView.layout(0, 0, getWidth()

           /*- SIDE_WIDTH*/, getHeight());

       }

       if (mRightView != null) {

           mRightView.layout(0/* + SIDE_WIDTH */, 0, getWidth(), getHeight());

       }

       int left = 0;

       switch (mPageLayer.getPosition()) {

       case Page.POSITION_LEFT:

           left = getWidth() - PageManager.SIDE_WIDTH;

           break;

       case Page.POSITION_CENTER:

           left = 0;

           break;

       case Page.POSITION_RIGHT:

           left = PageManager.SIDE_WIDTH - getWidth();

           break;

       }

       mCenterView.layout(left, 0, left + getWidth(), getHeight());

    }

 

    public void setView(int position, View view) {

       if (position == Page.POSITION_LEFT) {

           if (mLeftView != null) {

              removeView(mLeftView);

           }

           mLeftView = view;

       } else if (position == Page.POSITION_RIGHT) {

           if (mRightView != null) {

              removeView(mRightView);

           }

           mRightView = view;

       } else if (position == Page.POSITION_CENTER) {

           if (mCenterView != null) {

              removeView(mCenterView);

           }

           mCenterView = view;

       } else {

           return;

       }

       resetCurrentViews();

    }

 

    private View getView(int position) {

       if (position == Page.POSITION_LEFT) {

           return mLeftView;

       } else if (position == Page.POSITION_RIGHT) {

           return mRightView;

       } else if (position == Page.POSITION_CENTER) {

           return mCenterView;

       }

       return null;

    }

 

    @Override

    public boolean dispatchTouchEvent(MotionEvent ev) {

       if (!mScroller.isFinished()) {

           return true;

       }

       if (mVelocityTracker == null) {

           mVelocityTracker = VelocityTracker.obtain();

       }

       mVelocityTracker.addMovement(ev);

 

       final int action = ev.getAction();

       final float x = ev.getX();

       final Rect tempRect = mTempRect;

       final float y = ev.getY();

       final int xDiff = (int) Math.abs(x - mLastMotionX);

       final int yDiff = (int) Math.abs(y - mLastMotionY);

 

       switch (action) {

       case MotionEvent.ACTION_DOWN:

           mCenterView.getHitRect(tempRect);

           if (!tempRect.contains((int) ev.getX(), (int) ev.getY())) {

              mCanDrag = false;

              break;

           }

           /*

            * If being flinged and user touches, stop the fling. isFinished

            * will be false if being flinged.

            */

           if (!mScroller.isFinished()) {

              mScroller.abortAnimation();

           }

 

           // Remember where the motion event started

           mLastMotionX = x;

           mLastMotionY = y;

           mOffsetX = x - mCenterView.getLeft();

           mCanDrag = true;

 

           mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST

                  : TOUCH_STATE_SCROLLING;

 

           break;

 

       case MotionEvent.ACTION_MOVE: {

           if (!mCanDrag) {

              break;

           }

           int left = (int) (x - mOffsetX);

           boolean xMoved = xDiff > mTouchSlop;

 

           if (xMoved) {

              int r = mCenterView.getWidth() - PageManager.SIDE_WIDTH;

              if (mCenterView.getLeft() >= r && left > r) {

                  break;

              }

              int l = PageManager.SIDE_WIDTH - mCenterView.getWidth();

              if (mCenterView.getLeft() <= l && left < l) {

                  break;

              }

              // Scroll if the user moved far enough along the X axis

              mTouchState = TOUCH_STATE_SCROLLING;

              ev.setAction(MotionEvent.ACTION_CANCEL);

              super.dispatchTouchEvent(ev);

           }

 

           if (mTouchState == TOUCH_STATE_SCROLLING) {

              mCenterView.layout(left, 0, mCenterView.getWidth() + left,

                     mCenterView.getHeight());

              mLastMotionX = x;

              return true;

           }

           break;

       }

       case MotionEvent.ACTION_UP:

           int velocityX = 0;

           if (mTouchState == TOUCH_STATE_SCROLLING) {

              final VelocityTracker velocityTracker = mVelocityTracker;

              velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

              velocityX = (int) velocityTracker.getXVelocity();

           }

           int position = mPageLayer.getPosition();

           if (velocityX > SNAP_VELOCITY) {

              if (mPageLayer.getPosition() == Page.POSITION_RIGHT) {

                  position = Page.POSITION_CENTER;

              } else if (mPageLayer.getPosition() == Page.POSITION_CENTER) {

                  position = Page.POSITION_LEFT;

              }

           } else if (velocityX < -SNAP_VELOCITY) {

              if (mPageLayer.getPosition() == Page.POSITION_LEFT) {

                  position = Page.POSITION_CENTER;

              } else if (mPageLayer.getPosition() == Page.POSITION_CENTER) {

                  position = Page.POSITION_RIGHT;

              }

           } else {

              int left = mCenterView.getLeft();

              float w = mCenterView.getWidth() / 2.f;

              if (mTouchState != TOUCH_STATE_SCROLLING && mCanDrag

                     && position != Page.POSITION_CENTER) {

                  position = Page.POSITION_CENTER;

              } else if (left > w) {

                  position = Page.POSITION_LEFT;

              } else if (left + mCenterView.getWidth() < w) {

                  position = Page.POSITION_RIGHT;

              } else if (left + mCenterView.getWidth() > w && left < w) {

                  position = Page.POSITION_CENTER;

              } else {

                  position = mPageLayer.getPosition();

              }

           }

 

           if (!mPageLayer.gotoPosition(position, true)) {

              gotoPosition(mPageLayer.getPosition(), true);

           }

           if (mVelocityTracker != null) {

              mVelocityTracker.recycle();

              mVelocityTracker = null;

           }

 

           mTouchState = TOUCH_STATE_REST;

 

           break;

       case MotionEvent.ACTION_CANCEL:

           gotoPosition(mPageLayer.getPosition(), true);

           mTouchState = TOUCH_STATE_REST;

       }

       if (mTouchState != TOUCH_STATE_SCROLLING

              && (mCanDrag ? mPageLayer.getPosition() == Page.POSITION_CENTER

                     : true)) {

           if (super.dispatchTouchEvent(ev)) {

              if (mCanDrag && ev.getAction() == MotionEvent.ACTION_MOVE

                     && (xDiff > mTouchSlop || yDiff > mTouchSlop)) {

                  mCanDrag = false;

              }

           }

       }

       return true;

    }

 

    public void gotoPosition(int position, boolean animation) {

       gotoPosition(position, animation, 0);

    }

 

    public void gotoPosition(int position, boolean animation, int velocity) {

       View view = getView(position);

       if (view == null) {

           return;

       }

       int width = getWidth();

       int from = mCenterView.getLeft();

       int to = 0;

       if (position == Page.POSITION_LEFT) {

           from = mCenterView.getLeft();

           to = width - PageManager.SIDE_WIDTH;

       } else if (position == Page.POSITION_RIGHT) {

           from = mCenterView.getLeft();

           to = PageManager.SIDE_WIDTH - width;

       } else {

           from = mCenterView.getLeft();

           to = 0;

       }

       if (animation && width > 0) {

           int time = (int) ((float) (Math.abs(to - from)) / (float) width * PageManager.ANIMATION_TIME);

           mScroller.startScroll(from, 0, to - from, 0, time);

           invalidate();

       } else {

           mCenterView.layout(to, 0, mCenterView.getWidth(),

                  mCenterView.getHeight());

       }

    }

 

    @Override

    protected void dispatchDraw(Canvas canvas) {

       if (mCenterView != null) {

           int left = mCenterView.getLeft();

           if (mLeftView != null) {

              mLeftView.setVisibility(left > 0 ? View.VISIBLE : View.GONE);

           }

           if (mRightView != null) {

              mRightView

                     .setVisibility(left + getWidth() < getWidth() ? View.VISIBLE

                            : View.GONE);

           }

       }

       super.dispatchDraw(canvas);

    }

 

    @Override

    public void computeScroll() {

       boolean changed = false;

       if (mScroller.computeScrollOffset()) {

           int width = mCenterView.getWidth();

           int height = mCenterView.getHeight();

           int left = mScroller.getCurrX();

           // Log.d(TAG, "x:" + mScroller.getCurrX());

           mCenterView.layout(left, 0, width + left, height);

           changed = true;

       }

       if (changed) {

           invalidate();

       }

       super.computeScroll();

    }

 

    @Override

    protected void onLayout(boolean changed, int l, int t, int r, int b) {

       int width = r - l;

       int height = b - t;

       if (mLeftView != null) {

           mLeftView.layout(mLeftView.getLeft(), 0, mLeftView.getLeft()

                  + width /*- SIDE_WIDTH*/, height);

       }

       if (mRightView != null) {

           mRightView.layout(mRightView.getLeft(), 0, mRightView.getLeft()

                  + width /*- SIDE_WIDTH*/, height);

       }

       int left = mCenterView.getLeft();// mScroller.getCurrX();

       mCenterView.layout(left, 0, width + left, height);

    }

}

7、LayerGroup.java

class LayerGroup extends FrameLayout {

    private static final int SWITCH_DURATION = 1000;

    private PageLayer mCurrentPageLayer;

    private PageLayer mTempPageLayer;

    private Scroller mScroller;

    private boolean mEnter;

 

    public LayerGroup(Context context, PageLayer pageLayer) {

       super(context);

       mCurrentPageLayer = pageLayer;

       mScroller = new Scroller(context);

       addView(mCurrentPageLayer.mPageGroup);

    }

 

    @Override

    public boolean dispatchTouchEvent(MotionEvent ev) {

       if (!mScroller.isFinished()) {

           return true;

       }

       return super.dispatchTouchEvent(ev);

    }

 

    public boolean isSwitching() {

       return !mScroller.isFinished();

    }

 

    @Override

    public void computeScroll() {

       if (mScroller.computeScrollOffset()) {

           int x = mScroller.getCurrX();

           mCurrentPageLayer.mPageGroup.layout(x, 0, x + getWidth(),

                  getHeight());

           System.out.println("x:" + x);

           if (mTempPageLayer != null) {

              x = mEnter ? (x - getWidth()) : (x + getWidth());

              mTempPageLayer.mPageGroup.layout(x, 0, x + getWidth(),

                     getHeight());

           }

           invalidate();

       } else {

           switchCompleted();

       }

       super.computeScroll();

    }

 

    private void switchCompleted() {

       if (mTempPageLayer != null) {

           removeView(mTempPageLayer.mPageGroup);

           if (!mEnter) {

              mTempPageLayer.destory();

           }

           mTempPageLayer = null;

       }

    }

 

    public void setLayer(PageLayer pageLayer, boolean enter) {

       if (pageLayer == mCurrentPageLayer) {

           return;

       }

       if (!mScroller.isFinished()) {

           mScroller.abortAnimation();

           switchCompleted();

       }

       mEnter = enter;

       mTempPageLayer = mCurrentPageLayer;

       mCurrentPageLayer = pageLayer;

 

       removeAllViews();

 

       PageGroup currentPageGroup = mCurrentPageLayer.mPageGroup;

       PageGroup tempPageGroup = mTempPageLayer.mPageGroup;

 

       int from;

       int dx;

       if (enter) {

           from = getWidth();

           dx = -getWidth();

       } else {

           from = -getWidth();

           dx = getWidth();

       }

       currentPageGroup.layout(from, 0, from + getWidth(), getHeight());

       tempPageGroup.layout(0, 0, getWidth(), getHeight());

       if (enter) {

           addView(tempPageGroup);

           addView(currentPageGroup);

       } else {

           addView(currentPageGroup);

           addView(tempPageGroup);

       }

       mScroller.startScroll(from, 0, dx, 0, SWITCH_DURATION);

    }

 

    @Override

    protected void onLayout(boolean changed, int left, int top, int right,

           int bottom) {

       int width = right - left;

       int height = bottom - top;

       PageGroup currentPageGroup = mCurrentPageLayer.mPageGroup;

       currentPageGroup.layout(currentPageGroup.getLeft(),

              currentPageGroup.getTop(), currentPageGroup.getLeft() + width,

              currentPageGroup.getTop() + height);

       if (mTempPageLayer != null) {

           PageGroup tempPageGroup = mTempPageLayer.mPageGroup;

           tempPageGroup.layout(tempPageGroup.getLeft(),

                  tempPageGroup.getTop(), tempPageGroup.getLeft() + width,

                  tempPageGroup.getTop() + height);

       }

    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值