b站視頻代碼之側滑界面的java文件

說明

  1. b站教學視頻略過了這個部分,考慮到講解難度和大家看b站號也是爲了快速掌握,所以這個部分我直接把代碼貼到這。
  2. 這份代碼我應該是借鑑的某位大佬的寫法,具體來源我不記得了,如果有侵權的,請聯繫我刪除。

代碼

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();
        }
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章