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>
由于时间问题,只能将就,先......