在我看来,安卓的坐标系有问题。当我有一个普通视图(没有请求FEATURE_NO_TITLE)时,我将检索int contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();。这给了我状态栏的76px38px和标题栏的38px
但是,如果我请求FEATURE_NO_TITLE然后重复该过程,getTop()将返回0px,尽管状态栏仍然可见!
这种差异不应该有什么区别,因为我们通常不关心内容视图从哪里开始。不过,这对我来说确实很重要,因为我将视图放置在装饰视图上——它覆盖了整个可见窗口。
我知道这不是标题栏和设备密度的技巧,因为如果我请求自定义标题栏,并给它0高度,那么getTop()返回38px
解决方案/解决方法是在请求FEATURE_NO_TITLE时手动添加38个像素。我的问题是:这是一个android错误吗?或者有什么我不理解的东西,布局是如何工作的,使这种行为可以理解?
提前谢谢!
这是一个极小的程序,再现了这个问题。运行两次,并取消注释指定的行。我是根据android sdk 7编译的,运行在三星galaxy s和android 2.3.4上。
布局:main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layoutParent"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/someId"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </LinearLayout>

</RelativeLayout>

代码:TestStatusBarActivity.java
package com.test.teststatusbar;

import android.app.Activity;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.Window;
import android.widget.RelativeLayout;

public class TestStatusBarActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Uncomment the following line to see the alternate behavior
        //requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.main);

        RelativeLayout layoutParent = (RelativeLayout) findViewById(R.id.layoutParent);
        View something = findViewById(R.id.someId);
        something.setBackgroundColor(Color.CYAN);

        ViewTreeObserver vto = layoutParent.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {

                // decor window top
                Rect rectgle = new Rect();
                Window window = getWindow();
                window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
                int StatusBarHeight = rectgle.top;

                // "content view" top
                int contentViewTop = window.findViewById(
                        Window.ID_ANDROID_CONTENT).getTop();

                int TitleBarHeight = contentViewTop - StatusBarHeight;

                Log.i("STATUSBARTEST", "StatusBar Height = " + StatusBarHeight
                        + " , TitleBar Height = " + TitleBarHeight
                        + ", Content top = " + contentViewTop);
            }
        });

    }
}

工具书类
Similar question that seems to sidestep the issue?
Source question that helped make this example

最佳答案

这是安卓系统的错误吗?
不。系统只是构建视图层次结构,两者略有不同,这样做可以避免不必要的深度(出于性能原因,更多(嵌套的)布局元素意味着更多的开销)。
下面是标题栏的层次结构:
注意:我的像素值与您的略有不同,因为我在一个较小的模拟器上运行了您的示例。这件事不重要。
full size
包含标题栏和内容布局的基本线性布局将填充整个显示。这里还有一个25px的填充,因为状态栏覆盖了正常的ui层次结构。所以必须通过填充保留一些空间。
然后跟随标题栏作为线性布局的第一个元素,同样具有25 px的高度。这意味着findViewById(Window.ID_ANDROID_CONTENT).getTop();总共返回50,因为contentview framelayout距离其父linearlayout的顶部有50个像素(同样是25个padding+25个title)。这是正确的。
那么,当车头标被移除时会发生什么?
full size
系统将完全删除外部线性布局,这意味着ContentView现在将填充整个屏幕。findViewById(Window.ID_ANDROID_CONTENT).getTop();应该在这里返回0,它实际上是做什么的。这不是错的。但必须为状态栏再次预留空间。系统将该填充分配给此处的ContentView。
如何修复
我认为解决方案非常简单:必须包含contentview的填充以获得准确的结果。例如改变

int contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();


View contentView = window.findViewById(Window.ID_ANDROID_CONTENT);
int contentViewTop = contentView.getTop() + contentView.getPaddingTop();

这给我打印了正确的结果。

10-08 06:49