Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
376 views
in Technique[技术] by (71.8m points)

material design - Android NavigationView displays under NavigationBar, and cannot be clicked

As you can see, the background of NavigationView has been set android:clipToPadding='false', and it can be seen under transparent NavigationBar.

BackGround NavigationView

But the NavigationView(NavigationDrawer) cannot fully scroll up to above the NavigationBar, how to solve this?

I want the list items scroll to the top of NavigationBar, which means the last Send is not under but above NavigationBar.


layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        android:clipToPadding="false"
        android:clipChildren="false"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer">
    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

Well, the code runs like this, and I cannot search for a useful answer.

Any idea is welcome, thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Thanks to mehrdad khosravi! His solution is really a good direction and is more artistic.

But I am too lazy, so I have another but not that artistic solution: extended from NavigationView.

package your.package;

import android.content.Context;
import android.support.design.widget.NavigationView;
import android.util.AttributeSet;

import another.package.ScreenTool;

/**
 * This view makes the NavigationDrawer fit system view.
 * Created by MewX on 1/19/2016.
 */
public class NavigationFitSystemView extends NavigationView {
    public NavigationFitSystemView(Context context) {
        super(context);
    }

    public NavigationFitSystemView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NavigationFitSystemView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {

        // TODO: optimize for tablet screen layout
        super.onMeasure(widthSpec, heightSpec- ScreenTool.getCurrentNavigationBarSize(getContext()).y);
    }
}

And, the ScreenTool.java:

package another.package;

import android.content.Context;
import android.graphics.Point;
import android.os.Build;
import android.view.Display;
import android.view.WindowManager;

/**
 * This class contains many screen-relate functions.
 * Created by MewX on 1/18/2016.
 */
@SuppressWarnings("unused")
public class ScreenTool {
    /**
     * get status bar height in px, this is the defined value whenever statusBar is displayed.
     * @param context current context
     * @return px int status bar height
     */
    public static int getStatusBarHeightValue(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result; // in px
    }

    /**
     * get navigation bar height in px, this is the defined value whenever navBar is displayed.
     * @param context current context
     * @return px int navigation bar height
     */
    public static int getNavigationBarHeightValue(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result; // in px
    }

    /**
     * get current navigation bar size:
     *   if bar not displaying, the values is zero;
     *   else is the width and height value;
     * @param context current context
     * @return new Point(width, height)
     */
    public static Point getCurrentNavigationBarSize(Context context) {
        Point appUsableSize = getAppUsableScreenSize(context);
        Point realScreenSize = getRealScreenSize(context);

        // navigation bar on the right
        if (appUsableSize.x < realScreenSize.x) {
            return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y);
        }

        // navigation bar at the bottom
        if (appUsableSize.y < realScreenSize.y) {
            return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y);
        }

        // navigation bar is not present
        return new Point();
    }

    /**
     * get application usable screen size.
     * @param context current size
     * @return new Point(width, height)
     */
    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;
    }

    /**
     * get actual/real screen size, this is the full screen size.
     * @param context current context
     * @return new Point(width, height)
     */
    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 (Exception e) {
                size = new Point(0, 0);
            }
        }
        return size;
    }
}

Then, change the layout file from <android.support.design.widget.NavigationView /> to <your.package.NavigationFitSystemView />


At last, change your references in other sources, like MainActivity.java

Finally, the screen looks like this, and can be dynamically changed whereas the NavigationBar hides or shows.

NavigationFitSystemView


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...