一、实现方法
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); } } } |