說明
- b站教學視頻略過了這個部分,考慮到講解難度和大家看b站號也是爲了快速掌握,所以這個部分我直接把代碼貼到這。
- 這份代碼我應該是借鑑的某位大佬的寫法,具體來源我不記得了,如果有侵權的,請聯繫我刪除。
代碼
package com.example.eva;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Scroller;
public class SlideMenu extends FrameLayout {
private View menuView,mainView;
private int menuWidth;
private Scroller scroller;
public SlideMenu(Context context) {
super(context);
init();
}
public SlideMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
scroller = new Scroller(getContext());
}
/**
* 當1級子view全部加載完調用,可以用初始化子view引用
* 注意這裏無法獲取子view的寬高
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
menuView = getChildAt(0);
mainView = getChildAt(1);
menuWidth = menuView.getLayoutParams().width;
}
//使Menu也具有滑動功能
public boolean onInterceptTouchEvent(MotionEvent ev){
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) ev.getX();
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int) (ev.getX() - downX);
if (Math.abs(deltaX) > 8){
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}
/**
* s設置兩個子view在頁面上的佈局
* @param l:當前子view的左邊在父view的座標系的x座標
* @param t:當前子view的頂邊在父view的座標系的y座標
* @param r:當前子view的寬
* @param b:當前子view的高
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
menuView.layout(-menuWidth, 0, 0, b);
mainView.layout(0, 0, r, b);
}
/**
* 處理屏幕滑動事件
*/
private int downX;
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int) event.getX();
int deltaX = moveX - downX;
int newScrollX = getScrollX() - deltaX;
if (newScrollX < -menuWidth) newScrollX = -menuWidth;
if (newScrollX > 0) newScrollX = 0;
scrollTo(newScrollX, 0);
downX = moveX;
break;
case MotionEvent.ACTION_UP:
//當滑動距離小於Menu寬度的一半時,平滑滑動到主頁面
if(getScrollX()>-menuWidth/2){
closeMenu();
}else {
//當滑動距離大於Menu寬度的一半時,平滑滑動到Menu頁面
openMenu();
}
break;
}
return true;
}
//關閉menu
private void closeMenu(){
scroller.startScroll(getScrollX(),0,0-getScrollX(),0,400);
invalidate();
}
//打開menu
private void openMenu(){
scroller.startScroll(getScrollX(),0,-menuWidth-getScrollX(),0,400);
invalidate();
}
/**
* Scroller不主動去調用這個方法
* 而invalidate()可以調用這個方法
* invalidate->draw->computeScroll
*/
public void computeScroll(){
super.computeScroll();
if(scroller.computeScrollOffset()){
//返回true,表示動畫沒結束
scrollTo(scroller.getCurrX(),0);
invalidate();
}
}
/**
* 切換菜單的開和關
*/
public void switchMenu(){
if(getScrollX()==0){
openMenu();
}else {
closeMenu();
}
}
}