SpecialCyCi / AndroidResideMenu

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.
MIT License
2.85k stars 1.1k forks source link

Cutting Screen #121

Open ashishislive opened 7 years ago

ashishislive commented 7 years ago

Hello, Residemenu measuring whole size of screen for rendering menu effect so it is not showing properly on those device have soft keys (home,back,recent) other then it is working as expected. I guess it is not excluding that extra space (soft key space)

niteshsirohi1 commented 7 years ago

check pull request.

Kishanjvaghela commented 7 years ago

You need to change in library source code

@Override
    protected boolean fitSystemWindows(Rect insets) {
        setMyPadding(insets);
        return true;
    }

    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            Rect rect = new Rect(
                    insets.getSystemWindowInsetLeft(),
                    insets.getSystemWindowInsetTop(),
                    insets.getSystemWindowInsetRight(),
                    insets.getSystemWindowInsetBottom()
            );
            setMyPadding(rect);
            return insets.consumeSystemWindowInsets();
        }
        return super.onApplyWindowInsets(insets);
    }

    private void setMyPadding(Rect rect) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (hasNavBar()) {
                WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
                switch (manager.getDefaultDisplay().getRotation()) {
                    case Surface.ROTATION_90:
                        rect.right += viewActivity.getPaddingRight() + getNavBarWidth();
                        break;
                    case Surface.ROTATION_180:
                        rect.top += viewActivity.getPaddingTop() + getNavBarHeight();
                        break;
                    case Surface.ROTATION_270:
                        rect.left += viewActivity.getPaddingLeft() + getNavBarWidth();
                        break;
                    default:
                        rect.bottom += viewActivity.getPaddingBottom() + getNavBarHeight();
                }
            }
        }
        setPadding(rect.left, rect.top, rect.right, rect.bottom);
    }

    private int getNavBarWidth() {
        return getNavBarDimen("navigation_bar_width");
    }

    private int getNavBarHeight() {
        return getNavBarDimen("navigation_bar_height");
    }

    private int getNavBarDimen(String resourceString) {
        Resources r = getResources();
        int id = r.getIdentifier(resourceString, "dimen", "android");
        if (id > 0) {
            return r.getDimensionPixelSize(id);
        } else {
            return 0;
        }
    }

    /**
     * check is system has navigation bar or not* http://stackoverflow.com/a/29120269/3758898
     *
     * @return true if navigation bar is present or false
     */
    boolean hasNavBar() {
        try {
            // check for emulator
            Class<?> serviceManager = Class.forName("android.os.ServiceManager");
            IBinder serviceBinder = (IBinder) serviceManager.getMethod("getService", String.class).invoke(serviceManager, "window");
            Class<?> stub = Class.forName("android.view.IWindowManager$Stub");
            Object windowManagerService = stub.getMethod("asInterface", IBinder.class).invoke(stub, serviceBinder);
            Method hasNavigationBar = windowManagerService.getClass().getMethod("hasNavigationBar");
            return (boolean) hasNavigationBar.invoke(windowManagerService);
        } catch (ClassNotFoundException
                | ClassCastException
                | NoSuchMethodException
                | SecurityException
                | IllegalAccessException
                | IllegalArgumentException
                | InvocationTargetException e) {

            boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
            boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);
            return !hasHomeKey && !hasBackKey;
        }
Scienticious commented 7 years ago

@Kishanjvaghela thanks

Paridhi2502 commented 6 years ago

Still issue in larger screen. Please help!

yocheved-check-in commented 5 years ago

Go to ResideMenu - > fitSystemWindows function This lines is in comment, just recomment it:

this.setPadding(viewActivity.getPaddingLeft() + insets.left, viewActivity.getPaddingTop() + insets.top, viewActivity.getPaddingRight() + insets.right, viewActivity.getPaddingBottom() + insets.bottom);

mani516 commented 5 years ago

I too was facing same issue with ResideMenu and tried different solutions. Finally i have found a clean solution which works in devices with all types of navigations including gesture navigations.

However, the only limitation is that, some other activity should be shown before showing this home activity (in which ResideMenu is used) like some Splash screen

  1. When this splash screen is launched, find its total height dynamically and save in some shared pref.
    private void setAppUsableHeight() {
        final View root = findViewById(android.R.id.content);
        if (root != null) {
            root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout()  {
                    root.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    int height = root.getHeight();
                    GILog.d(TAG, "TDV height: " + height);
                    saveLastCalculatedValueForAppUsableHeight(height, SplashActivity.this);
                }
            });
        }
    }
  2. Change attachToActivity() method of ResideMenu as follows
    public void attachToActivity(Activity activity, int customHeight) {
       // keep exiting implementation and add below lines to it
        if (customHeight > 0) {
            ViewGroup.LayoutParams params = viewActivity.getLayoutParams();
            if (params != null) {
                params.height = customHeight;
                viewActivity.setLayoutParams(params);
            }    
        }
    }
  3. Now, when Home screen (having reside menu) is launched, initialize ResideMenu as usual, adding these two extra lines
        resideMenu.setFitsSystemWindows(true);
        resideMenu.attachToActivity(this, getLastCalculatedValueForAppUsableHeight(this));
public static void saveLastCalculatedValueForAppUsableHeight(int height, Context context) {
        SharedPreferencesUtils.putSharedPreference(PREF_KEY_APP_USABLE_SCREEN_HEIGHT, String.valueOf(height), context);
    }

    public static int getLastCalculatedValueForAppUsableHeight(Context context) {
        String heightStr = SharedPreferencesUtils.getSharedPreference(PREF_KEY_APP_USABLE_SCREEN_HEIGHT, context);
        int height = 0;
        if (!TextUtils.isEmpty(heightStr)) {
            try {
                height = Integer.parseInt(heightStr);
            } catch (NumberFormatException e) {

            }
        }
        return height;
    }
  1. Also you should remove overriding implementation of public WindowInsets onApplyWindowInsets(WindowInsets insets) and protected boolean fitSystemWindows(Rect insets) methods in ResideMenu

Note: By doing this, the activity contents will not go behind the soft navigation bar. But the ResideMenu will still be behind the soft nav gar. But we can add an empty Menu item in the bottom to make sure all menu items are shown. Also, as our app is restricted to be only in Portrait mode, orientation changes are not handled, but you can do it easily.