3

Android の座標系に問題があるようです。( を要求せずにFEATURE_NO_TITLE) 通常のビューを取得したら、 を取得しますint contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();。これにより、ステータスバーとタイトルバーが得られ76pxます。38px38px

ただし、リクエストFEATURE_NO_TITLEしてから手順を繰り返すと、ステータスバーがまだ表示されているにもかかわらず、getTop()が返されます!0px

通常、コンテンツ ビューがどこから始まるかは気にしないため、この不一致は違いを生むことはありません。ただし、表示されているウィンドウ全体をカバーする装飾ビューにビューを配置しているため、私にとっては重要です。

0カスタム タイトルバーを要求して高さを指定すると、getTop()が返されるため、これはタイトルバーとデバイスの密度のトリックではないことがわかっています38px

解決策/回避策は、リクエスト時に 38 ピクセルを手動で追加することFEATURE_NO_TITLEです。私の質問は:これは Android のバグですか? または、この動作を理解できるようにするレイアウトの仕組みについて、私が理解していないことがありますか?

前もって感謝します!

問題を再現する最小限のプログラムを次に示します。2 回実行し、示された行のコメントを外します。私は Android SDK 7 に対してコンパイルし、Android 2.3.4 を搭載した Samsung Galaxy S で実行しています。

レイアウト: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);
            }
        });

    }
}

参考文献

4

2 に答える 2

4

これはAndroidのバグですか?

いいえ。システムは、両方の場合でわずかに異なるビュー階層を構築するだけで、不必要な深さを回避します(パフォーマンス上の理由から、(ネストされた) レイアウト要素が増えると、オーバーヘッドが増えます)

階層がタイトルバーでどのように見えるかを次に示します。

注: 小さいエミュレーターでサンプルを実行したため、私のピクセル値はあなたのものとは少し異なります。この場合は問題にならないはずです。

ここに画像の説明を入力 フルサイズ

タイトルバーとコンテンツ レイアウトを保持する基本的な LinearLayout は、ディスプレイ全体を埋めます。また、ステータス バーが通常の UI 階層をオーバーレイするため、ここには 25 ピクセルのパディングがあります。そのため、パディングによって確保されたスペースが必要です。

次に、同じく 25 ピクセルの高さで、LinearLayout の最初の要素としてタイトルバーに続きます。つまりfindViewById(Window.ID_ANDROID_CONTENT).getTop();、 contentview FrameLayout は親 LinearLayout の上部から 50 ピクセル(ここでも 25 パディング + 25 タイトル)であるため、合計で 50 が返されます。どちらが正しい。

では、タイトルバーが削除されるとどうなるでしょうか?

ここに画像の説明を入力 フルサイズ

システムは外側の LinearLayout を完全に削除します。つまり、コンテンツ ビューが画面全体を占めるようになります。findViewById(Window.ID_ANDROID_CONTENT).getTop();ここで 0 を返す必要があります。これは間違っていません。ただし、ステータスバー用に再度スペースを確保する必要があります。システムはそのパディングを contentview に割り当てました。

修正方法

解決策は非常に簡単だと思います。正確な結果を得るには、コンテンツビューのパディングを含める必要があります。例: 変更

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

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

これは私にとって正しい結果を出力します。

于 2012-05-24T10:04:07.863 に答える
0

これは、使用しているAndroidのバージョンによって異なります。Samsung Galaxy Y (2.3.6) と HTC Desire HD (2.3.5) であなたのコードを試しましたが、あなたが説明したとおりに発生しました。しかし、HTC ONE V (4.0.3) では予想通りの結果になりました。タイトルのないビュー top は 0 px を返しました。したがって、すべての電話で正しく結果が得られるとは限らないため、この出力に依存しないでください。

于 2012-06-14T08:44:48.870 に答える