DrawerLayout 模仿google官方左滑,menu内容延伸到通知栏

来源:互联网 发布:电力工程计价软件 编辑:程序博客网 时间:2024/05/16 14:49

 NavigationView extends ScrimInsetsFrameLayout


    最近做项目,要模仿google官方应用,使用drawerLayout,达到如下效果

snapshot.tiff

    即,menu栏的顶部可以显示到通知栏中。

    1. 使用NavigationVIew 作为menu ,并且需要在DrawerLayout ,NavigationView 设置 android:fitsSystemWindows="true" 属性,该属性可以写在xml中,也可以使用代码,但是注意使用地方,当其用到做为activivty 的 theme 时,会引发toast 布局错位,文本显示不全的问题。

    

<?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">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:background="@android:color/holo_red_light">        <android.support.v7.widget.Toolbar            android:id="@+id/toolbar"            android:layout_width="match_parent"            android:layout_height="?attr/actionBarSize"            android:background="?attr/colorPrimary"            app:popupTheme="@style/AppTheme.PopupOverlay" />        <Button            android:id="@+id/nextbtn"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="nextBtn"/>    </LinearLayout>    <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"        app:headerLayout="@layout/nav_header_main"        app:menu="@menu/activity_main_drawer" /></android.support.v4.widget.DrawerLayout>

     在这里使用了toolbar ,

  Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);  需啊添加以下代码,setSupportActionBar(toolbar);
  values-21 ,设置属性
  <pre name="code" class="html">   <style name="AppTheme.NoActionBar">        <item name="windowActionBar">false</item>        <item name="windowNoTitle">true</item>        <item name="android:windowDrawsSystemBarBackgrounds">true</item>        <item name="android:statusBarColor">@android:color/transparent</item>    </style>

2. 当menu使用的是其他控件,例如listview。
  <pre name="code" class="html"><com.instanza.cocovoice.uiwidget.HackyDrawerLayout 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:context=".MainActivity">    <com.instanza.cocovoice.activity.base.SomaActionbarFrameLayout        android:id="@+id/frame"        android:fitsSystemWindows="true"        android:layout_width="match_parent"        android:layout_height="match_parent"/>    <com.instanza.cocovoice.uiwidget.ScrimInsetsFrameLayout        android:id="@+id/drawer_left"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="start"        app:insetForeground="#4000"          android:fitsSystemWindows="true">        <ListView            android:id="@+id/drawer_listview"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:layout_gravity="start"            android:background="@color/white"            android:choiceMode="singleChoice"            android:divider="@null"            android:scrollbars="none"></ListView>    </com.instanza.cocovoice.uiwidget.ScrimInsetsFrameLayout></com.instanza.cocovoice.uiwidget.HackyDrawerLayout>

主要是listview要有个父控件ScrimInsetsFrameLayout,

app:insetForeground="#4000"  则是设置遮罩的阴影颜色。
<pre name="code" class="html">public class ScrimInsetsFrameLayout extends FrameLayout{    private Drawable mInsetForeground;    private Rect mInsets;    private Rect mTempRect = new Rect();    private OnInsetsCallback mOnInsetsCallback;    public ScrimInsetsFrameLayout(Context context) {        super(context);        init(context, null, 0);    }    public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init(context, attrs, 0);    }    public ScrimInsetsFrameLayout(            Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context, attrs, defStyle);    }    private void init(Context context, AttributeSet attrs, int defStyle) {        final TypedArray a = context.obtainStyledAttributes(attrs,                R.styleable.ScrimInsetsView, defStyle, 0);        if (a == null) {            return;        }        mInsetForeground = a.getDrawable(                R.styleable.ScrimInsetsView_insetForeground);        a.recycle();        setWillNotDraw(true);    }    @Override    protected boolean fitSystemWindows(Rect insets) {        mInsets = new Rect(insets);        setWillNotDraw(mInsetForeground == null);        ViewCompat.postInvalidateOnAnimation(this);        if (mOnInsetsCallback != null) {            mOnInsetsCallback.onInsetsChanged(insets);        }        return true; // consume insets    }    @Override    public void draw(Canvas canvas) {        super.draw(canvas);        int width = getWidth();        int height = getHeight();        if (mInsets != null && mInsetForeground != null) {            int sc = canvas.save();            canvas.translate(getScrollX(), getScrollY());            // Top            mTempRect.set(0, 0, width, mInsets.top);            mInsetForeground.setBounds(mTempRect);            mInsetForeground.draw(canvas);            // Bottom            mTempRect.set(0, height - mInsets.bottom, width, height);            mInsetForeground.setBounds(mTempRect);            mInsetForeground.draw(canvas);            // Left            mTempRect.set(                    0,                    mInsets.top,                    mInsets.left,                    height - mInsets.bottom);            mInsetForeground.setBounds(mTempRect);            mInsetForeground.draw(canvas);            // Right            mTempRect.set(                    width - mInsets.right,                    mInsets.top, width,                    height - mInsets.bottom);            mInsetForeground.setBounds(mTempRect);            mInsetForeground.draw(canvas);            canvas.restoreToCount(sc);        }    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        if (mInsetForeground != null) {            mInsetForeground.setCallback(this);        }    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        if (mInsetForeground != null) {            mInsetForeground.setCallback(null);        }    }    /**     * Allows the calling container to specify a callback for custom     * processing when insets change (i.e. when {@link #fitSystemWindows(Rect)}     * is called. This is useful for setting padding on UI elements     * based on UI chrome insets (e.g. a Google Map or a ListView).     * When using with ListView or GridView, remember to set     * clipToPadding to false.     */    public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) {        mOnInsetsCallback = onInsetsCallback;    }    public static interface OnInsetsCallback {        public void onInsetsChanged(Rect insets);    }}

在values-21
<pre name="code" class="html"><style name="Theme.App" parent="@style/Theme.AppCompat.Light.NoActionBar">    <item name="android:windowDrawsSystemBarBackgrounds">true</item>    <item name="android:statusBarColor">@android:color/transparent</item></style>


其实,第一种与第二种是一致的,因为
NavigationView extends ScrimInsetsFrameLayout

0 0