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

代码分析Android实现侧滑菜单

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

代码分析Android实现侧滑菜单

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

1、实现效果

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; 
 
 
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; 
 
 
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() { 
     
    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; 
  } 
   
   
  public boolean getUgcIsShowing() { 
    return mUgcIsShowing; 
  } 
 
   
  public void closeUgc() { 
    mUgcIsShowing = false; 
  } 
 
} 

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

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

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

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