主页面的布局
左边菜单的布局
右边菜单的布局
自定义控件的代码
package com.example.administrator.slidingmenu;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
/*
* @项目名: SlidingMenu
* @包名: com.example.administrator.slidingmenu
* @文件名: SlidingMenu
* @创建者: Administrator
* @创建时间: 2016/8/16 0016 下午 4:35
* @描述: TODO
*/
public class SlidingMenu extends ViewGroup {
private static final String TAG = "SlidingMenu";
private float mStartX;
private float mStartY;
private View mChildLeft;
private Scroller mScroller;
private boolean flag = false;
public SlidingMenu(Context context) {
this(context, null);
}
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//得到右边菜单的view
View childRight = getChildAt(1);
childRight.layout(0, 0, childRight.getMeasuredWidth(), childRight.getMeasuredHeight());
//得到左边的菜单view,进行布局
mChildLeft = getChildAt(0);
mChildLeft.layout(-mChildLeft.getMeasuredWidth(), 0, 0, mChildLeft.getMeasuredHeight());
}
//对左右滑动的事件进行拦截,父容器自己消费
@Override
public boolean onInterceptHoverEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//得到初始的位置
mStartX = event.getX();
mStartY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
//得到当前的位置
float currentX = event.getX();
float currentY = event.getY();
//取水平和上下移动的距离绝对值
float dx = Math.abs(currentX - mStartX);
float dy = Math.abs(currentY - mStartX);
//如果水平距离大于上下距离,则消费事件
if (dx > dy) {
return true;
}
break;
}
return super.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartX = event.getX();
mStartY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float dx = mStartX - moveX;//得到是一个相对值,这个值可以直接作为偏移量(正负)
//得到绝对距离,
float finalX = getScrollX() + dx;
//确定平移的边界
if (dx > 0) {//偏移量大于0,向左边移动,越界
scrollTo(0, 0);
return true;
}
if (finalX < -mChildLeft.getMeasuredWidth()) {
//坐标为负的,偏移量为正
scrollTo(-mChildLeft.getMeasuredWidth(), 0);
return true;
}
scrollBy((int) dx, 0);
break;
case MotionEvent.ACTION_UP:
//放开的时候,如果左边菜单一半,滑出.否则退回
int the = -mChildLeft.getMeasuredWidth() / 2;
if (getScrollX() > the) {
//没有一半,退回
// scrollTo(0, 0);
close();
return true;
} else if (getScrollX() < the) {
// scrollTo(-mChildLeft.getMeasuredWidth(), 0);
open();
return true;
}
break;
}
return true;
}
//定义一个平滑滑动的方法,可以控制滑动目的的时间和距离
private void smoothScrollTo(int end) {
//相对与起始点已将滑动的距离
int startX = getScrollX();
int dx = end - startX;
//开始滑动
mScroller.startScroll(startX, 0, dx, 0, 500);
//重新绘制
invalidate();
}
//重新computescroller方法,用于得到子容器的布局参数值的变化
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), 0);
invalidate();
}
}
private void open() {
smoothScrollTo(-mChildLeft.getMeasuredWidth());
flag=true;
}
private void close() {
smoothScrollTo(0);
flag=false;
}
public void toggle(){
if (flag){
close();
}else{
open();
}
}
}
acitvity页面的代码
public class MainActivity extends AppCompatActivity {
private SlidingMenu mSlidingMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSlidingMenu = (SlidingMenu) findViewById(R.id.slidingmenu);
}
public void onBack(View view){
mSlidingMenu.toggle();
}
public void OnTabClick(View v) {
//点击菜单选项,关闭侧滑菜单,弹出toast
mSlidingMenu.toggle();
}
}