自定义控件之(上下左右)侧滑页面
1.效果图(还有顶部及底部就省略)
2.代码实现
1)java代码
/** * Created by 刘强lq * * 自定义控件 上下左右滑出界面 */ public class SliderPager extends FrameLayout { //右边侧滑 public static final int MODEL_RIGHT = 0; //左边侧滑 public static final int MODEL_LEFT = 1; //顶部滑出 public static final int MODEL_TOP = 2; //低部滑出 public static final int MODEL_BUTTOM = 3; /** * 存放主页内容的View */ private ViewGroup mContentView; /** * 存放侧滑栏内容的View */ private ViewGroup mSiderView; /** * 存放侧滑栏内容View宽 */ private int mSiderViewWidth; /** * 存放侧滑栏内容View高 */ private int mSiderViewHeight; /** * SliderPager布局的宽 */ private int mSliderPagerWidth; /** * SliderPager布局的高 */ private int mSliderPagerHeight; /** * 侧滑栏显示的模式 */ private int mSlidingModel; /** * 显示部分 */ private int mSlidingShowLeftOrRightValue = 0; /** * 平滑者 */ private Scroller mScroller; /** * 侧滑页面是否打开 默认是关闭的状态 */ private boolean mIsOpenPager = false; /** * 如果mContentView中存在ViewPager的话 针对于左右滑动 */ private ViewPager mViewPager; /** * 记录当前mViewPager选中的第几个item(如果存在ViewPager的话) */ private int mCurrentViewPagerPosition = 0; /** * 如果mSiderView中存在ListView的话 针对于上下滑动 */ private ListView mListView; public SliderPager(Context context) { this(context, null); } public SliderPager(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SliderPager(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScroller = new Scroller(context); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SliderPager); int indexCount = typedArray.getIndexCount(); for (int i = 0; i < indexCount; i++) { int index = typedArray.getIndex(i); switch (index) { case R.styleable.SliderPager_slidingModel: mSlidingModel = typedArray.getInt(index, 0); break; case R.styleable.SliderPager_slidingShowLeftOrRight: mSlidingShowLeftOrRightValue = typedArray.getDimensionPixelSize(index, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; default: break; } } typedArray.recycle(); } /** * 孩子View的定位 */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); switch (mSlidingModel) { case 0: //侧滑在右边 mSiderView.layout(mSliderPagerWidth, 0, mSliderPagerWidth + mSiderViewWidth, mSiderViewHeight); break; case 1: //侧滑在左边 mSiderView.layout(0 - mSiderViewWidth, 0, 0, mSiderViewHeight); break; case 2://侧滑在上边 mSiderView.layout(0, 0 - mSiderViewHeight, mSliderPagerWidth, 0); break; case 3://侧滑在下边 mSiderView.layout(0, mSiderViewHeight, mSliderPagerWidth, mSliderPagerHeight + mSiderViewHeight); break; default: break; } } /** * 获取宽高 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mSiderViewWidth = mSiderView.getMeasuredWidth() - mSlidingShowLeftOrRightValue; mSiderViewHeight = mSiderView.getMeasuredHeight(); mSliderPagerWidth = getMeasuredWidth(); mSliderPagerHeight = getMeasuredHeight(); } /** * 加载布局完后回调 */ @Override protected void onFinishInflate() { super.onFinishInflate(); mContentView = (ViewGroup) getChildAt(0); //如果mContentView中包含ViewPager 取出 for (int i = 0; i < mContentView.getChildCount(); i++) { View childView = mContentView.getChildAt(i); if (childView instanceof ViewPager) { mViewPager = (ViewPager) childView; } } mSiderView = (ViewGroup) getChildAt(1); //如果mSiderView中包含ListView 取出 for (int i = 0; i < mSiderView.getChildCount(); i++) { View childView = mSiderView.getChildAt(i); if (childView instanceof ListView) { mListView = (ListView) childView; } } mContentView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Log.e("liuqiang", "isOpenPager:" + mIsOpenPager); if (mIsOpenPager) { closeSlidePager(); } } }); if (mViewPager != null) { mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { mCurrentViewPagerPosition = position; } @Override public void onPageSelected(int position) { mCurrentViewPagerPosition = position; } @Override public void onPageScrollStateChanged(int state) { } }); } } /** * 记录手指按下开始的X轴的位置 */ private float mStartX; /** * 记录手指按下开始的Y轴的位置 */ private float mStartY; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mStartX = event.getX(); mStartY = event.getY(); break; case MotionEvent.ACTION_MOVE: float endX = event.getX(); float endY = event.getY(); //得到X轴的偏移量 int distanceX = (int) (endX - mStartX); int scrollToX = getScrollX() - distanceX; //得到Y轴的偏移量 int distanceY = (int) (endY - mStartY); int scrollToY = getScrollY() - distanceY; switch (mSlidingModel) { case 0://从右往左 if (scrollToX < -50) { scrollToX = 0; } else if (scrollToX > mSiderViewWidth) { scrollToX = mSiderViewWidth; } scrollTo(scrollToX, getScrollY()); break; case 1://从左往右 if (scrollToX > 50) { scrollToX = 0; } else if (scrollToX < -mSiderViewWidth) { scrollToX = -mSiderViewWidth; } scrollTo(scrollToX, getScrollY()); break; case 2://从上往下 if (scrollToY > 50) { scrollToY = 0; } else if (scrollToY < -mSiderViewHeight) { scrollToY = -mSiderViewHeight; } scrollTo(getScrollX(), scrollToY); break; case 3://从下往上 if (scrollToY < -50) { scrollToY = 0; } else if (scrollToY > mSiderViewHeight) { scrollToY = mSiderViewHeight; } scrollTo(getScrollX(), scrollToY); break; default: break; } mStartX = endX; mStartY = endY; break; case MotionEvent.ACTION_UP: int scrollX = getScrollX(); int scrollY = getScrollY(); switch (mSlidingModel) { case 0: if (scrollX > mSiderViewWidth / 2) { mScroller.startScroll(getScrollX(), getScrollY(), mSiderViewWidth - getScrollX(), getScrollY() , Math.abs(mSiderViewWidth - getScrollX())); mIsOpenPager = true; mIntercept = false; } else { mScroller.startScroll(getScrollX(), getScrollY(), 0 - getScrollX(), getScrollY(), Math.abs(0 - getScrollX())); mIsOpenPager = false; mIntercept = false; } break; case 1: if (scrollX < -(mSiderViewWidth / 2)) { mScroller.startScroll(getScrollX(), getScrollY(), -mSiderViewWidth - getScrollX(), getScrollY(), Math.abs(-mSiderViewWidth - getScrollX())); mIsOpenPager = true; mIntercept = false; } else { mScroller.startScroll(getScrollX(), getScrollY(), 0 - getScrollX(), getScrollY(), Math.abs(0 - getScrollX())); mIsOpenPager = false; mIntercept = false; } break; case 2: if (scrollY < -(mSiderViewHeight / 2)) { mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), -mSiderViewHeight - getScrollY(), Math.abs(-mSiderViewHeight - getScrollY())); mIsOpenPager = true; mIntercept = false; } else { mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), 0 - getScrollY(), Math.abs(0 - getScrollY())); mIsOpenPager = false; mIntercept = false; } break; case 3: if (scrollY > mSiderViewHeight / 2) { mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), mSiderViewHeight - getScrollY() , Math.abs(mSiderViewHeight - getScrollY())); mIsOpenPager = true; mIntercept = false; } else { mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), 0 - getScrollY(), Math.abs(0 - getScrollY())); mIsOpenPager = false; mIntercept = false; } break; default: break; } invalidate(); break; } return onInterceptTouchEvent(event); } /** * mScrollerd的回调 */ @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } } /** * 事件拦截 记录手指按下开始的X,Y轴的位置 */ private float mInterceptStartX; private float mInterceptStartY; /** * 事件是否拦截 默认不拦截 */ private boolean mIntercept = false; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mInterceptStartX = ev.getX(); mInterceptStartY = ev.getY(); break; case MotionEvent.ACTION_MOVE: float interceptEndX = ev.getX(); float interceptEndY = ev.getY(); int distanceX = (int) (interceptEndX - mInterceptStartX); int distanceY = (int) (interceptEndY - mInterceptStartY); //对每一个滑动的模式进行拦截判断 switch (mSlidingModel) { case 0: //从右滑出 if (mIsOpenPager) { //要关闭的时候 if (distanceX > 0) { mIntercept = true; } else if (distanceX < 0) { mIntercept = false; } else if (Math.abs(distanceY) > 50) { mIntercept = false; } } else { //要打开的时候 if (distanceX > 0) { mIntercept = false; } else if (distanceX < 0) { if (mViewPager != null) { if (mCurrentViewPagerPosition == mViewPager.getChildCount()) { mIntercept = true; } else { mIntercept = false; } } else { mIntercept = true; } } else if (Math.abs(distanceY) > 50) { mIntercept = false; } } break; case 1: //左滑动的情况下处理事件的拦截 //对左滑动的页面中嵌套scrollView等等控件时的拦截 if (mIsOpenPager) { //要关闭的时候 if (distanceX > 0) { mIntercept = false; } else if (distanceX < 0) { mIntercept = true; } else if (Math.abs(distanceY) > 50) { mIntercept = true; } } else { //要打开的时候 if (distanceX > 0) { if (mCurrentViewPagerPosition == 0) { mIntercept = true; } else { mIntercept = false; } } else if (distanceX < 0) { mIntercept = false; } else if (Math.abs(distanceY) > 50) { mIntercept = false; } } break; case 2: //顶部滑出 if (distanceY < 0) { //从下往上滑 if (mListView != null) { if (mListView.getLastVisiblePosition() == (mListView.getCount() - 1) && mListView.getChildCount() > 0) { //判定滑动到了当前一屏显示的ListView最后个条目 mIntercept = true; } else { mIntercept = false; } } } else { mIntercept = false; } break; case 3: if (distanceY > 0) { //从上往下滑 if (mListView != null) { if (mListView.getFirstVisiblePosition() == 0 && mListView.getChildCount() > 0) { //判定滑动到了当前一屏显示的ListView第一个条目 mIntercept = true; } else { mIntercept = false; } } } else { mIntercept = false; } break; } mInterceptStartX = interceptEndX; mInterceptStartY = interceptEndY; break; case MotionEvent.ACTION_UP: break; } return mIntercept; } /** * 打开侧滑页面 */ public void openSlidePager() { switch (mSlidingModel) { case 0: mScroller.startScroll(getScrollX(), getScrollY(), mSiderViewWidth - getScrollX(), getScrollY() , Math.abs(mSiderViewWidth - getScrollX())); break; case 1: mScroller.startScroll(getScrollX(), getScrollY(), -mSiderViewWidth - getScrollX(), getScrollY(), Math.abs(-mSiderViewWidth - getScrollX())); break; case 2: mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), -mSiderViewHeight - getScrollY(), Math.abs(-mSiderViewHeight - getScrollY())); break; case 3: mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), mSiderViewHeight - getScrollY() , Math.abs(mSiderViewHeight - getScrollY())); break; default: break; } invalidate(); mIsOpenPager = true; } /** * 关闭侧滑页面 */ public void closeSlidePager() { switch (mSlidingModel) { case 0: mScroller.startScroll(getScrollX(), getScrollY(), 0 - getScrollX(), getScrollY(), Math.abs(0 - getScrollX())); invalidate(); break; case 1: mScroller.startScroll(getScrollX(), getScrollY(), 0 - getScrollX(), getScrollY(), Math.abs(0 - getScrollX())); invalidate(); break; case 2: mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), 0 - getScrollY(), Math.abs(0 - getScrollY())); invalidate(); break; case 3: mScroller.startScroll(getScrollX(), getScrollY(), getScrollX(), 0 - getScrollY(), Math.abs(0 - getScrollY())); invalidate(); break; default: break; } mIsOpenPager = false; } /** * 获取滑动方向 * * @return */ public int getSlidingModel() { return mSlidingModel; } /** * 设置滑动方向 * * @param slidingModel */ public void setSlidingModel(int slidingModel) { mSlidingModel = slidingModel; invalidate(); } /** * 获取左右页面滑出留的的距离 * * @return */ public int getSlidingShowLeftOrRightValue() { return mSlidingShowLeftOrRightValue; } /** * 设置左右滑出页面留的的距离 * * @param slidingShowLeftOrRightValue */ public void setSlidingShowLeftOrRightValue(int slidingShowLeftOrRightValue) { mSlidingShowLeftOrRightValue = px2dp(slidingShowLeftOrRightValue); invalidate(); } /** * 当前打开滑动页面的状态 * * @return */ public boolean isOpenPager() { return mIsOpenPager; } /** * 将px转化为dip * * @param pxValue * @return */ private int px2dp(int pxValue) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, pxValue, getResources().getDisplayMetrics()); } }
2)属性
<declare-styleable name="SliderPager"> <attr name="slidingModel" format="enum"> <enum name="sliding_right" value="0"/> <enum name="sliding_left" value="1"/> <enum name="sliding_top" value="2"/> <enum name="sliding_buttom" value="3"/> </attr> <attr name="slidingShowLeftOrRight" format="dimension"/> </declare-styleable>
由于时间问题,只能将就,先......