web-dev-qa-db-ja.com

フラグメントのコンテナとしてのandroid.R.id.content

私の状況は、フラグメントBを含むアクティビティAです。私は常にこのように実装します。

アクティビティAのレイアウト:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/container"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />

フラグメントBのレイアウト:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Button
        Android:id="@+id/button"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="@string/button_title"
        Android:layout_centerInParent="true"
        Android:background="@drawable/green_button"
        Android:textColor="@Android:color/white"/>

</RelativeLayout>

これはうまく機能しますが、Androidデバイスモニターを開いて階層の表示を見ると:

そのため、階層内に2つの同じ役に立たないFrameLayoutがあり、R.id.containerを切り取ることができます。私はこのようにします:

アクティビティAでのonCreate(Bundle args)の実装:

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

    getFragmentManager().beginTransaction()
        .add(Android.R.id.content, FragmentB.newInstance()).commit();
}

アクティビティのコンテンツを設定せず、フラグメントBをシステムコンテナAndroid.R.id.contentにアタッチします。これは私にとって素晴らしい働きをします。役に立たないインクルードを1つ削除しました。

私の質問は、この「ハック」を行うことをお勧めします。いずれにせよアプリケーションがクラッシュする可能性がありますか?また、この実装後にどのような問題が発生する可能性がありますか?誰かがこの質問で有益な経験を持っているかもしれませんか?

良い答えをくれたすべての人に感謝します。

15
Ilya Demidov

何も悪いことはありません。あなたが言ったように:あなたはあなたの余分なR.id.contentレイアウトを必要としないので...ただsetContentViewでそれを追加しないでください。 ActionBarの公式ドキュメントにもそれについての言及があります: http://developer.Android.com/guide/topics/ui/actionbar.html#Tabs

または、タブコンテンツがアクティビティのレイアウトを埋める場合、アクティビティにはレイアウトはまったく必要ありません(setContentView()を呼び出す必要もありません)。代わりに、Android.R.id.contentIDで参照できるデフォルトのルートビューに各フラグメントを配置できます。

14以上(ネイティブActionBarのため)のみを開発する場合は、すべて問題ないはずですが、support libを使用する場合は、以下のポイントをお読みください。

I. 19より前のサポートライブラリリビジョンを使用する場合:

重要なことは:あなたが開発するあなたの最小APIレベルは何ですか?

API <14をサポートするアプリでAppCompatを使用する場合は、さまざまな動作に注意する必要があります。 Android.R.id.content アプリケーションがコンテンツを表示する画面の一部です。ネイティブAPI14以降の場合この部分はアクティビティコンテンツを表示することになっているため、ActionBarのすぐ下の部分です。

AppCompatでは、ActionBarのネイティブサポートはありません。 Android.R.id.content アプリ画面全体のコンテナです。つまり、ActionBarはそこでエミュレートされ、標準のビュー階層として追加されるため、ActionBarを含みます。この問題を解決するには、APIが14未満で、異なるIDを使用しているかどうかを確認する必要があります。 R.id.action_bar_activity_content


正しいIDを取得するためのヘルパーメソッドを作成できます。

public static int getContentViewId() {
    return Build.VERSION.SDK_INT>=Build.VERSION_CODES.ICE_CREAM_SANDWICH ? Android.R.id.content : R.id.action_bar_activity_content;
}

したがって、14歳以上で開発している場合、これは完全に優れたソリューションです。カスタムActionBar実装(AppCompatなど)を使用する場合は、このトリックを実行する必要があります。


II。サポートライブラリリビジョン19(またはそれ以降)を使用する場合:

この動作はサポートライブラリリビジョン19で修正されたようです: https://code.google.com/p/Android/issues/detail?id=58108#c21

http://grepcode.com/file/repository.grepcode.com/Java/ext/com.google.Android/android/4.4.2_r1/Android/support/v7/app/ActionBarActivityDelegateBase.Java/#228

あなたは彼らが古いものを置き換えているのを見ることができます R.id.action_bar_activity_content 標準で Android.R.id.content (およびNO_IDを持つ古いAndroid.R.id.content)より良い互換性のために!したがって、Support Lib r19以降(またはネイティブフレームワークのみ)を使用する場合は、<14および14+の両方のバリアントでAndroid.R.id.contentのみを使用できます:)

21