フラグメントのテーマを設定する


117

フラグメントのテーマを設定しようとしています。

マニフェストでテーマを設定しても機能しません。

android:theme="@android:style/Theme.Holo.Light"

以前のブログを見ると、ContextThemeWrapperを使用する必要があるように見えます。コード化された例を誰かに紹介してもらえますか?何も見つかりません。

回答:


187

マニフェストにテーマを設定することは、通常、アクティビティに使用されます。

フラグメントのテーマを設定する場合は、フラグメントのonCreateView()に次のコードを追加します。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    // create ContextThemeWrapper from the original Activity Context with the custom theme
    final Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.yourCustomTheme);

    // clone the inflater using the ContextThemeWrapper
    LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);

    // inflate the layout using the cloned inflater, not default inflater
    return localInflater.inflate(R.layout.yourLayout, container, false);
}

30
これは私にはうまくいきません。フラグメントには、マニフェストファイルで指定されているテーマと同じテーマが含まれています。
ジョルジ

1
マニフェストでは、フラグメントではなく、アクティビティのテーマを指定します。あなたはfragmentまたはfragmentActivityを使用していますか?
David

1
私のために働いた。アクティビティ内のクラシックフラグメント。
David

8
@David "マニフェストのテーマの設定はアクティビティに使用されます"。これは完全に真実ではありません。実行時にFragmentTransactionを使用してフラグメントを追加する場合、そのテーマはフラグメントにも適用されます。
sebster 2013年

4
これは、ActionBarSherlockライブラリのSherlockFragmentActivityでは機能しないようです。
toobsco42 2013年

18

フラグメントは、そのアクティビティからテーマを取得します。各フラグメントには、そのフラグメントが存在するアクティビティのテーマが割り当てられます。

テーマはFragment.onCreateViewメソッドで適用されます。コードはビューを作成します。ビューは実際にはテーマが使用されるオブジェクトです。

Fragment.onCreateViewでは、ビューを膨らませるLayoutInflaterパラメーターを取得し、テーマに使用されるコンテキストを保持します。これは実際にはアクティビティです。したがって、インフレートされたビューはアクティビティのテーマを使用します。

テーマをオーバーライドするには、LayoutInflater.cloneInContextを呼び出します。これは、テーマの変更に使用できることをドキュメントで説明しています。ここではContextThemeWrapperを使用できます。次に、複製されたインフレーターを使用してフラグメントのビューを作成します。


Googleドキュメントとして、それを述べた:「... ...特定のコンテキストに関連付けられた新しいLayoutInflaterオブジェクトを尻のブランドを返します」 - developer.android.com/reference/android/view/...
クリス・

Davidsコードソリューションへの非常に役立つ追加。ありがとう!
muetzenflo

13

私が使用した単一のスタイルを適用するために

getContext().getTheme().applyStyle(styleId, true);

onCreateView()の断片の前にフラグメントのルートビューを膨張させると、それは私のために動作します。


1
min api 23 forgetContext()
警戒

あなたの分のAPIの問題への修正のために、この答えをチェックし@vigilancer:stackoverflow.com/questions/36736244/...
rm8x

1
素晴らしいソリューション。すべての子フラグメントにテーマを適用するonAttach(Context)にコードを追加しました
crysxd

これは、コンテキスト(ほとんどの場合はアクティビティ)のテーマを変更するため、予期しない結果をもたらす可能性があります。アクティビティの将来の膨張(たとえば、ローテーション後)では、どこでも新しいテーマが使用されます
Irhala

12

また、フラグメントダイアログをそのアクティビティとは異なるテーマで表示するように試み、この解決策に従いました。コメントで言及された一部の人々のように、私はそれを機能させておらず、ダイアログはマニフェストで指定されたテーマで表示され続けました。問題AlertDialog.Builderは、onCreateDialogメソッドでダイアログを作成していたため、onCreateViewリンク先の回答に示されているメソッドを使用していないことでした。そして、インスタンス化しているときに、代わりにインスタンス化されたものを使用するべきだったときにAlertDialog.Builder使用してコンテキストで渡していました。getActivity()ConstextThemeWrapper

これが私のonCreateDialogのコードです。

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Create ContextThemeWrapper from the original Activity Context
    ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(getActivity(), android.R.style.Theme_DeviceDefault_Light_Dialog);
    LayoutInflater inflater =   getActivity().getLayoutInflater().cloneInContext(contextThemeWrapper);
    // Now take note of the parameter passed into AlertDialog.Builder constructor
    AlertDialog.Builder builder = new AlertDialog.Builder(contextThemeWrapper);
    View view = inflater.inflate(R.layout.set_server_dialog, null);
    mEditText = (EditText) view.findViewById(R.id.txt_server);
    mEditText.requestFocus();  // Show soft keyboard automatically
    mEditText.setOnEditorActionListener(this);
    builder.setView(view);
    builder.setTitle(R.string.server_dialog);
    builder.setPositiveButton(android.R.string.ok, this);
    Dialog dialog = builder.create();
    dialog.setCanceledOnTouchOutside(false);
    return dialog;
}

私はもともとAlertDialog.Builder次のようにインスタンス化されていました:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

私が変更したもの:

AlertDialog.Builder builder = new AlertDialog.Builder(contextThemeWrapper);

この変更後、フラグメントダイアログは正しいテーマで表示されました。他の誰かが同様の問題を抱えており、AlertDialog.Builderthen を利用している場合は、ビルダーに渡されるコンテキストを確認してください。お役に立てれば!:)


9

android:minSdkVersion="11"マニフェストに設定したことを確認してください。これが、Davidが例がうまく機能しなかっます。

また、セットandroid:theme="@android:style/Theme.Holo.Light"の属性<application>タグとはありません<activity>タグ。

別の考えられる問題は、を使用するときにコンテキストを取得する方法ですContextThemeWrapper()getActivity().getApplicationContext()単にそれを置き換えるようなものを使用する場合getActivity()代わりに。

通常、Theme.HoloはMainActivityにリンクされたフラグメントに適用されます。

フラグメントに別のテーマを適用する場合は、ContextThemeWrapperを使用することに注意してください。フラグメントを追加するMainActivityからコードを提供すると役立つ場合があります。


いくつかの便利なリンク:

フラグメントのカスタムリストビューが親テーマに準拠していません


8

私はデイビッドがそれが機能することを提案したソリューションを試しましたが、すべてのシナリオではありません:
1.スタックに追加された最初のフラグメントはアクティビティのテーマを持ち、onCrateViewで定義されたものではなく、2番目のフラグメントでスタックに追加して、フラグメントに適用されていることを修正します。

2.それらが正しく表示された2番目のフラグメントで、メモリをクリーンアップしてアプリを強制的に閉じ、アプリを再度開き、フラグメントでアクティビティが再作成されたときに、フラグメントがそれらを間違って変更しましたアクティビティ。フラグメントのonCrateViewで設定されたものとは異なります。

この問題を修正するために、小さな変更を加え、inflater.inflateのコンテナー引数をnullに置き換えました。

インフレーターがいくつかのシナリオでコンテナービューからのコンテキストを使用する方法がわかりません。

注-そのandroid.support.v4.app.Fragment&android.support.v7.app.AppCompatActivityを使用しています。

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle   savedInstanceState) {

// create ContextThemeWrapper from the original Activity Context with the custom theme 
final Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.yourCustomTheme);

// clone the inflater using the ContextThemeWrapper 
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);

// inflate the layout using the cloned inflater, not default inflater 
return localInflater.inflate(R.layout.yourLayout, null, false);
} 

ありがとう、あなたの解決策は私を救います。私のDialogFragmentのテーマは、他のフラグメントとはどういうわけか違いました。付属のインフレーターを使用していたため、EditTextがおかしくなりました。私はContextThemeWrapperに関していくつかの助けを見つけましたが、それらはそれがどのように行われるかを示していません。あなたの解決策は私にとってうまくいきます。どうもありがとう。
Phuong Dao 2017

4

少し遅れていることはわかっていますが、助けになったため、他の人の役に立つかもしれません。フラグメントのonCreatView関数内に以下のコード行を追加してみることもできます。

    inflater.context.setTheme(R.style.yourCustomTheme)

2

Javaクラスを作成し、テーマを変更するレイアウトをonCreateメソッドで使用します。次に、それをマニフェストで通常どおり記述します。


1

特定のフラグメントにスタイルを適用するだけの場合は、onCreateView()またはonAttach()フラグメントを呼び出す前にこの行を追加します。

getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getActivity().getWindow().setStatusBarColor(Color.TRANSPARENT);

透明なステータスバーを設定する場合は、ルートレイアウトのプロパティにfalseを設定しfitsSystemWindowsます。

android:fitsSystemWindows="false"

1

インフレータを呼び出す前に、フラグメントコンテキストにテーマを設定することで機能します。

注:これは、MvvmCrossと組み合わせたXamarin.Androidの例です。これがJavaプログラマーでも機能するかどうかは、100%わかりません。しかし、あなたは試すことができます:)

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    Context.SetTheme(Theme);

    base.OnCreateView(inflater, container, savedInstanceState);

    var view = this.BindingInflate(FragmentLayoutId, container, false);

    // Doing some other stuff

    return view;
}

SetTheme拡張メソッドコード

public static void SetTheme(this Context context, AppThemeStyle themeStyle)
{
    var themeStyleResId = themeStyle == AppThemeStyle.Dark ? Resource.Style.AppTheme : Resource.Style.AppTheme_Light;

    context.SetTheme(themeStyleResId);
}

これが一部の人々の助けになることを願っています。


1

android:theme = "@style/myTheme"フラグメントのレイアウトファイルで使用して問題を解決しました。たとえば、これはのスタイルとLinearLayoutコンテンツを変更しますが、以外のことは変更しませんLinearLayout。したがって、フラグメント全体を任意のスタイルで装飾するには、テーマを最も外側の親レイアウトに適用します。

注:まだ解決策が見つからない場合に備えて、試してみることができます。

           <LinearLayout 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:theme = "@style/myTheme" >

            <TextView
                android:id="@+id/tc_buttom_text1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Time elapsed"/>

            <TextView
                android:id="@+id/tc_buttom_text2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="00:00:00 00"/>
        </LinearLayout>

-1

あなたはonAttachでロリポップのためにこれを試すことができます

最終的なウィンドウウィンドウ= activity.getWindow(); window.setStatusBarColor(myStatusBarColor)

オンデッタッチでデフォルトに戻します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.