public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);// 隱藏系統的標題欄
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SlidingMenu slidingMenu = (SlidingMenu) findViewById(R.id.sliding_menu);
findViewById(R.id.btn_show_menu).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
slidingMenu.toggle();
}
});
}
public void onClickMenu(View v) {
TextView menuTextView = (TextView) v;
Toast.makeText(this, menuTextView.getText(), Toast.LENGTH_SHORT).show();
}
}
public class SlidingMenu extends ViewGroup {
private int menuViewWidth;
private View menuView;
private View mainView;
private float downX;
/** 是否有移動操作 */
private boolean hasMove;
private float distanceX;
/** 菜單當前移動到的位置 */
private float currentX;
/** 用於模擬滾動數據的類 */
private Scroller scroller;
private float downY;
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
scroller = new Scroller(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
menuView = getChildAt(0);
mainView = getChildAt(1);
// 測量菜單
menuViewWidth = menuView.getLayoutParams().width;
menuView.measure(menuViewWidth, heightMeasureSpec);
// 測量主界面
mainView.measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 對SlidingMenu裏面的子控件進行排版
menuView.layout(l - 240, t, l, b);
mainView.layout(l, t, r, b);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
hasMove = true;
distanceX = currentX + event.getX() - downX;
// 預防超出範圍
if (distanceX < 0) {
distanceX = 0;
} else if (distanceX > menuViewWidth) {
distanceX = menuViewWidth;
}
scrollTo(distanceX);
break;
case MotionEvent.ACTION_UP:
if (hasMove) {
hasMove = false;
// 如果擡起手的時候,移動的距離小於菜單寬/2,則把菜單完全隱藏
if (distanceX < menuViewWidth / 2) {
scrollTo(0);
currentX = 0;// 要移動到的目標位置
} else {
// 完全顯示
scrollTo(menuViewWidth);
currentX = menuViewWidth;// 要移動到的目標位置
}
startScroll((int) distanceX, (int) currentX);
}
break;
default:
break;
}
return true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = ev.getX();
downY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float distanceX = ev.getX() - downX;
float distanceY = ev.getY() - downY;
if (Math.abs(distanceX) > Math.abs(distanceY)) {
// 如果水平方向移動距離比y方向移動距離大,則認爲是水平移動,把touch攔截
return true;
}
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
/** 打開菜單或者關閉菜單 */
public void toggle() {
int startX;
int destX;
// 如果滑動距離 == 0,說明菜單原來是隱藏的,需要顯示出來
if (getMyScrollX() == 0) {
startX = 0;
destX = menuViewWidth;
} else {
// 隱藏
startX = menuViewWidth;
destX = 0;
}
currentX = destX;
startScroll(startX, destX);
}
/**
*
* @param startX 開始移動的x位置
* @param destX 要移動到的目標位置
*/
private void startScroll(int startX, int destX) {
int dx = destX - startX; // 移動的距離
int startY = 0;
int dy = 0;
int maxDuration = 1000;
float maxMoveDistanceX = menuViewWidth;
float scale = maxDuration / maxMoveDistanceX;// 最後要算什麼類型,則這個類型的數據應該做爲被除數
int duration = (int) (Math.abs(dx) * scale);
scroller.startScroll(startX, startY, dx, dy, duration);
invalidate();// 通知系統去刷新View,內部會調用onDraw
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {// 判斷數據是否模擬結束了,如果沒結束返回true
int currX = scroller.getCurrX();
scrollTo(currX);
invalidate();// 通知系統去刷新View,內部會調用onDraw
}
}
/**
* 封裝系統的方法,是爲了傳正數的時候往右移動,傳負的時候往左移動
* @param x
*/
public void scrollTo(float x) {
super.scrollTo(-(int) x, 0);
}
/**
*
* @return
*/
public int getMyScrollX() {
return -super.getScrollX();
}
}