关于actionbar的overlay模式请参考 如何让android的actionbar浮动且透明 一文。这篇文章讲的是如何在这种模式下让actionbar不遮住顶部的内容。

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

其实很多人都能想到的是,将ListView加上一个高度和actionbar的高度相同的header不就行了吗?

但是,难点是如何得到actionbar的高度。

actionbar的高度其实是在android系统主题的资源文件中定义的,如果你没有主动去修改actionbar的高度,那么可以通过下面的代码来获取:

TypedArray actionbarSizeTypedArray = getActivity().obtainStyledAttributes(new int[] {
android.R.attr.actionBarSize
});
float h = actionbarSizeTypedArray.getDimension(, );

但是这种方式并不太规范,而且在android4.4之后,statusbar所在的区域也是可以显示内容的,这时你还得去计算statusbar的高度。

其 实FrameLayout 中boolean fitSystemWindows(Rect insets)方法的insets参数就包含了非内容区域的高度。fitSystemWindows会在加载的时候被调用,如果我们在ListView重 写fitSystemWindows不就可以知道该给ListView添加多高的HeaderView了吗?

但是一般我们不希望这样用 ListView,因为使用重写的ListView的几率实在太大了(下拉刷新ListView等),而采取另外的方法,把ListView和一个重写了 fitSystemWindows方法的FrameLayout放在同一个FrameLayout中,然后通过回调的方式来通知ListView已经获取 到了actionbar(或者+statusbar)的高度了。

我们将这个实现了fitSystemWindows方法的FrameLayout命名为:DrawInsetsFrameLayout

代码如下:

/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.drawinsetsframelayoutdemo;
import <span style="width: auto; height: auto; float: none;" id="6_nwp"><a style="text-decoration: none;" mpid="" target="_blank" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0930%2F1720%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=android&k0=android&kdi0=8&k1=style&kdi1=8&sid=1591b71c7abd51a3&ch=0&tu=u1921070&jk=3064ed901c653638&cf=29&rb=0&fv=16&stid=9&urlid=0&luki=1&seller_id=1&di=128" id="6_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">android</span></a></span>.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.FrameLayout;
/**
* A layout that draws something in the insets passed to {@link #fitSystemWindows(Rect)}, i.e. the area above UI chrome
* (status and navigation bars, overlay action bars).
*/
public class DrawInsetsFrameLayout extends FrameLayout {
private Drawable mInsetBackground;
private Rect mInsets;
private Rect mTempRect = new Rect();
private OnInsetsCallback mOnInsetsCallback;
public DrawInsetsFrameLayout(Context context) {
super(context);
init(context, null, );
}
public DrawInsetsFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, );
}
public DrawInsetsFrameLayout(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.<span style="width: auto; height: auto; float: none;" id="7_nwp"><a style="text-decoration: none;" mpid="" target="_blank" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0930%2F1720%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=style&k0=android&kdi0=8&k1=style&kdi1=8&sid=1591b71c7abd51a3&ch=0&tu=u1921070&jk=3064ed901c653638&cf=29&rb=0&fv=16&stid=9&urlid=0&luki=2&seller_id=1&di=128" id="7_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">style</span></a></span>able.DrawInsetsFrameLayout, defStyle, );
if (a == null) {
return;
}
mInsetBackground = a.getDrawable(R.styleable.DrawInsetsFrameLayout_insetBackground);
a.recycle();
setWillNotDraw(true);
}
@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(, , width, mInsets.top);
mInsetBackground.setBounds(mTempRect);
mInsetBackground.draw(canvas);
// Bottom
mTempRect.set(, height - mInsets.bottom, width, height);
mInsetBackground.setBounds(mTempRect);
mInsetBackground.draw(canvas);
// Left
mTempRect.set(, 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);
}
}

其中最主要的就是fitSystemWindows方法,其他的不过是绘制DrawInsetsFrameLayout在actionbar部分的显示颜色而已。

如何使用DrawInsetsFrameLayout呢?

package com.example.drawinsetsframelayoutdemo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import <span style="width: auto; height: auto; float: none;" id="5_nwp"><a style="text-decoration: none;" mpid="" target="_blank" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0930%2F1720%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=android&k0=android&kdi0=8&k1=style&kdi1=8&sid=1591b71c7abd51a3&ch=0&tu=u1921070&jk=3064ed901c653638&cf=29&rb=0&fv=16&stid=9&urlid=0&luki=1&seller_id=1&di=128" id="5_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">android</span></a></span>.app.Activity;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class MainActivity extends Activity {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView= (ListView) findViewById(R.id.listview);
String[] from = { "Text", "Button" };
int[] to = { R.id.text, R.id.button };
List<Map<String, ?>> list = new ArrayList<Map<String, ?>>();
for (int i = ; i < ; i++) {
Map<String, String> m = new HashMap<String, String>();
m.put("Text", "Text" + i);
m.put("Button", "Button" + i);
list.add(m);
}
SimpleAdapter adapter = new SimpleAdapter(this, list, R.layout.listitem, from, to);
listView.setAdapter(adapter); DrawInsetsFrameLayout drawInsetsFrameLayout = (DrawInsetsFrameLayout) findViewById(R.id.my_draw_insets_layout);
drawInsetsFrameLayout.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);
}
});
} }

设置actionbar风格的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:<span style="width: auto; height: auto; float: none;" id="1_nwp"><a style="text-decoration: none;" mpid="" target="_blank" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0930%2F1720%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=android&k0=android&kdi0=8&k1=style&kdi1=8&sid=1591b71c7abd51a3&ch=0&tu=u1921070&jk=3064ed901c653638&cf=29&rb=0&fv=16&stid=9&urlid=0&luki=1&seller_id=1&di=128" id="1_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">android</span></a></span>="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"
/>
<com.example.drawinsetsframelayoutdemo.DrawInsetsFrameLayout
<span style="width: auto; height: auto; float: none;" id="2_nwp"><a style="text-decoration: none;" mpid="" target="_blank" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0930%2F1720%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=android&k0=android&kdi0=8&k1=style&kdi1=8&sid=1591b71c7abd51a3&ch=0&tu=u1921070&jk=3064ed901c653638&cf=29&rb=0&fv=16&stid=9&urlid=0&luki=1&seller_id=1&di=128" id="2_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">android</span></a></span>:id="@+id/my_draw_insets_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
yourapp:insetBackground="#9000" />
</FrameLayout>

效果图:

Android ActionBar的Overlay模式如何不遮盖顶部内容的问题的更多相关文章

  1. Android Actionbar Tab 导航模式

    Android Actionbar Tab 下图中,红色矩形圈起来的就是我们 ActionBar Tab,下面我们将一步一步的实现下图中的效果. 初次尝试 package com.example.it ...

  2. Android Training精要(二)開啟ActionBar的Overlay模式

    在3.0上的實現 <resources> <!-- the theme applied to the application or activity --> <style ...

  3. Android ActionBar详解

    Android ActionBar详解 分类: Android2014-04-30 15:23 1094人阅读 评论(0) 收藏 举报 androidActionBar   目录(?)[+]   第4 ...

  4. Android ActionBar 关于tab的应用 以及 TabListener的方法详解

    actionBar的tab标签应用以及TabListener的方法详解 package com.example.actionBarTest.actionBarTab; import android.a ...

  5. ActionBar官方教程(10)ActionBar的下拉列表模式

    Adding Drop-down Navigation As another mode of navigation (or filtering) for your activity, the acti ...

  6. Android actionBar与Fragment结合使用Demo2

    上一篇文章介绍了ActionBar的使用,这里介绍ActionBar的还有一种用法.达到的效果和曾经的GroupActivity或TabHost是一样的,可作为导航来使用. 实现效果图: 源码: 布局 ...

  7. Android Immersive Mode (沉浸模式) 还是 Translucent Bars (透明状态栏)

    Immersive Mode (沉浸模式) 还是 Translucent Bars (透明状态栏) [科普]什么叫真正的“沉浸式”状态栏? 为什么在国内会有很多用户把「透明栏」(Translucent ...

  8. 【转】Android 当打开“开发者模式”中的“不保留活动”后,程序应当怎么保持正常运行

    当打开这个设置以后,程序的Activity会自动销毁,每次返回的时候就会不断重oncreate,此时伴随的问题多多. 参考文档:http://www.bubuko.com/infodetail-960 ...

  9. [Xamarin.Android] ActionBar Tips

    [Xamarin.Android] ActionBar Tips ActionBar用途 快速搞懂 ActionBar的用途,可以参考下列文章: [Android]使用 ActionBarCompat ...

随机推荐

  1. 11g RAC R2 之Linux DNS 配置

    在动手配置前,最好先了解下DNS的理论,以免犯不必要的错误.这都是被坑后的觉悟 -_-!!! Oracle 11g RAC 集群中引入了SCAN(SingleClientAccessName)的概念, ...

  2. Android--消除“Permission is only granted to system apps”错误

    原文:http://blog.csdn.net/gaojinshan/article/details/14230673 在AndroidManifest.xml中使用了如下的配置: <uses- ...

  3. hadoop的核心思想

    hadoop的核心思想 1.1.1. hadoop的核心思想 Hadoop包括两大核心,分布式存储系统和分布式计算系统. 1.1.1.1. 分布式存储 为什么数据需要存储在分布式的系统中哪,难道单一的 ...

  4. telnet 时代的 bbs

    人类曾经用telnet 来访问 bbs,后来有了www,web 浏览器取代了telnet Telnet协议是TCP/IP协议族中的一员 arp和ping的区别 ping也属于一个通信协议,是TCP/I ...

  5. Android之EditText

    EditText 属性介绍: maxLength:设置最大输入字符数. hint:设置空白提示文字. textColorHint:设置空白提示文字的颜色. enabled:设置是否可编辑(可以获得焦点 ...

  6. 1293: [SCOI2009]生日礼物 - BZOJ

    Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可以没有彩珠,但多个彩 ...

  7. smarty中的母板极制_extends和block标签

    模板继承 继承是从面向对象编程而来的概念,模板继承可以让你定义一个或多个父模板,提供给子模板来进行扩展. 扩展继承意味着子模板可以覆盖部分或全部父模板的块区域. 继承结构可以是多层次的,所以你可以继承 ...

  8. 【HDOJ】【4089】Activation

    概率DP kuangbin总结中的第5题 题解copy: HDU 4098 题意:有n个人排队等着在官网上激活游戏.Tomato排在第m个. 对于队列中的第一个人.有一下情况: 1.激活失败,留在队列 ...

  9. jquery获取标签内容,编辑内容

    一.获取页面元素 三种方式获取页面中元素的内容. input标签使用:.val()获取 标签下的html及文本内容:.html() 仅获取标签下的纯文本内容:.text() <head> ...

  10. Codeforces Round #363 (Div. 2)->A. Launch of Collider

    A. Launch of Collider time limit per test 2 seconds memory limit per test 256 megabytes input standa ...