博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android ActionBar的Overlay模式如何不遮盖顶部内容的问题
阅读量:5134 次
发布时间:2019-06-13

本文共 7935 字,大约阅读时间需要 26 分钟。

关于actionbar的overlay模式请参考 一文。这篇文章讲的是如何在这种模式下让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(0, 0);

但是这种方式并不太规范,而且在4.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 android.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, 0);    }    public DrawInsetsFrameLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init(context, attrs, 0);    }    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.styleable.DrawInsetsFrameLayout, defStyle, 0);        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(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);    }}

其中最主要的就是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 android.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
> list = new ArrayList
>(); for (int i = 0; i < 103; i++) { Map
m = new HashMap
(); 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文件:

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" >
android:id="@+id/my_draw_insets_layout" android:layout_width="match_parent" android:layout_height="match_parent" yourapp:insetBackground="#9000" />

效果图:

转载于:https://www.cnblogs.com/zhujiabin/p/4251085.html

你可能感兴趣的文章
[转载]Hash
查看>>
Nuget:Newtonsoft.Json
查看>>
你是这样理解shell编程的嘛?
查看>>
前端性能优化之重排和重绘
查看>>
Assets和Raw区别
查看>>
【luogu4185】 [USACO18JAN]MooTube [并查集]
查看>>
手机号脱敏处理
查看>>
CI控制器调用内部方法并载入相应模板的做法
查看>>
Hdu - 1002 - A + B Problem II
查看>>
HDU - 2609 - How many
查看>>
每天CookBook之Python-003
查看>>
每天CookBook之Python-004
查看>>
Android设置Gmail邮箱
查看>>
StringBuffer的用法
查看>>
js编写时间选择框
查看>>
java基础英语---第二十四天
查看>>
webService客户端service方式搭建(四)
查看>>
初识HTML5
查看>>
思达报表工具Style Report基础教程—创建一个多数据块的联合(Union)、镜像(Mirror)...
查看>>
HNOI2019爆零记
查看>>