The idea of ResideMenu is from Dribbble 1 and 2. It has come true and run in iOS devices. iOS ResideMenu This project is the RefsideMenu Android version. The visual effect is partly referred to iOS version of ResideMenu. And thanks to the authors for the above idea and contribution.

Overview

#AndroidResideMenu

中文说明请点击 这里

The idea of ResideMenu is from Dribble 1 and 2. It has come true and run in iOS devices. iOS ResideMenu This project is the RefsideMenu Android version. The visual effect is partly referred to iOS version of ResideMenu. And thanks to the authors for the above idea and contribution.

Now with 3D support !

DEMO

This copy is the demo.

Version Migration

Upgrading to v1.4 from v1.3, v1.2, v1.1, v1.0

Duplicate the followed code in dispatchTouchEvent() of Activity, replace the old dispatchTouchEvent() code.

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return resideMenu.dispatchTouchEvent(ev);
    }

Requirements

Run in Android 2.3 +

Installation

Gradle

repositories {
    mavenCentral()
}
dependencies {
    compile 'com.specyci:residemenu:1.6+'
}

Other

  1. import ResideMenu project to your workspace.
  2. make it as a dependency library project to your main project.
    ( see example )

or

If you want to merge ResideMenu with your project, you should follow these steps.

  1. Copy all files from src/com/special/ResideMenu to your project.
  2. Copy libs/nineoldandroids-library-2.4.0.jar to your project’s corresponding path: libs/
  3. Copy res/drawable-hdpi/shadow.9.png to your project’s corresponding path: res/drawable-hdpi/
  4. Copy res/layout/residemenu.xml and residemenu_item.xml to your project’s corresponding path: res/layout

Usage

init ResideMenu: write these code in Activity onCreate()

        // attach to current activity;
        resideMenu = new ResideMenu(this);
        resideMenu.setBackground(R.drawable.menu_background);
        resideMenu.attachToActivity(this);

        // create menu items;
        String titles[] = { "Home", "Profile", "Calendar", "Settings" };
        int icon[] = { R.drawable.icon_home, R.drawable.icon_profile, R.drawable.icon_calendar, R.drawable.icon_settings };

        for (int i = 0; i < titles.length; i++){
            ResideMenuItem item = new ResideMenuItem(this, icon[i], titles[i]);
            item.setOnClickListener(this);
            resideMenu.addMenuItem(item,  ResideMenu.DIRECTION_LEFT); // or  ResideMenu.DIRECTION_RIGHT
        }

If you want to use slipping gesture to operate(lock/unlock) the menu, override this code in Acitivity dispatchTouchEvent() (please duplicate the followed code in dispatchTouchEvent() of Activity.

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return resideMenu.dispatchTouchEvent(ev);
    }

On some occasions, the slipping gesture function for locking/unlocking menu, may have conflicts with your widgets, such as viewpager. By then you can add the viewpager to ignored view, please refer to next chapter – Ignored Views.

open/close menu

resideMenu.openMenu(ResideMenu.DIRECTION_LEFT); // or ResideMenu.DIRECTION_RIGHT
resideMenu.closeMenu();

listen in the menu state

    resideMenu.setMenuListener(menuListener);
    private ResideMenu.OnMenuListener menuListener = new ResideMenu.OnMenuListener() {
        @Override
        public void openMenu() {
            Toast.makeText(mContext, "Menu is opened!", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void closeMenu() {
            Toast.makeText(mContext, "Menu is closed!", Toast.LENGTH_SHORT).show();
        }
    };

disable a swipe direction

  resideMenu.setSwipeDirectionDisable(ResideMenu.DIRECTION_RIGHT);

Custom Usage

Do your reside menu configurations, by creating an instance of ResideMenu with your custom layout's resource Ids. If you want to use default layout, just pass that variable as -1.

        resideMenu = new ResideMenu(activity, R.layout.menu_left, R.layout.menu_right);
        resideMenu.setBackground(R.drawable.menu_background);
        resideMenu.attachToActivity(activity);
        resideMenu.setScaleValue(0.5f);

        resideMenu.setSwipeDirectionDisable(ResideMenu.DIRECTION_RIGHT);
        resideMenu.setSwipeDirectionDisable(ResideMenu.DIRECTION_LEFT);

As your configuration's completed, now you can customize side menus by getting instances of them as following:

        View leftMenu = resideMenu.getLeftMenuView();
        // TODO: Do whatever you need to with leftMenu
        View rightMenu = resideMenu.getRightMenuView();
        // TODO: Do whatever you need to with rightMenu

##Ignored Views On some occasions, the slipping gesture function for locking/unlocking menu, may have conflicts with your widgets such as viewpager.By then you can add the viewpager to ignored view.

        // add gesture operation's ignored views
        FrameLayout ignored_view = (FrameLayout) findViewById(R.id.ignored_view);
        resideMenu.addIgnoredView(ignored_view);

So that in ignored view’s workplace, the slipping gesture will not be allowed to operate menu.

##About me A student from SCAU China.
Email: specialcyci#gmail.com

Comments
  • 发现一个问题

    发现一个问题

    假设:从主页手势滑动到右边,再手势滑动回到主页,这时屏幕右半边无法点击,还会点到右边侧滑菜单的item;我猜测是滑动回主页时右边的菜单变透明,实际上还存在在主页上放,导致主页右半部分无法点击,我用一个方法回避这个问题就是在ResideMenu.java里的public boolean dispatchTouchEvent(MotionEvent ev)方法里把if (xOffset < -200 || xOffset > 200) { pressedState = PRESSED_MOVE_HORIZANTAL; ev.setAction(MotionEvent.ACTION_CANCEL); } 判断语句数值调大,从原来的50调到200,但这样用户体验会差一些。 我是菜鸟,希望能和其他人交流一下这个问题,找到更好的解决办法。

    opened by CatsPills 8
  • Change LeftMenu Width in Android Marshmallow

    Change LeftMenu Width in Android Marshmallow

    Is there a way to change the leftmenu width in android Marshmallow. I used this code and it working in Lollipop and under, but it seems that it's ignored in android M

        public void setWidth() {
            try {
                // getting type of the field from superClass
                Field privateLeftScrollMenu = ResideMenu.class.getDeclaredField("scrollViewLeftMenu");
                // transform this field to public
                privateLeftScrollMenu.setAccessible(true);
                // getting value from this field which is reference to a TextView
                ScrollView sv = (ScrollView) privateLeftScrollMenu.get(this);
                //finaly setting the Typface
                sv.setLayoutParams(new ViewGroup.LayoutParams(350, ViewGroup.LayoutParams.MATCH_PARENT));
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    
        }
    

    This how is looking in android M screenshot_20160715-134410

    opened by smidaharoun 5
  • Root FrameLayout showing fullscreen

    Root FrameLayout showing fullscreen

    Hello, I'm testing your library and found it very useful, awesome! I'm having a problem with the size of the root layout. I want display the app icon and name in the top|left of the screen when the menu is open, but I have found that the height of the layout is the height of the entire screen (including the statusbar). Every view placed at the top of the layout is hidden under the statusbar and this also happens with the left and right menu scrolls when there are several items. This is a screen capture that shows the problem: err First I thought it was due to the size of the background image, so I tried to remove it. This doesn't solve the problem. I have tried modifying the method setViewPadding(), but this moves all the views, including the content of the application itself. Hope someone can tell me how ti fix this. Thanks!

    bug 
    opened by RlagoMan 5
  • excellent work!I dump the view tree,found some layouts between decorView and contentView  which are redundant.

    excellent work!I dump the view tree,found some layouts between decorView and contentView which are redundant.

    private void initValue(Activity activity) { this.activity = activity; leftMenuItems = new ArrayList(); rightMenuItems = new ArrayList(); ignoredViews = new ArrayList();

        viewDecor = (ViewGroup) activity.getWindow().getDecorView();
        viewActivity = new TouchDisableView(this.activity);
        // View mContent = viewDecor.getChildAt(0);
        // viewDecor.removeViewAt(0);
        ViewGroup contentView = (ViewGroup) (viewDecor.findViewById(android.R.id.content));
        View mContent = contentView.getChildAt(0);
        contentView.removeAllViews();
        viewDecor.removeAllViews();
    
        viewActivity.setContent(mContent);
        addView(viewActivity);
    
        ViewGroup parent = (ViewGroup) scrollViewLeftMenu.getParent();
        parent.removeView(scrollViewLeftMenu);
        parent.removeView(scrollViewRightMenu);
    }
    
    opened by whysqwhw 4
  • Problem with map

    Problem with map

    Hi, thanks for your library. I have a problem with your library and map. I've put a map in a fragment, but when I open the menu, the map doesn't move and stay at his position. All the others views move with the main view. Can you help me ? Thanks

    opened by rombra169 4
  • 关于MenuItems的点击监听问题

    关于MenuItems的点击监听问题

    楼主你好,最近尝试着用你的这个Demo开发应用,发现在,menu打开之后,不做任何操作,关闭menu,再打开menu点击menu中的任意一个item,这个item的onclicklistener会失效,只有在执行了关闭menu的动作之后,这个item的onclicklistener才会执行。同样在切换了新的Activity之后也会发生同样的问题,所以想请教下楼主,应该在哪里加以修改?或者应该在哪里注意item的点击响应来避免这种情况?(我试过在点击响应中加上 menu.close(),并不起效)。还请楼主赐教。

    bug 
    opened by yehongliang 4
  • How set onclick listener

    How set onclick listener

    i used this ResideMenuItem rightItems = new ResideMenuItem(this, icon[i], options[i]); rightItems.setOnClickListener(this);

    but how i can listen to the specific item on the onClick method?

    opened by Ofiro 3
  • How to open left drawer from extreme left only?

    How to open left drawer from extreme left only?

    Hi I am new to this high level of coding. Please could you help me by telling how can we open left drawer from extreme left as we do in inbuilt navigation drawer by android. Currently what is with your code is that if I swipe a little even from right, it just openmenu. Problem is that I have horizontalscrollview on my fragment and if I want to scroll in it, it opens left menu. Please help me out.

    opened by 19rs39 3
  • How to change text on changing frame?

    How to change text on changing frame?

    Hi Could you please tell me how to write name of Fragment in place of Reside Menu Demo? On clicking home it should be home, if on calendar it should be calendar.

    Please help. Thanks

    opened by 19rs39 3
  • Activity not fitted into the dark placeholder

    Activity not fitted into the dark placeholder

    In my flo (Nexus 7 2013) the view of activity is not fitted into the black place holder of it. Is seems that they don't scale the same amount. I attached a screenshot of the view hierarchy dump to clarify the issue.

    screenshot from 2014-08-16 01 32 07

    opened by avsector 3
  • conflict with layout of fragment in 2.3v

    conflict with layout of fragment in 2.3v

    hi and thank you for your amazing menu. but i hava a problem when i slide and see the menu and then click on an item, functionality of my fragment is invoked! instead of switch the fragment. changes are applide on the current fragment on minisize of my fragment and swithching fragment and closing reside menu is not working. when my current fragment is empty(just a relativelayout/linearlayout) switching between menu and fragment is perfectly work.

    bug 
    opened by ahosseinich 3
  • Download the library and replace ResideMenu class with given below code.

    Download the library and replace ResideMenu class with given below code.

    Download the library and replace ResideMenu class with given below code.

    package com.special.ResideMenu;

    import android.app.Activity; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.os.Build; import android.util.DisplayMetrics; import android.view.; import android.view.animation.AnimationUtils; import android.widget.;

    import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.AnimatorSet; import com.nineoldandroids.animation.ObjectAnimator; import com.nineoldandroids.view.ViewHelper;

    import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List;

    /**

    • User: special

    • Date: 13-12-10

    • Time: 下午10:44

    • Mail: [email protected] */ public class ResideMenu extends FrameLayout {

      public static final int DIRECTION_LEFT = 0; public static final int DIRECTION_RIGHT = 1; private static final int PRESSED_MOVE_HORIZONTAL = 2; private static final int PRESSED_DOWN = 3; private static final int PRESSED_DONE = 4; private static final int PRESSED_MOVE_VERTICAL = 5;

      private ImageView imageViewShadow; private ImageView imageViewBackground; private LinearLayout layoutLeftMenu; private LinearLayout layoutRightMenu; private View scrollViewLeftMenu; private View scrollViewRightMenu; private View scrollViewMenu; private Context mContext; /**

      • Current attaching activity. / private Activity activity; /*
      • The DecorView of current activity. / private ViewGroup viewDecor; private TouchDisableView viewActivity; /*
      • The flag of menu opening status. / private boolean isOpened; private float shadowAdjustScaleX; private float shadowAdjustScaleY; /*
      • Views which need stop to intercept touch events. */ private List ignoredViews; private List leftMenuItems; private List rightMenuItems; private DisplayMetrics displayMetrics = new DisplayMetrics(); private OnMenuListener menuListener; private float lastRawX; private boolean isInIgnoredView = false; private int scaleDirection = DIRECTION_LEFT; private int pressedState = PRESSED_DOWN; private List disabledSwipeDirection = new ArrayList(); // Valid scale factor is between 0.0f and 1.0f. private float mScaleValue = 0.5f;

      private boolean mUse3D; private static final int ROTATE_Y_ANGLE = 10;

      public ResideMenu(Context context) { super(context); mContext=context; initViews(context, -1, -1);

      }

      /**

      • This constructor provides you to create menus with your own custom
      • layouts, but if you use custom menu then do not call addMenuItem because
      • it will not be able to find default views */ public ResideMenu(Context context, int customLeftMenuId, int customRightMenuId) { super(context); mContext=context; initViews(context, customLeftMenuId, customRightMenuId); }

      private void initViews(Context context, int customLeftMenuId, int customRightMenuId) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.residemenu_custom, this);

       if (customLeftMenuId >= 0) {
           scrollViewLeftMenu = inflater.inflate(customLeftMenuId, this, false);
       } else {
           scrollViewLeftMenu = inflater.inflate(
                   R.layout.residemenu_custom_left_scrollview, this, false);
           layoutLeftMenu = (LinearLayout) scrollViewLeftMenu.findViewById(R.id.layout_left_menu);
       }
      
       if (customRightMenuId >= 0) {
           scrollViewRightMenu = inflater.inflate(customRightMenuId, this, false);
       } else {
           scrollViewRightMenu = inflater.inflate(
                   R.layout.residemenu_custom_right_scrollview, this, false);
           layoutRightMenu = (LinearLayout) scrollViewRightMenu.findViewById(R.id.layout_right_menu);
       }
      
       imageViewShadow = (ImageView) findViewById(R.id.iv_shadow);
       imageViewBackground = (ImageView) findViewById(R.id.iv_background);
      
       RelativeLayout menuHolder = (RelativeLayout) findViewById(R.id.sv_menu_holder);
       menuHolder.addView(scrollViewLeftMenu);
       menuHolder.addView(scrollViewRightMenu);
      

      }

      /**

      • Returns left menu view so you can findViews and do whatever you want with */ public View getLeftMenuView() { return scrollViewLeftMenu; }

      /**

      • Returns right menu view so you can findViews and do whatever you want with */ public View getRightMenuView() { return scrollViewRightMenu; }

      @Override protected boolean fitSystemWindows(Rect insets) { // Applies the content insets to the view's padding, consuming that // content (modifying the insets to be 0), // and returning true. This behavior is off by default and can be // enabled through setFitsSystemWindows(boolean) // in api14+ devices.

       Point appUsableSize = getAppUsableScreenSize(mContext);
       Point realScreenSize = getRealScreenSize(mContext);
      
       boolean hasBackKey=false;
       // navigation bar at the bottom
       if (appUsableSize.y < realScreenSize.y) {
           hasBackKey=true;
       }
      
      
      
      
       // This is added to fix soft navigationBar's overlapping to content above LOLLIPOP
       int bottomPadding = viewActivity.getPaddingBottom() + insets.bottom;
      
       if (hasBackKey ) {//there's a navigation bar
           bottomPadding += getNavigationBarHeight();
       }
      
       this.setPadding(viewActivity.getPaddingLeft() + insets.left,
               viewActivity.getPaddingTop() + insets.top,
               viewActivity.getPaddingRight() + insets.right,
               bottomPadding);
       insets.left = insets.top = insets.right = insets.bottom = 0;
       return true;
      

      }

      public static Point getAppUsableScreenSize(Context context) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); Point size = new Point(); display.getSize(size); return size; }

      public static Point getRealScreenSize(Context context) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); Point size = new Point();

       if (Build.VERSION.SDK_INT >= 17) {
           display.getRealSize(size);
       } else if (Build.VERSION.SDK_INT >= 14) {
           try {
               size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
               size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
           } catch (IllegalAccessException e) {} catch (InvocationTargetException e) {} catch (NoSuchMethodException e) {}
       }
      
       return size;
      

      }

      private int getNavigationBarHeight() { Resources resources = getResources(); int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } return 0; }

      /**

      • Set up the activity;
      • @param activity */ public void attachToActivity(Activity activity) { initValue(activity); setShadowAdjustScaleXByOrientation(); viewDecor.addView(this, 0); }

      private void initValue(Activity activity) { this.activity = activity; leftMenuItems = new ArrayList(); rightMenuItems = new ArrayList(); ignoredViews = new ArrayList(); viewDecor = (ViewGroup) activity.getWindow().getDecorView(); viewActivity = new TouchDisableView(this.activity);

       View mContent = viewDecor.getChildAt(0);
       viewDecor.removeViewAt(0);
       viewActivity.setContent(mContent);
       addView(viewActivity);
      
       ViewGroup parent = (ViewGroup) scrollViewLeftMenu.getParent();
       parent.removeView(scrollViewLeftMenu);
       parent.removeView(scrollViewRightMenu);
      

      }

      private void setShadowAdjustScaleXByOrientation() { int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { shadowAdjustScaleX = 0.034f; shadowAdjustScaleY = 0.12f; } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { shadowAdjustScaleX = 0.06f; shadowAdjustScaleY = 0.07f; } }

      /**

      • Set the background image of menu;
      • @param imageResource */ public void setBackground(int imageResource) { imageViewBackground.setImageResource(imageResource); }

      /**

      • The visibility of the shadow under the activity;
      • @param isVisible */ public void setShadowVisible(boolean isVisible) { if (isVisible) imageViewShadow.setBackgroundResource(R.drawable.shadow); else imageViewShadow.setBackgroundResource(0); }

      /**

      • Add a single item to the left menu;
      • WARNING: It will be removed from v2.0.
      • @param menuItem */ @Deprecated public void addMenuItem(ResideMenuItem menuItem) { this.leftMenuItems.add(menuItem); layoutLeftMenu.addView(menuItem); }

      /**

      • Add a single items;
      • @param menuItem
      • @param direction */ public void addMenuItem(ResideMenuItem menuItem, int direction) { if (direction == DIRECTION_LEFT) { this.leftMenuItems.add(menuItem); layoutLeftMenu.addView(menuItem); } else { this.rightMenuItems.add(menuItem); layoutRightMenu.addView(menuItem); } }

      /**

      • WARNING: It will be removed from v2.0.
      • @param menuItems */ @Deprecated public void setMenuItems(List menuItems) { this.leftMenuItems = menuItems; rebuildMenu(); }

      /**

      • Set menu items by a array;
      • @param menuItems
      • @param direction */ public void setMenuItems(List menuItems, int direction) { if (direction == DIRECTION_LEFT) this.leftMenuItems = menuItems; else this.rightMenuItems = menuItems; rebuildMenu(); }

      private void rebuildMenu() { if (layoutLeftMenu != null) { layoutLeftMenu.removeAllViews(); for (ResideMenuItem leftMenuItem : leftMenuItems) layoutLeftMenu.addView(leftMenuItem); }

       if (layoutRightMenu != null) {
           layoutRightMenu.removeAllViews();
           for (ResideMenuItem rightMenuItem : rightMenuItems)
               layoutRightMenu.addView(rightMenuItem);
       }
      

      }

      /**

      • WARNING: It will be removed from v2.0.
      • @return */ @Deprecated public List getMenuItems() { return leftMenuItems; }

      /**

      • Return instances of menu items;
      • @return */ public List getMenuItems(int direction) { if (direction == DIRECTION_LEFT) return leftMenuItems; else return rightMenuItems; }

      /**

      • If you need to do something on closing or opening menu,
      • set a listener here.
      • @return */ public void setMenuListener(OnMenuListener menuListener) { this.menuListener = menuListener; }

      public OnMenuListener getMenuListener() { return menuListener; }

      /**

      • Show the menu; */ public void openMenu(int direction) {

        setScaleDirection(direction);

        isOpened = true; AnimatorSet scaleDown_activity = buildScaleDownAnimation(viewActivity, mScaleValue, mScaleValue); AnimatorSet scaleDown_shadow = buildScaleDownAnimation(imageViewShadow, mScaleValue + shadowAdjustScaleX, mScaleValue + shadowAdjustScaleY); AnimatorSet alpha_menu = buildMenuAnimation(scrollViewMenu, 1.0f); scaleDown_shadow.addListener(animationListener); scaleDown_activity.playTogether(scaleDown_shadow); scaleDown_activity.playTogether(alpha_menu); scaleDown_activity.start(); }

      /**

      • Close the menu; */ public void closeMenu() {

        isOpened = false; AnimatorSet scaleUp_activity = buildScaleUpAnimation(viewActivity, 1.0f, 1.0f); AnimatorSet scaleUp_shadow = buildScaleUpAnimation(imageViewShadow, 1.0f, 1.0f); AnimatorSet alpha_menu = buildMenuAnimation(scrollViewMenu, 0.0f); scaleUp_activity.addListener(animationListener); scaleUp_activity.playTogether(scaleUp_shadow); scaleUp_activity.playTogether(alpha_menu); scaleUp_activity.start(); }

      @Deprecated public void setDirectionDisable(int direction) { disabledSwipeDirection.add(direction); }

      public void setSwipeDirectionDisable(int direction) { disabledSwipeDirection.add(direction); }

      private boolean isInDisableDirection(int direction) { return disabledSwipeDirection.contains(direction); }

      private void setScaleDirection(int direction) {

       int screenWidth = getScreenWidth();
       float pivotX;
       float pivotY = getScreenHeight() * 0.5f;
      
       if (direction == DIRECTION_LEFT) {
           scrollViewMenu = scrollViewLeftMenu;
           pivotX = screenWidth * 1.5f;
       } else {
           scrollViewMenu = scrollViewRightMenu;
           pivotX = screenWidth * -0.5f;
       }
      
       ViewHelper.setPivotX(viewActivity, pivotX);
       ViewHelper.setPivotY(viewActivity, pivotY);
       ViewHelper.setPivotX(imageViewShadow, pivotX);
       ViewHelper.setPivotY(imageViewShadow, pivotY);
       scaleDirection = direction;
      

      }

      /**

      • return the flag of menu status;
      • @return */ public boolean isOpened() { return isOpened; }

      private OnClickListener viewActivityOnClickListener = new OnClickListener() { @Override public void onClick(View view) { if (isOpened()) closeMenu(); } };

      private Animator.AnimatorListener animationListener = new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { if (isOpened()) { showScrollViewMenu(scrollViewMenu); if (menuListener != null) menuListener.openMenu(); } }

       @Override
       public void onAnimationEnd(Animator animation) {
           // reset the view;
           if (isOpened()) {
               viewActivity.setTouchDisable(true);
               viewActivity.setOnClickListener(viewActivityOnClickListener);
           } else {
               viewActivity.setTouchDisable(false);
               viewActivity.setOnClickListener(null);
               hideScrollViewMenu(scrollViewLeftMenu);
               hideScrollViewMenu(scrollViewRightMenu);
               if (menuListener != null)
                   menuListener.closeMenu();
           }
       }
      
       @Override
       public void onAnimationCancel(Animator animation) {
      
       }
      
       @Override
       public void onAnimationRepeat(Animator animation) {
      
       }
      

      };

      /**

      • A helper method to build scale down animation;

      • @param target

      • @param targetScaleX

      • @param targetScaleY

      • @return */ private AnimatorSet buildScaleDownAnimation(View target, float targetScaleX, float targetScaleY) {

        AnimatorSet scaleDown = new AnimatorSet(); scaleDown.playTogether( ObjectAnimator.ofFloat(target, "scaleX", targetScaleX), ObjectAnimator.ofFloat(target, "scaleY", targetScaleY) );

        if (mUse3D) { int angle = scaleDirection == DIRECTION_LEFT ? -ROTATE_Y_ANGLE : ROTATE_Y_ANGLE; scaleDown.playTogether(ObjectAnimator.ofFloat(target, "rotationY", angle)); }

        scaleDown.setInterpolator(AnimationUtils.loadInterpolator(activity, android.R.anim.decelerate_interpolator)); scaleDown.setDuration(250); return scaleDown; }

      /**

      • A helper method to build scale up animation;

      • @param target

      • @param targetScaleX

      • @param targetScaleY

      • @return */ private AnimatorSet buildScaleUpAnimation(View target, float targetScaleX, float targetScaleY) {

        AnimatorSet scaleUp = new AnimatorSet(); scaleUp.playTogether( ObjectAnimator.ofFloat(target, "scaleX", targetScaleX), ObjectAnimator.ofFloat(target, "scaleY", targetScaleY) );

        if (mUse3D) { scaleUp.playTogether(ObjectAnimator.ofFloat(target, "rotationY", 0)); }

        scaleUp.setDuration(250); return scaleUp; }

      private AnimatorSet buildMenuAnimation(View target, float alpha) {

       AnimatorSet alphaAnimation = new AnimatorSet();
       alphaAnimation.playTogether(
               ObjectAnimator.ofFloat(target, "alpha", alpha)
       );
      
       alphaAnimation.setDuration(250);
       return alphaAnimation;
      

      }

      /**

      • If there were some view you don't want reside menu
      • to intercept their touch event, you could add it to
      • ignored views.
      • @param v */ public void addIgnoredView(View v) { ignoredViews.add(v); }

      /**

      • Remove a view from ignored views;
      • @param v */ public void removeIgnoredView(View v) { ignoredViews.remove(v); }

      /**

      • Clear the ignored view list; */ public void clearIgnoredViewList() { ignoredViews.clear(); }

      /**

      • If the motion event was relative to the view
      • which in ignored view list,return true;
      • @param ev
      • @return */ private boolean isInIgnoredView(MotionEvent ev) { Rect rect = new Rect(); for (View v : ignoredViews) { v.getGlobalVisibleRect(rect); if (rect.contains((int) ev.getX(), (int) ev.getY())) return true; } return false; }

      private void setScaleDirectionByRawX(float currentRawX) { if (currentRawX < lastRawX) setScaleDirection(DIRECTION_RIGHT); else setScaleDirection(DIRECTION_LEFT); }

      private float getTargetScale(float currentRawX) { float scaleFloatX = ((currentRawX - lastRawX) / getScreenWidth()) * 0.75f; scaleFloatX = scaleDirection == DIRECTION_RIGHT ? -scaleFloatX : scaleFloatX;

       float targetScale = ViewHelper.getScaleX(viewActivity) - scaleFloatX;
       targetScale = targetScale > 1.0f ? 1.0f : targetScale;
       targetScale = targetScale < 0.5f ? 0.5f : targetScale;
       return targetScale;
      

      }

      private float lastActionDownX, lastActionDownY;

      @Override public boolean dispatchTouchEvent(MotionEvent ev) { float currentActivityScaleX = ViewHelper.getScaleX(viewActivity); if (currentActivityScaleX == 1.0f) setScaleDirectionByRawX(ev.getRawX());

       switch (ev.getAction()) {
           case MotionEvent.ACTION_DOWN:
               lastActionDownX = ev.getX();
               lastActionDownY = ev.getY();
               isInIgnoredView = isInIgnoredView(ev) && !isOpened();
               pressedState = PRESSED_DOWN;
               break;
      
           case MotionEvent.ACTION_MOVE:
               if (isInIgnoredView || isInDisableDirection(scaleDirection))
                   break;
      
               if (pressedState != PRESSED_DOWN &&
                       pressedState != PRESSED_MOVE_HORIZONTAL)
                   break;
      
               int xOffset = (int) (ev.getX() - lastActionDownX);
               int yOffset = (int) (ev.getY() - lastActionDownY);
      
               if (pressedState == PRESSED_DOWN) {
                   if (yOffset > 25 || yOffset < -25) {
                       pressedState = PRESSED_MOVE_VERTICAL;
                       break;
                   }
                   if (xOffset < -50 || xOffset > 50) {
                       pressedState = PRESSED_MOVE_HORIZONTAL;
                       ev.setAction(MotionEvent.ACTION_CANCEL);
                   }
               } else if (pressedState == PRESSED_MOVE_HORIZONTAL) {
                   if (currentActivityScaleX < 0.95)
                       showScrollViewMenu(scrollViewMenu);
      
                   float targetScale = getTargetScale(ev.getRawX());
                   if (mUse3D) {
                       float angle = scaleDirection == DIRECTION_LEFT ? -ROTATE_Y_ANGLE : ROTATE_Y_ANGLE;
                           //int angle = scaleDirection == DIRECTION_LEFT ? -ROTATE_Y_ANGLE : ROTATE_Y_ANGLE;
                       angle *= (1 - targetScale) * 2;
                       ViewHelper.setRotationY(viewActivity, angle);
      
                       ViewHelper.setScaleX(imageViewShadow, targetScale - shadowAdjustScaleX);
                       ViewHelper.setScaleY(imageViewShadow, targetScale - shadowAdjustScaleY);
                   } else {
                       ViewHelper.setScaleX(imageViewShadow, targetScale + shadowAdjustScaleX);
                       ViewHelper.setScaleY(imageViewShadow, targetScale + shadowAdjustScaleY);
                   }
                   ViewHelper.setScaleX(viewActivity, targetScale);
                   ViewHelper.setScaleY(viewActivity, targetScale);
                   ViewHelper.setAlpha(scrollViewMenu, (1 - targetScale) * 2.0f);
      
                   lastRawX = ev.getRawX();
                   return true;
               }
      
               break;
      
           case MotionEvent.ACTION_UP:
      
               if (isInIgnoredView) break;
               if (pressedState != PRESSED_MOVE_HORIZONTAL) break;
      
               pressedState = PRESSED_DONE;
               if (isOpened()) {
                   if (currentActivityScaleX > 0.56f)
                       closeMenu();
                   else
                       openMenu(scaleDirection);
               } else {
                   if (currentActivityScaleX < 0.94f) {
                       openMenu(scaleDirection);
                   } else {
                       closeMenu();
                   }
               }
      
               break;
      
       }
       lastRawX = ev.getRawX();
       return super.dispatchTouchEvent(ev);
      

      }

      public int getScreenHeight() { activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.heightPixels; }

      public int getScreenWidth() { activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.widthPixels; }

      public void setScaleValue(float scaleValue) { this.mScaleValue = scaleValue; }

      public void setUse3D(boolean use3D) { mUse3D = use3D; }

      public interface OnMenuListener {

       /**
        * This method will be called at the finished time of opening menu animations.
        */
       public void openMenu();
      
       /**
        * This method will be called at the finished time of closing menu animations.
        */
       public void closeMenu();
      

      }

      private void showScrollViewMenu(View scrollViewMenu) { if (scrollViewMenu != null && scrollViewMenu.getParent() == null) { addView(scrollViewMenu); } }

      private void hideScrollViewMenu(View scrollViewMenu) { if (scrollViewMenu != null && scrollViewMenu.getParent() != null) { removeView(scrollViewMenu); } } }

    Originally posted by @niteshsirohi1 in https://github.com/SpecialCyCi/AndroidResideMenu/issues/127#issuecomment-298280467

    opened by shiv2810 0
  • Scroll view Issue

    Scroll view Issue

    i am also facing same problem, when i use scroll view with reside menu it does not scroll all up to end of scroll view , please provide me a solution for this problem

    opened by Bilal5008 1
  • Space at the bottom of devices

    Space at the bottom of devices

    Space at the bottom of devices which are either flagship or new android phones . Especially those devices where you can hide the navigation bar from settings and navigate through gesture.

    opened by ghost 7
Releases(1.6)
  • 1.6(Jan 7, 2015)

  • 1.5(Dec 3, 2014)

    1. Add fitSystemWindows(Rect insets) method to avoid undesired status bar overlay. Remove private method setViewPadding(). _(Thanks @RlagoMan)_ 2965c94a5f83f6616e7c1e934531893f4bd2792f #13
    2. Fixed activity not fitting into the dark placeholder. 97d9b833639cc5b0f81dcd6a0e8d1a984d07db93 #18 #19
    3. It should remove the other menu view while showing a menu. ada024575f59464a06be1df49cf32bf34150b0b8 #30
    4. Fix bug for setShadowVisible. 27b6491b0bc9d047a6ac6526e73d9724409b46a9
    Source code(tar.gz)
    Source code(zip)
  • 1.4.2(Aug 31, 2014)

  • 1.4.1(May 30, 2014)

    Change Log

    • Fix the conflict with ListView.
    • Fix the conflict with OnItemClickListener.

    Version Migration

    Upgrading to v1.4.1 from v1.3, v1.2, v1.1, v1.0

    Duplicate the followed code in dispatchTouchEvent() of Activity, replace the old dispatchTouchEvent() code.

        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            return resideMenu.dispatchTouchEvent(ev);
        }
    
    Source code(tar.gz)
    Source code(zip)
  • v1.3(May 26, 2014)

  • v1.2(Apr 14, 2014)

Owner
Special
Special
An extension of ResideMenu

Folder-ResideMenu =========== A Special Drawer. An extension of AndroidResideMenu Screenshot Please waiting for loading the images... Usage init Resid

Dean Ding 372 Oct 7, 2022
A menu consisting of icons (ImageViews) and metaball bouncing selection to give a blob effect. Inspired by Material design

Metaball-Menu A menu consisting of icons (ImageViews) and metaball bouncing selection to give a blob effect. Inspired by Material design ScreenShot Us

AbYsMeL 198 Sep 15, 2022
An android custom view which looks like the menu in Path 2.0 (for iOS).

ArcMenu & RayMenu ArcMenu An android custom view which looks like the menu in Path 2.0 (for iOS). RayMenu About The user experience in Path 2.0 (for i

daCapricorn 1.3k Nov 29, 2022
iOS UIActionSheet for Android

ActionSheet This is like iOS UIActionSheet component, has iOS6 and iOS7 style, support custom style, background, button image, text color and spacing

星一 810 Nov 10, 2022
iOS UIActionSheet for Android

ActionSheet This is like iOS UIActionSheet component, has iOS6 and iOS7 style, support custom style, background, button image, text color and spacing

星一 810 Nov 10, 2022
Bike-share - Jetpack Compose and SwiftUI based Kotlin Multiplatform sample project

BikeShare Jetpack Compose and SwiftUI based Kotlin Multiplatform sample project

Andrew Steinmetz 1 Feb 15, 2022
Android-NewPopupMenu 3.9 0.0 Java is an android library to create popup menu with GoogleMusic app-like style.

Android-NewPopupMenu Android-NewPopupMenu is an android library to create popup menu with GoogleMusic app-like style. Requirements Tested with APIv4 H

u1aryz 159 Nov 21, 2022
BottomSheet-Android - A simple customizable BottomSheet Library for Android Kotlin

BottomSheet-Android A simple customizable BottomSheet Library for Android Kotlin

Munachimso Ugorji 0 Jan 3, 2022
Animations for Android L drawer, back, dismiss and check icons

Material Menu Morphing Android menu, back, dismiss and check buttons Have full control of the animation: Including in your project compile 'com.balysv

Balys Valentukevicius 2.5k Dec 30, 2022
Simple and easy to use circular menu widget for Android.

Deprecated This project is no longer maintained. No new issues or pull requests will be accepted. You can still use the source or fork the project to

Anup Cowkur 420 Nov 25, 2022
A multicard menu that can open and close with animation on android

MultiCardMenu A multicard menu that can open and close with animation on android,require API level >= 11 Demo ##Usage <net.wujingchao.android.view.

null 562 Nov 10, 2022
An Android Library that allows users to pull down a menu and select different actions. It can be implemented inside ScrollView, GridView, ListView.

AndroidPullMenu AndroidPullMenu is an Open Source Android library that allows developers to easily create applications with pull menu. The aim of this

Armando TBA 181 Nov 29, 2022
Android PopupMenu and iOS14+ UIMenu components for react-native.

Android PopupMenu and iOS14+ UIMenu components for react-native. Falls back to ActionSheet for versions below iOS14.

null 568 Jan 1, 2023
an animated circular menu for Android

CircularFloatingActionMenu An animated, customizable circular floating menu for Android, inspired by Path app. Getting Started Requirements API >= 15

Oğuz Bilgener 2.7k Dec 24, 2022
A menu which can ... BOOM! - Android

BoomMenu 2.0.0 Comes Finally Approximately 8 months ago, I got an inspiration to creating something that can boom and show menu, which I named it Boom

Nightonke 5.8k Dec 27, 2022
Android library that provides the floating action button to sheet transition from Google's Material Design.

MaterialSheetFab Library that implements the floating action button to sheet transition from Google's Material Design documentation. It can be used wi

Gordon Wong 1.6k Dec 13, 2022
Android Satellite Menu

#Satellite Menu 'Path' has a very attractive menu sitting on the left bottom corner of the screen. Satellite Menu is the open version of this menu. Fo

Siyamed SINIR 1.4k Nov 15, 2022
DropDownMenu for Android,Filter the list based on multiple condition.

DropDownMenu DropDownMenu for Android,filter the list based on multiple condition. To get this project into your build Step 1. Add the specific reposi

Jay.Fang 808 Nov 10, 2022