文章标题 通过重写FrameLayout 中boolean fitSystemWindows(Rect insets)方法来实现ActionBar的Overlay模式不遮盖顶部的设计

应用场景:

在一个ListView显示图片的界面中,当ListView向下滑动的时候,actionbar是是浮动在GridView上面一层的。可是当ListView滚动到顶部,顶部的内容是全然显示出来的,当然这种情况一般ActionBar我们会做成透明效果。

主要代码:

1.对应的FrameLayout

...
@Override
    protected boolean fitSystemWindows(Rect insets) {
        mInsets = new Rect(insets);
        setWillNotDraw(mInsetBackground == null);
        postInvalidateOnAnimation();
        if (mOnInsetsCallback != null) {
            mOnInsetsCallback.onInsetsChanged(insets);
        }
        return true; // consume insets
    }
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        if (mInsets != null && mInsetBackground != null) {
            // Top
            mTempRect.set(0, 0, width, mInsets.top);
            mInsetBackground.setBounds(mTempRect);
            mInsetBackground.draw(canvas);
            // Bottom
            mTempRect.set(0, height - mInsets.bottom, width, height);
            mInsetBackground.setBounds(mTempRect);
            mInsetBackground.draw(canvas);
            // Left
            mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom);
            mInsetBackground.setBounds(mTempRect);
            mInsetBackground.draw(canvas);
            // Right
            mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom);
            mInsetBackground.setBounds(mTempRect);
            mInsetBackground.draw(canvas);
        }
    }
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mInsetBackground != null) {
            mInsetBackground.setCallback(this);
        }
    }
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mInsetBackground != null) {
            mInsetBackground.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);
    }
    ...

2.对应的activity

xxxlayout.setOnInsetsCallback(new DrawInsetsFrameLayout.OnInsetsCallback() {
            @Override
            public void onInsetsChanged(Rect insets) {
                // Update the map padding (inset the compass, zoom buttons, attribution, etc.)
                Log.i("", "insets.top = " + insets.top);
                View headerView = new View(MainActivity.this);
                AbsListView.LayoutParams params = new AbsListView.LayoutParams(LayoutParams.FILL_PARENT, insets.top);

                headerView.setLayoutParams(params);
                headerView.setBackgroundColor(0x33000000); 
                listView.addHeaderView(headerView);
            }
        });

3.actionbar风格的xml文件:

<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
    <item name="android:actionBarStyle">@style/TranslucentActionBar</item>
    <item name="android:windowActionBarOverlay">true</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>
<style name="TranslucentActionBar" parent="android:Widget.Holo.Light.ActionBar.Solid.Inverse">
    <item name="android:background">@null</item>
</style>

当中TranslucentActionBar是为自己定义的FrameLayout自己定义的一个属性,而activity的actionbar和statusbar在这里我们都是设置成了浮动模式的,注意<item name="android:windowTranslucentStatus">true</item>

4.最后是布局内容

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:yourapp="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />
    <xxxFrameLayout
        android:id="@+id/my_draw_insets_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        yourapp:insetBackground="#9000" />
</FrameLayout>

5.当然效果图是这种

文章标题
通过重写FrameLayout 中boolean fitSystemWindows(Rect insets)方法来实现ActionBar的Overlay模式不遮盖顶部的设计

文章标题
通过重写FrameLayout 中boolean fitSystemWindows(Rect insets)方法来实现ActionBar的Overlay模式不遮盖顶部的设计

最后鸣谢:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0930/1720.html