栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android开源AndroidSideMenu实现抽屉和侧滑菜单

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android开源AndroidSideMenu实现抽屉和侧滑菜单

AndroidSideMenu能够让你轻而易举地创建侧滑菜单。需要注意的是,该项目自身并不提供任何创建菜单的工具,因此,开发者可以自由创建内部菜单。

核心类如下:

 
 
package com.agimind.widget; 
 
import java.util.linkedList; 
import java.util.Queue; 
 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.PorterDuff.Mode; 
import android.graphics.Rect; 
import android.graphics.Region.Op; 
import android.os.Build; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.animation.Animation; 
import android.view.animation.DecelerateInterpolator; 
import android.view.animation.Transformation; 
import android.widget.frameLayout; 
 
public class SlideHolder extends frameLayout { 
 
  public final static int DIRECTION_LEFT = 1; 
  public final static int DIRECTION_RIGHT = -1; 
   
  protected final static int MODE_READY = 0; 
  protected final static int MODE_SLIDE = 1; 
  protected final static int MODE_FINISHED = 2; 
   
  private Bitmap mCachedBitmap; 
  private Canvas mCachedCanvas; 
  private Paint mCachedPaint; 
  private View mMenuView; 
   
  private int mMode = MODE_READY; 
  private int mDirection = DIRECTION_LEFT; 
   
  private int mOffset = 0; 
  private int mStartOffset; 
  private int mEndOffset; 
   
  private boolean mEnabled = true; 
  private boolean mInterceptTouch = true; 
  private boolean mAlwaysOpened = false; 
  private boolean mDispatchWhenOpened = false; 
   
  private Queue mWhenReady = new linkedList(); 
   
  private onSlideListener mListener; 
   
  public SlideHolder(Context context) { 
    super(context); 
     
    initView(); 
  } 
   
  public SlideHolder(Context context, AttributeSet attrs) { 
    super(context, attrs); 
     
    initView(); 
  } 
   
  public SlideHolder(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
     
    initView(); 
  } 
   
  private void initView() { 
    mCachedPaint = new Paint( 
   Paint.ANTI_ALIAS_FLAG 
   | Paint.FILTER_BITMAP_FLAG 
   | Paint.DITHER_FLAG 
 ); 
  } 
   
  @Override 
  public void setEnabled(boolean enabled) { 
    mEnabled = enabled; 
  } 
   
  @Override 
  public boolean isEnabled() { 
    return mEnabled; 
  } 
   
   
  public void setDirection(int direction) { 
    closeImmediately(); 
     
    mDirection = direction; 
  } 
   
   
  public void setAllowInterceptTouch(boolean allow) { 
    mInterceptTouch = allow; 
  } 
   
  public boolean isAllowedInterceptTouch() { 
    return mInterceptTouch; 
  } 
   
   
  public void setDispatchTouchWhenOpened(boolean dispatch) { 
    mDispatchWhenOpened = dispatch; 
  } 
   
  public boolean isDispatchTouchWhenOpened() { 
    return mDispatchWhenOpened; 
  } 
   
   
  public void setAlwaysOpened(boolean opened) { 
    mAlwaysOpened = opened; 
     
    requestLayout(); 
  } 
   
  public int getMenuOffset() { 
    return mOffset; 
  } 
   
  public void setonSlideListener(onSlideListener lis) { 
    mListener = lis; 
  } 
   
  public boolean isOpened() { 
    return mAlwaysOpened || mMode == MODE_FINISHED; 
  } 
   
  public void toggle(boolean immediately) { 
    if(immediately) { 
      toggleImmediately(); 
    } else { 
      toggle(); 
    } 
  } 
   
  public void toggle() { 
    if(isOpened()) { 
      close(); 
    } else { 
      open(); 
    } 
  } 
   
  public void toggleImmediately() { 
    if(isOpened()) { 
      closeImmediately(); 
    } else { 
      openImmediately(); 
    } 
  } 
   
  public boolean open() { 
    if(isOpened() || mAlwaysOpened || mMode == MODE_SLIDE) { 
      return false; 
    } 
     
    if(!isReadyForSlide()) { 
      mWhenReady.add(new Runnable() { 
  
 @Override 
 public void run() { 
   open(); 
 } 
      }); 

      return true; 
    } 
     
    initSlideMode(); 
     
    Animation anim = new SlideAnimation(mOffset, mEndOffset); 
    anim.setAnimationListener(mOpenListener); 
    startAnimation(anim); 
     
    invalidate(); 
     
    return true; 
  } 
   
  public boolean openImmediately() { 
    if(isOpened() || mAlwaysOpened || mMode == MODE_SLIDE) { 
      return false; 
    } 
     
    if(!isReadyForSlide()) { 
      mWhenReady.add(new Runnable() { 
  
 @Override 
 public void run() { 
   openImmediately(); 
 } 
      }); 

      return true; 
    } 
     
    mMenuView.setVisibility(View.VISIBLE); 
    mMode = MODE_FINISHED; 
    requestLayout(); 
     
    if(mListener != null) { 
      mListener.onSlideCompleted(true); 
    } 
     
    return true; 
  } 
   
  public boolean close() { 
    if(!isOpened() || mAlwaysOpened || mMode == MODE_SLIDE) { 
      return false; 
    } 
     
    if(!isReadyForSlide()) { 
      mWhenReady.add(new Runnable() { 
  
 @Override 
 public void run() { 
   close(); 
 } 
      }); 

      return true; 
    } 
     
    initSlideMode(); 
     
    Animation anim = new SlideAnimation(mOffset, mEndOffset); 
    anim.setAnimationListener(mCloseListener); 
    startAnimation(anim); 
     
    invalidate(); 
     
    return true; 
  } 
   
  public boolean closeImmediately() { 
    if(!isOpened() || mAlwaysOpened || mMode == MODE_SLIDE) { 
      return false; 
    } 
     
    if(!isReadyForSlide()) { 
      mWhenReady.add(new Runnable() { 
  
 @Override 
 public void run() { 
   closeImmediately(); 
 } 
      }); 

      return true; 
    } 
     
    mMenuView.setVisibility(View.GONE); 
    mMode = MODE_READY; 
    requestLayout(); 
     
    if(mListener != null) { 
      mListener.onSlideCompleted(false); 
    } 
     
    return true; 
  } 
   
  @Override 
  protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    final int parentLeft = 0; 
    final int parentTop = 0; 
    final int parentRight = r - l; 
    final int parentBottom = b - t; 
     
    View menu = getChildAt(0); 
    int menuWidth = menu.getMeasuredWidth(); 
     
    if(mDirection == DIRECTION_LEFT) { 
      menu.layout(parentLeft, parentTop, parentLeft+menuWidth, parentBottom); 
    } else { 
      menu.layout(parentRight-menuWidth, parentTop, parentRight, parentBottom); 
    } 
     
    if(mAlwaysOpened) { 
      if(mDirection == DIRECTION_LEFT) { 
 mOffset = menuWidth; 
      } else { 
 mOffset = 0; 
      } 
    } else if(mMode == MODE_FINISHED) { 
      mOffset = mDirection*menuWidth; 
    } else if(mMode == MODE_READY) { 
      mOffset = 0; 
    } 
     
    View main = getChildAt(1); 
    main.layout( 
   parentLeft + mOffset, 
   parentTop, 
   parentLeft + mOffset + main.getMeasuredWidth(), 
   parentBottom 
 ); 
     
    invalidate(); 
     
    Runnable rn; 
    while((rn = mWhenReady.poll()) != null) { 
      rn.run(); 
    } 
  } 
   
  private boolean isReadyForSlide() { 
    return (getWidth() > 0 && getHeight() > 0); 
  } 
   
  @Override 
  protected void onMeasure(int wSp, int hSp) { 
    mMenuView = getChildAt(0); 
     
    if(mAlwaysOpened) { 
      View main = getChildAt(1); 

      if(mMenuView != null && main != null) { 
 measureChild(mMenuView, wSp, hSp); 
 LayoutParams lp = (LayoutParams) main.getLayoutParams(); 
  
 if(mDirection == DIRECTION_LEFT) { 
   lp.leftMargin = mMenuView.getMeasuredWidth(); 
 } else { 
   lp.rightMargin = mMenuView.getMeasuredWidth(); 
 } 
      } 
    } 
     
    super.onMeasure(wSp, hSp); 
  } 
 
  private byte mframe = 0; 
   
  @Override 
  protected void dispatchDraw(Canvas canvas) { 
    try { 
      if(mMode == MODE_SLIDE) { 
 View main = getChildAt(1); 
 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    
   if(main.isDirty()) { 
     mCachedCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); 
     main.draw(mCachedCanvas); 
 } 
 } else { 
    
   if(++mframe % 5 == 0) { 
     mCachedCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); 
     main.draw(mCachedCanvas); 
   } 
 } 
 
  
  
 View menu = getChildAt(0); 
 final int scrollX = menu.getScrollX(); 
 final int scrollY = menu.getScrollY(); 
  
 canvas.save(); 
  
 if(mDirection == DIRECTION_LEFT) { 
   canvas.clipRect(0, 0, mOffset, menu.getHeight(), Op.REPLACe); 
 } else { 
   int menuWidth = menu.getWidth(); 
   int menuLeft = menu.getLeft(); 
    
   canvas.clipRect(menuLeft+menuWidth+mOffset, 0, menuLeft+menuWidth, menu.getHeight()); 
 } 
  
 canvas.translate(menu.getLeft(), menu.getTop()); 
 canvas.translate(-scrollX, -scrollY); 
  
 menu.draw(canvas); 
  
 canvas.restore(); 
  
 canvas.drawBitmap(mCachedBitmap, mOffset, 0, mCachedPaint); 
      } else { 
 if(!mAlwaysOpened && mMode == MODE_READY) { 
   mMenuView.setVisibility(View.GONE); 
 } 
  
 super.dispatchDraw(canvas); 
      } 
    } catch(IndexOutOfBoundsException e) { 
       
    } 
  } 
   
  private int mHistoricalX = 0; 
  private boolean mCloseonRelease = false; 
   
  @Override 
  public boolean dispatchTouchEvent(MotionEvent ev) { 
    if(((!mEnabled || !mInterceptTouch) && mMode == MODE_READY) || mAlwaysOpened) { 
      return super.dispatchTouchEvent(ev); 
    } 
     
    if(mMode != MODE_FINISHED) { 
      onTouchEvent(ev); 

      if(mMode != MODE_SLIDE) { 
 super.dispatchTouchEvent(ev); 
      } else { 
 MotionEvent cancelEvent = MotionEvent.obtain(ev); 
 cancelEvent.setAction(MotionEvent.ACTION_CANCEL); 
 super.dispatchTouchEvent(cancelEvent); 
 cancelEvent.recycle(); 
      } 

      return true; 
    } else { 
      final int action = ev.getAction(); 

      Rect rect = new Rect(); 
      View menu = getChildAt(0); 
      menu.getHitRect(rect); 

      if(!rect.contains((int) ev.getX(), (int) ev.getY())) { 
 if (action == MotionEvent.ACTION_UP && mCloseonRelease && !mDispatchWhenOpened) { 
   close(); 
   mCloseonRelease = false; 
 } else { 
   if(action == MotionEvent.ACTION_DOWN && !mDispatchWhenOpened) { 
     mCloseonRelease = true; 
   } 
    
   onTouchEvent(ev); 
 } 
  
 if(mDispatchWhenOpened) { 
   super.dispatchTouchEvent(ev); 
 } 
  
 return true; 
      } else { 
 onTouchEvent(ev); 
  
 ev.offsetLocation(-menu.getLeft(), -menu.getTop()); 
 menu.dispatchTouchEvent(ev); 
  
 return true; 
      } 
    } 
  } 
   
  private boolean handleTouchEvent(MotionEvent ev) { 
    if(!mEnabled) { 
      return false; 
    } 
     
    float x = ev.getX(); 
     
    if(ev.getAction() == MotionEvent.ACTION_DOWN) { 
      mHistoricalX = (int) x; 

      return true; 
    } 
     
    if(ev.getAction() == MotionEvent.ACTION_MOVE) { 
 
      float diff = x - mHistoricalX; 
 
      if((mDirection*diff > 50 && mMode == MODE_READY) || (mDirection*diff < -50 && mMode == MODE_FINISHED)) { 
 mHistoricalX = (int) x; 
  
 initSlideMode(); 
      } else if(mMode == MODE_SLIDE) { 
 mOffset += diff; 
  
 mHistoricalX = (int) x; 
  
 if(!isSlideAllowed()) { 
   finishSlide(); 
 } 
      } else { 
 return false; 
      } 
    } 
     
    if(ev.getAction() == MotionEvent.ACTION_UP) { 
      if(mMode == MODE_SLIDE) { 
 finishSlide(); 
      } 

      mCloseonRelease = false; 

      return false; 
    } 
     
    return mMode == MODE_SLIDE; 
  } 
   
  @Override 
  public boolean onTouchEvent(MotionEvent ev) { 
    boolean handled = handleTouchEvent(ev); 
     
    invalidate(); 
     
    return handled; 
  } 
   
  private void initSlideMode() { 
    mCloseonRelease = false; 
     
    View v = getChildAt(1); 
     
    if(mMode == MODE_READY) { 
      mStartOffset = 0; 
      mEndOffset = mDirection*getChildAt(0).getWidth(); 
    } else { 
      mStartOffset = mDirection*getChildAt(0).getWidth(); 
      mEndOffset = 0; 
    } 
     
    mOffset = mStartOffset; 
     
    if(mCachedBitmap == null || mCachedBitmap.isRecycled() || mCachedBitmap.getWidth() != v.getWidth()) { 
      mCachedBitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888); 
      mCachedCanvas = new Canvas(mCachedBitmap); 
    } else { 
      mCachedCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); 
    } 
     
    v.setVisibility(View.VISIBLE); 
     
    mCachedCanvas.translate(-v.getScrollX(), -v.getScrollY()); 
    v.draw(mCachedCanvas); 
     
    mMode = MODE_SLIDE; 
     
    mMenuView.setVisibility(View.VISIBLE); 
  } 
   
  private boolean isSlideAllowed() { 
    return (mDirection*mEndOffset > 0 && mDirection*mOffset < mDirection*mEndOffset && mDirection*mOffset >= mDirection*mStartOffset) 
 || (mEndOffset == 0 && mDirection*mOffset > mDirection*mEndOffset && mDirection*mOffset <= mDirection*mStartOffset); 
  } 
   
  private void completeOpening() { 
    mOffset = mDirection*mMenuView.getWidth(); 
    requestLayout(); 
     
    post(new Runnable() { 

      @Override 
      public void run() { 
 mMode = MODE_FINISHED; 
 mMenuView.setVisibility(View.VISIBLE); 
      } 
    }); 
     
    if(mListener != null) { 
      mListener.onSlideCompleted(true); 
    } 
  } 
   
  private Animation.AnimationListener mOpenListener = new Animation.AnimationListener() { 
     
    @Override 
    public void onAnimationStart(Animation animation) {} 
     
    @Override 
    public void onAnimationRepeat(Animation animation) {} 
     
    @Override 
    public void onAnimationEnd(Animation animation) { 
      completeOpening(); 
    } 
  }; 
   
  private void completeClosing() { 
    mOffset = 0; 
    requestLayout(); 
     
    post(new Runnable() { 

      @Override 
      public void run() { 
 mMode = MODE_READY; 
 mMenuView.setVisibility(View.GONE); 
      } 
    }); 
     
    if(mListener != null) { 
      mListener.onSlideCompleted(false); 
    } 
  } 
   
  private Animation.AnimationListener mCloseListener = new Animation.AnimationListener() { 
     
    @Override 
    public void onAnimationStart(Animation animation) {} 
     
    @Override 
    public void onAnimationRepeat(Animation animation) {} 
     
    @Override 
    public void onAnimationEnd(Animation animation) { 
      completeClosing(); 
    } 
  }; 
   
  private void finishSlide() { 
    if(mDirection*mEndOffset > 0) { 
      if(mDirection*mOffset > mDirection*mEndOffset/2) { 
 if(mDirection*mOffset > mDirection*mEndOffset) mOffset = mEndOffset; 
  
 Animation anim = new SlideAnimation(mOffset, mEndOffset); 
 anim.setAnimationListener(mOpenListener); 
 startAnimation(anim); 
      } else { 
 if(mDirection*mOffset < mDirection*mStartOffset) mOffset = mStartOffset; 
  
 Animation anim = new SlideAnimation(mOffset, mStartOffset); 
 anim.setAnimationListener(mCloseListener); 
 startAnimation(anim); 
      } 
    } else { 
      if(mDirection*mOffset < mDirection*mStartOffset/2) { 
 if(mDirection*mOffset < mDirection*mEndOffset) mOffset = mEndOffset; 
  
 Animation anim = new SlideAnimation(mOffset, mEndOffset); 
 anim.setAnimationListener(mCloseListener); 
 startAnimation(anim); 
      } else { 
 if(mDirection*mOffset > mDirection*mStartOffset) mOffset = mStartOffset; 
  
 Animation anim = new SlideAnimation(mOffset, mStartOffset); 
 anim.setAnimationListener(mOpenListener); 
 startAnimation(anim); 
      } 
    } 
  } 
   
  private class SlideAnimation extends Animation { 
     
    private static final float SPEED = 0.6f; 
     
    private float mStart; 
    private float mEnd; 
     
    public SlideAnimation(float fromX, float toX) { 
      mStart = fromX; 
      mEnd = toX; 

      setInterpolator(new DecelerateInterpolator()); 
 
      float duration = Math.abs(mEnd - mStart) / SPEED; 
      setDuration((long) duration); 
    } 
     
    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
      super.applyTransformation(interpolatedTime, t); 

      float offset = (mEnd - mStart) * interpolatedTime + mStart; 
      mOffset = (int) offset; 

      postInvalidate(); 
    } 
     
  } 
   
  public static interface onSlideListener { 
    public void onSlideCompleted(boolean opened); 
  } 
 
} 

使用:

package com.agimind.sidemenuexample; 
 
import com.agimind.widget.SlideHolder; 
 
import android.os.Bundle; 
import android.view.MenuItem; 
import android.view.View; 
import android.app.ActionBar; 
import android.app.Activity; 
 
public class MainActivity extends Activity { 
 
  private SlideHolder mSlideHolder; 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
 
    mSlideHolder = (SlideHolder) findViewById(R.id.slideHolder); 
    // mSlideHolder.setAllowInterceptTouch(false); 
    // mSlideHolder.setAlwaysOpened(true); 
     
 
    ActionBar actionBar = getActionBar(); 
    actionBar.setDisplayShowHomeEnabled(true); 
    actionBar.setHomeButtonEnabled(true); 
     
    View toggleView = findViewById(R.id.textView); 
    toggleView.setonClickListener(new View.onClickListener() { 
 
      @Override 
      public void onClick(View v) { 
 mSlideHolder.toggle(); 
      } 
    }); 
  } 
 
  @Override 
  public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
    case android.R.id.home: 
      mSlideHolder.toggle(); 
      break; 
 
    default: 
      break; 
    } 
    return super.onOptionsItemSelected(item); 
  } 
} 

布局如下:

 
 
   
 
     
 
      

下载:AndroidSideMenu

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/159685.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号