Android 側滑菜單的實現

來源:互聯網
上載者:User

標籤:path   源碼   menu   

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;/** * 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;//時間間隔2sprivate static final int INTERVAL = 2000;//側滑菜單選中的itemprivate int mViewPosition;//側滑傳遞的標題private String mstrTitle;@Overrideprotected 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{@Overridepublic String getDataTitle() {return mstrTitle;}}@Overridepublic 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;}}

還有部分源碼為貼出,有興趣可以下載。

本文項目源碼:點擊

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Android 側滑菜單的實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.