web-dev-qa-db-ja.com

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

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

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

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

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

100
user1232691

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

テーマをフラグメントに設定する場合は、フラグメントの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);
}
166
David

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

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

Fragment.onCreateViewでは、ビューを拡張するLayoutInflaterパラメーターを取得し、テーマに使用されるコンテキストを保持します。実際はこれがアクティビティです。そのため、膨らんだビューはアクティビティのテーマを使用します。

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

12
Pointer Null

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

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.Builderを使用している場合は、ビルダーに渡されるコンテキストを確認してください。お役に立てれば! :)

11
BruceHill

マニフェストにAndroid:minSdkVersion="11"が設定されていることを確認してください。これが David's の例がうまくいかなかった原因かもしれません。

また、Android:theme="@Android:style/Theme.Holo.Light"タグに<application>属性を設定し、NOT<activity>タグを設定します。

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

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

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


便利なリンク:

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

9
sebster

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

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

フラグメントのonCreateView()beforeフラグメントのルートビューを膨らませてくれます。

9
Tomask

Davidが提案した解決策を試しましたが、すべてのシナリオでは機能しませんでした:
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);
} 
7
avi

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

2
Devam03

フラグメントのレイアウトファイルで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
Niraj Niroula

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

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

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

Android:fitsSystemWindows="false"
1
Siddharth Sheth

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

注:これは、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);
}

これが何人かの人々の助けになることを願っています!

0
Jop Middelkamp