欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

代码分析Android实现侧滑菜单

程序员文章站 2023-11-28 21:56:58
android 侧滑菜单的实现,参考网上的代码,实现侧滑菜单。最重要的是这个动画类ugcanimations,如何使用动画类来侧滑的封装flipperlayout。 1、...

android 侧滑菜单的实现,参考网上的代码,实现侧滑菜单。最重要的是这个动画类ugcanimations,如何使用动画类来侧滑的封装flipperlayout。

1、实现效果

代码分析Android实现侧滑菜单

2、动画类ugcanimations

package com.mmsx.base; 
import android.content.context; 
import android.view.view; 
import android.view.viewgroup.marginlayoutparams; 
import android.view.animation.alphaanimation; 
import android.view.animation.animation; 
import android.view.animation.animationset; 
import android.view.animation.anticipateinterpolator; 
import android.view.animation.overshootinterpolator; 
import android.view.animation.rotateanimation; 
import android.view.animation.scaleanimation; 
import android.view.animation.translateanimation; 
import android.widget.imageview; 
import android.widget.relativelayout; 
 
/** 
 * path动画类 
 * 
 */ 
public class ugcanimations { 
  private static int xoffset = 15; 
  private static int yoffset = -13; 
 
  public static void initoffset(context context) { 
    xoffset = (int) (15 * context.getresources().getdisplaymetrics().density); 
    yoffset = -(int) (13 * context.getresources().getdisplaymetrics().density); 
  } 
 
  public static animation getrotateanimation(float fromdegrees, 
      float todegrees, long durationmillis) { 
    rotateanimation rotate = new rotateanimation(fromdegrees, todegrees, 
        animation.relative_to_self, 0.5f, animation.relative_to_self, 
        0.5f); 
    rotate.setduration(durationmillis); 
    rotate.setfillafter(true); 
    return rotate; 
  } 
 
  public static animation getalphaanimation(float fromalpha, float toalpha, 
      long durationmillis) { 
    alphaanimation alpha = new alphaanimation(fromalpha, toalpha); 
    alpha.setduration(durationmillis); 
    alpha.setfillafter(true); 
    return alpha; 
  } 
 
  public static animation getscaleanimation(long durationmillis) { 
    scaleanimation scale = new scaleanimation(1.0f, 1.5f, 1.0f, 1.5f, 
        animation.relative_to_self, 0.5f, animation.relative_to_self, 
        0.5f); 
    scale.setduration(durationmillis); 
    return scale; 
  } 
 
  public static animation gettranslateanimation(float fromxdelta, 
      float toxdelta, float fromydelta, float toydelta, 
      long durationmillis) { 
    translateanimation translate = new translateanimation(fromxdelta, 
        toxdelta, fromydelta, toydelta); 
    translate.setduration(durationmillis); 
    translate.setfillafter(true); 
    return translate; 
  } 
 
  public static void startopenanimation(relativelayout relativelayout, 
      imageview background, imageview menu, long durationmillis) { 
    background.setvisibility(view.visible); 
    relativelayout.setvisibility(view.visible); 
    background.startanimation(getalphaanimation(0f, 1f, durationmillis)); 
    menu.startanimation(getrotateanimation(0, 90, durationmillis)); 
    for (int i = 0; i < relativelayout.getchildcount(); i++) { 
      imageview imageview = (imageview) relativelayout.getchildat(i); 
      imageview.setvisibility(view.visible); 
      marginlayoutparams params = (marginlayoutparams) imageview 
          .getlayoutparams(); 
      animationset set = new animationset(true); 
      set.addanimation(getrotateanimation(-270, 0, durationmillis)); 
      set.addanimation(getalphaanimation(0.5f, 1.0f, durationmillis)); 
      set.addanimation(gettranslateanimation( 
          -params.leftmargin + xoffset, 0f, params.bottommargin 
              + yoffset, 0f, durationmillis)); 
      set.setfillafter(true); 
      set.setduration(durationmillis); 
      set.setstartoffset((i * 100) 
          / (-1 + relativelayout.getchildcount())); 
      set.setinterpolator(new overshootinterpolator(1f)); 
      imageview.startanimation(set); 
    } 
  } 
  public static void startcloseanimation(final relativelayout relativelayout, 
      final imageview background, imageview menu, long durationmillis) { 
    background.startanimation(getalphaanimation(1f, 0f, durationmillis)); 
    menu.startanimation(getrotateanimation(90, 0, durationmillis)); 
    for (int i = 0; i < relativelayout.getchildcount(); i++) { 
      final imageview imageview = (imageview) relativelayout 
          .getchildat(i); 
      marginlayoutparams params = (marginlayoutparams) imageview 
          .getlayoutparams(); 
      animationset set = new animationset(true); 
      set.addanimation(getrotateanimation(0, -270, durationmillis)); 
      set.addanimation(getalphaanimation(1.0f, 0.5f, durationmillis)); 
      set.addanimation(gettranslateanimation(0f, -params.leftmargin 
          + xoffset, 0f, params.bottommargin + yoffset, 
          durationmillis)); 
      set.setfillafter(true); 
      set.setduration(durationmillis); 
      set.setstartoffset(((relativelayout.getchildcount() - i) * 100) 
          / (-1 + relativelayout.getchildcount())); 
      set.setinterpolator(new anticipateinterpolator(1f)); 
      set.setanimationlistener(new animation.animationlistener() { 
        public void onanimationstart(animation arg0) { 
        } 
        public void onanimationrepeat(animation arg0) { 
        } 
        public void onanimationend(animation arg0) { 
          relativelayout.setvisibility(view.gone); 
          background.setvisibility(view.gone); 
        } 
      }); 
      imageview.startanimation(set); 
    } 
  } 
  public static animation clickanimation(long durationmillis) { 
    animationset set = new animationset(true); 
    set.addanimation(getalphaanimation(1.0f, 0.3f, durationmillis)); 
    set.addanimation(getscaleanimation(durationmillis)); 
    set.setduration(durationmillis); 
    return set; 
  } 
} 

3、封装使用动画类flipperlayout

package com.mmsx.base; 
import android.content.context; 
import android.util.attributeset; 
import android.util.typedvalue; 
import android.view.motionevent; 
import android.view.velocitytracker; 
import android.view.view; 
import android.view.viewconfiguration; 
import android.view.viewgroup; 
import android.widget.scroller; 
 
/** 
 * 自己重写的viewgroup,用与滑动切换界面使用,代码不详解,慢点看的话应该能看懂的... 
 */ 
public class flipperlayout extends viewgroup { 
 
  private scroller mscroller; 
  private velocitytracker mvelocitytracker; 
  private int mwidth; 
 
  public static final int screen_state_close = 0; 
  public static final int screen_state_open = 1; 
  public static final int touch_state_restart = 0; 
  public static final int touch_state_scrolling = 1; 
  public static final int scroll_state_no_allow = 0; 
  public static final int scroll_state_allow = 1; 
  private int mscreenstate = 0; 
  private int mtouchstate = 0; 
  private int mscrollstate = 0; 
  private int mvelocityvalue = 0; 
  private boolean monclick = false; 
  private onugcdismisslistener monugcdismisslistener; 
  private onugcshowlistener monugcshowlistener; 
 
  public flipperlayout(context context) { 
    super(context); 
    mscroller = new scroller(context); 
    mwidth = (int) typedvalue.applydimension(typedvalue.complex_unit_dip, 
        54, getresources().getdisplaymetrics()); 
 
  } 
 
  public flipperlayout(context context, attributeset attrs, int defstyle) { 
    super(context, attrs, defstyle); 
  } 
 
  public flipperlayout(context context, attributeset attrs) { 
    super(context, attrs); 
  } 
 
  protected void onlayout(boolean changed, int l, int t, int r, int b) { 
    for (int i = 0; i < getchildcount(); i++) { 
      view child = getchildat(i); 
      int height = child.getmeasuredheight(); 
      int width = child.getmeasuredwidth(); 
      child.layout(0, 0, width, height); 
    } 
  } 
 
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { 
    super.onmeasure(widthmeasurespec, heightmeasurespec); 
    int width = measurespec.getsize(widthmeasurespec); 
    int height = measurespec.getsize(heightmeasurespec); 
    setmeasureddimension(width, height); 
    for (int i = 0; i < getchildcount(); i++) { 
      getchildat(i).measure(widthmeasurespec, heightmeasurespec); 
    } 
  } 
 
  public boolean dispatchtouchevent(motionevent ev) { 
    obtainvelocitytracker(ev); 
    switch (ev.getaction()) { 
    case motionevent.action_down: 
      mtouchstate = mscroller.isfinished() ? touch_state_restart 
          : touch_state_scrolling; 
      if (mtouchstate == touch_state_restart) { 
        int x = (int) ev.getx(); 
        int screenwidth = getwidth(); 
        if (x <= mwidth && mscreenstate == screen_state_close 
            && mtouchstate == touch_state_restart 
            || x >= screenwidth - mwidth 
            && mscreenstate == screen_state_open 
            && mtouchstate == touch_state_restart) { 
          if (mscreenstate == screen_state_open) { 
            monclick = true; 
          } 
          mscrollstate = scroll_state_allow; 
        } else { 
          monclick = false; 
          mscrollstate = scroll_state_no_allow; 
        } 
      } else { 
        return false; 
      } 
      break; 
    case motionevent.action_move: 
      mvelocitytracker.computecurrentvelocity(1000, 
          viewconfiguration.getmaximumflingvelocity()); 
      if (mscrollstate == scroll_state_allow 
          && getwidth() - (int) ev.getx() < mwidth) { 
        return true; 
      } 
      break; 
    case motionevent.action_up: 
      releasevelocitytracker(); 
      if (monclick) { 
        monclick = false; 
        mscreenstate = screen_state_close; 
        mscroller.startscroll(getchildat(1).getscrollx(), 0, 
            -getchildat(1).getscrollx(), 0, 800); 
        invalidate(); 
      } 
      break; 
    } 
    return super.dispatchtouchevent(ev); 
  } 
 
  public boolean onintercepttouchevent(motionevent ev) { 
    obtainvelocitytracker(ev); 
    switch (ev.getaction()) { 
    case motionevent.action_down: 
      mtouchstate = mscroller.isfinished() ? touch_state_restart 
          : touch_state_scrolling; 
      if (mtouchstate == touch_state_scrolling) { 
        return false; 
      } 
      break; 
 
    case motionevent.action_move: 
      monclick = false; 
      mvelocitytracker.computecurrentvelocity(1000, 
          viewconfiguration.getmaximumflingvelocity()); 
      if (mscrollstate == scroll_state_allow 
          && math.abs(mvelocitytracker.getxvelocity()) > 200) { 
        return true; 
      } 
      break; 
 
    case motionevent.action_up: 
      releasevelocitytracker(); 
      if (mscrollstate == scroll_state_allow 
          && mscreenstate == screen_state_open) { 
        return true; 
      } 
      break; 
    } 
    return super.onintercepttouchevent(ev); 
  } 
 
  public boolean ontouchevent(motionevent event) { 
    obtainvelocitytracker(event); 
    switch (event.getaction()) { 
    case motionevent.action_down: 
      mtouchstate = mscroller.isfinished() ? touch_state_restart 
          : touch_state_scrolling; 
      if (mtouchstate == touch_state_scrolling) { 
        return false; 
      } 
      break; 
 
    case motionevent.action_move: 
      mvelocitytracker.computecurrentvelocity(1000, 
          viewconfiguration.getmaximumflingvelocity()); 
      mvelocityvalue = (int) mvelocitytracker.getxvelocity(); 
      getchildat(1).scrollto(-(int) event.getx(), 0); 
      break; 
 
    case motionevent.action_up: 
      if (mscrollstate == scroll_state_allow) { 
        if (mvelocityvalue > 2000) { 
          mscreenstate = screen_state_open; 
          mscroller 
              .startscroll( 
                  getchildat(1).getscrollx(), 
                  0, 
                  -(getwidth() 
                      - math.abs(getchildat(1) 
                          .getscrollx()) - 
 
                  mwidth), 0, 250); 
          invalidate(); 
 
        } else if (mvelocityvalue < -2000) { 
          mscreenstate = screen_state_close; 
          mscroller.startscroll(getchildat(1).getscrollx(), 0, 
              -getchildat(1).getscrollx(), 0, 250); 
          invalidate(); 
        } else if (event.getx() < getwidth() / 2) { 
          mscreenstate = screen_state_close; 
          mscroller.startscroll(getchildat(1).getscrollx(), 0, 
              -getchildat(1).getscrollx(), 0, 800); 
          invalidate(); 
        } else { 
          mscreenstate = screen_state_open; 
          mscroller 
              .startscroll( 
                  getchildat(1).getscrollx(), 
                  0, 
                  -(getwidth() 
                      - math.abs(getchildat(1) 
                          .getscrollx()) - 
 
                  mwidth), 0, 800); 
          invalidate(); 
        } 
      } 
      break; 
    } 
    return super.ontouchevent(event); 
  } 
 
  public void open() { 
    mtouchstate = mscroller.isfinished() ? touch_state_restart 
        : touch_state_scrolling; 
    if (mtouchstate == touch_state_restart) { 
      mscreenstate = screen_state_open; 
      mscroller.startscroll(getchildat(1).getscrollx(), 0, -(getwidth() 
          - math.abs(getchildat(1).getscrollx()) - 
 
      mwidth), 0, 800); 
      invalidate(); 
    } 
  } 
 
  //关闭当前的侧滑菜单,用view打开点击事件的页面 
  public void close(view view) { 
    mscreenstate = screen_state_close; 
    mscroller.startscroll(getchildat(1).getscrollx(), 0, -getchildat(1) 
        .getscrollx(), 0, 800); 
    invalidate(); 
    setcontentview(view); 
  } 
 
  public void computescroll() { 
    super.computescroll(); 
    if (mscroller.computescrolloffset()) { 
      getchildat(1).scrollto(mscroller.getcurrx(), mscroller.getcurry()); 
      postinvalidate(); 
    } else { 
      if (mscreenstate == screen_state_open) { 
        if (monugcdismisslistener != null) { 
          monugcdismisslistener.dismiss(); 
        } 
      } else if (mscreenstate == screen_state_close) { 
        if (monugcshowlistener != null) { 
          monugcshowlistener.show(); 
        } 
      } 
    } 
  } 
  private void obtainvelocitytracker(motionevent event) { 
    if (mvelocitytracker == null) { 
      mvelocitytracker = velocitytracker.obtain(); 
    } 
    mvelocitytracker.addmovement(event); 
  } 
  private void releasevelocitytracker() { 
    if (mvelocitytracker != null) { 
      mvelocitytracker.recycle(); 
      mvelocitytracker = null; 
    } 
  } 
  public int getscreenstate() { 
    return mscreenstate; 
  } 
  public void setcontentview(view view) { 
    removeviewat(1); 
    addview(view, 1, getlayoutparams()); 
  } 
  public interface onopenlistener { 
    public abstract void open(); 
  } 
  public interface oncloselistener { 
    public abstract void close(); 
  } 
  public interface onugcdismisslistener { 
    public abstract void dismiss(); 
  } 
  public interface onugcshowlistener { 
    public abstract void show(); 
  } 
  public void setonugcdismisslistener( 
      onugcdismisslistener onugcdismisslistener) { 
    monugcdismisslistener = onugcdismisslistener; 
  } 
  public void setonugcshowlistener(onugcshowlistener onugcshowlistener) { 
    monugcshowlistener = onugcshowlistener; 
  } 
} 

4、主界面mainactivity

package com.mmsx.activity;  
import com.mmsx.activity.sideslipmenu.onchangeviewlistener; 
import com.mmsx.activity.sideslipother.ondatalistener; 
import com.mmsx.base.flipperlayout; 
import com.mmsx.base.flipperlayout.onopenlistener; 
import com.mmsx.base.viewutil; 
import android.os.bundle; 
import android.app.activity; 
import android.view.viewgroup.layoutparams; 
import android.widget.toast; 
 
public class mainactivity extends activity implements onopenlistener{ 
 
  //侧滑主要控制类,设置跟布局 
  private flipperlayout mroot; 
  //侧滑的默认界面,主界面 
  private sidesliphome mhome; 
  //侧滑的菜单,进行选择的 
  private sideslipmenu msideslipmenu; 
  //其他菜单列表选择的效果 
  private sideslipother mother; 
  //退出时间间隔变量 
  private long mexittime; 
  //时间间隔2s 
  private static final int interval = 2000; 
  //侧滑菜单选中的item 
  private int mviewposition; 
  //侧滑传递的标题 
  private string mstrtitle; 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
     //创建容器,并设置全屏大小 
    mroot = new flipperlayout(this); 
    //布局的参数 
    layoutparams params = new layoutparams(layoutparams.fill_parent, 
        layoutparams.fill_parent); 
    mroot.setlayoutparams(params); 
    //创建菜单界面和内容首页界面,并添加到容器中,用于初始显示 
    mhome = new sidesliphome(this, this); 
    msideslipmenu = new sideslipmenu(this); 
    mroot.addview(msideslipmenu.getview(), params); 
    mroot.addview(mhome.getview(), params); 
    //设置跟布局 
    setcontentview(mroot); 
    //设置监听 
    setlistener(); 
  } 
 
  //设置监听 
  private void setlistener() { 
    mhome.setonopenlistener(this); 
     //监听菜单界面切换显示内容(onchangeviewlistener接口在sideslipmenu中定义) 
    msideslipmenu.setonchangeviewlistener(new onchangeviewlistener() { 
       
      public void onchangeview(int arg0) { 
        mviewposition = arg0; 
        mother = new sideslipother(mainactivity.this); 
        switch (arg0) { 
        case viewutil.home: 
          mroot.close(mhome.getview()); 
          break; 
        case viewutil.message: 
          mstrtitle = "消息"; 
          //设置数据接口监听 
          mother.setdatatitle(new datatitle()); 
          mroot.close(mother.getview()); 
          break; 
        case viewutil.friends: 
          mstrtitle = "好友"; 
          mother.setdatatitle(new datatitle()); 
          mroot.close(mother.getview()); 
          break; 
        case viewutil.photo: 
          mstrtitle = "照片"; 
          mother.setdatatitle(new datatitle()); 
          mroot.close(mother.getview()); 
          break; 
        case viewutil.viewed: 
          mstrtitle = "转帖"; 
          mother.setdatatitle(new datatitle()); 
          mroot.close(mother.getview()); 
          break; 
        case viewutil.gifts: 
          mstrtitle = "礼物"; 
          mother.setdatatitle(new datatitle()); 
          mroot.close(mother.getview()); 
          break; 
        case viewutil.recommend: 
          mstrtitle = "游戏"; 
          mother.setdatatitle(new datatitle()); 
          mroot.close(mother.getview()); 
          break; 
        case viewutil.lbs: 
          mstrtitle = "附近 "; 
          mother.setdatatitle(new datatitle()); 
          mroot.close(mother.getview()); 
          break; 
        default: 
          break; 
        } 
      } 
    }); 
  } 
   
  //传递数据到侧滑选中的页面 
  private class datatitle implements ondatalistener{ 
    @override 
    public string getdatatitle() { 
      return mstrtitle; 
    } 
     
  } 
 
  @override 
  public void open() { 
    if (mroot.getscreenstate() == flipperlayout.screen_state_close) { 
      mroot.open(); 
    } 
  } 
   
  /** 
   * 返回键监听 
   */ 
  public void onbackpressed() { 
    /** 
     * 如果界面的path菜单没有关闭时,先将path菜单关闭,否则则判断两次返回时间间隔,小于两秒则退出程序 
     */ 
    if (mroot.getscreenstate() == flipperlayout.screen_state_open) { 
      if (msideslipmenu.getugcisshowing()) { 
        msideslipmenu.closeugc(); 
      } else { 
        exit(); 
      } 
    } else { 
      switch (mviewposition) { 
      case viewutil.home: 
        if (mhome.getugcisshowing()) { 
          mhome.closeugc(); 
        } else { 
          exit(); 
        } 
        break; 
      default: 
        exit(); 
        break; 
      } 
 
    } 
 
  }   
  /** 
   * 判断两次返回时间间隔,小于两秒则退出程序 
   */ 
  private void exit() { 
    if (system.currenttimemillis() - mexittime > interval) { 
      toast.maketext(this, "再按一次返回键,可直接退出程序", toast.length_short).show(); 
      mexittime = system.currenttimemillis(); 
    } else { 
      finish(); 
      android.os.process.killprocess(android.os.process.mypid()); 
      system.exit(0); 
    } 
  } 
}

5、sidesliphome

package com.mmsx.activity; 
import com.mmsx.base.flipperlayout.onopenlistener; 
 
import android.app.activity; 
import android.content.context; 
import android.view.layoutinflater; 
import android.view.view; 
import android.widget.textview; 
 
public class sidesliphome { 
  private context mcontext; 
  private activity mactivity; 
  private view mhomeview; 
  private boolean mugcisshowing = false;  
  private onopenlistener monopenlistener; 
  public sidesliphome(context context, activity activity) { 
    mcontext = context; 
    mactivity = activity; 
    mhomeview = layoutinflater.from(context).inflate(r.layout.sideslip_home, null); 
     
    initui(); 
  } 
 
  private void initui() { 
    textview ivtitlename = (textview)mhomeview.findviewbyid(r.id.ivtitlename);  
    ivtitlename.settext("主页动态"); 
     
  } 
   
  public void setonopenlistener(onopenlistener onopenlistener) { 
    monopenlistener = onopenlistener; 
  } 
 
  public view getview() { 
    return mhomeview; 
  } 
   
  /** 
   * 获取path菜单显示状态 
   */ 
  public boolean getugcisshowing() { 
    return mugcisshowing; 
  } 
 
  /** 
   * 关闭path菜单 
   */ 
  public void closeugc() { 
    mugcisshowing = false; 
  } 
 
} 

好了,以上就是本文的全部叙述,希望大家喜欢。