Parça için tema belirleme


117

Bir parçanın temasını oluşturmaya çalışıyorum.

Manifest'te temayı ayarlamak işe yaramıyor:

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

Önceki bloglara baktığımda, bir ContextThemeWrapper kullanmam gerekiyormuş gibi görünüyor. Kimse beni kodlanmış bir örneğe yönlendirebilir mi? Hiçbir şey bulamıyorum

Yanıtlar:


187

Manifest'te Tema ayarlamak genellikle Etkinlik için kullanılır.

Fragment için Tema ayarlamak istiyorsanız, sonraki kodu Fragmanın onCreateView () öğesine ekleyin:

@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
bu benim için çalışmıyor. Parça, hala bildirim dosyasında belirtilen temaya sahiptir.
Giorgi

1
Manifest'te, parçayı değil, etkinlik için Temayı belirtirsiniz. fragment veya fragmentActivity kullanıyor musunuz?
David

1
Benim için çalıştı. Aktivite içinde klasik Fragment ile.
David

8
@David "Bildirimde Temayı Ayarlamak Etkinlik için kullanılıyor". Bu tamamen doğru değil. Fragment'inizi çalışma zamanında eklemek için bir FragmentTransaction kullanırsanız, tema Fragmentlere de uygulanır.
sebster

4
Bu, ActionBarSherlock kitaplığından bir SherlockFragmentActivity için işe yaramıyor gibi görünüyor.
toobsco42

18

Fragment temasını Activity'den alır. Her parçaya, içinde bulunduğu Aktivitenin teması atanır.

Tema, kodunuzun aslında temanın kullanıldığı nesneler olan görünümleri oluşturduğu Fragment.onCreateView yönteminde uygulanır.

Fragment.onCreateView'da görünümleri şişiren ve tema için kullanılan Bağlamı tutan LayoutInflater parametresini alırsınız, aslında bu Activity'dir. Yani şişirilmiş görünümleriniz Activity temasını kullanır.

Temayı geçersiz kılmak için , Dokümanlar'da temayı değiştirmek için kullanılabileceğinden bahseden LayoutInflater.cloneInContext'i çağırabilirsiniz . ContextThemeWrapper'ı burada kullanabilirsiniz. Ardından, parçanın görünümlerini oluşturmak için klonlanmış şişirici kullanın.


Google docs'un belirttiği gibi: "... Verilen Bağlamla ilişkilendirilmiş yeni bir LayoutInflater nesnesi döndürür ..." - developer.android.com/reference/android/view/…
Chris

Davids kod çözümüne çok yararlı bir katkı. Teşekkürler!
muetzenflo

13

Tek bir stili uygulamak için sadece kullandım

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

içinde onCreateView()fragmanın önce parçanın kök görünümü şişirme ve bu benim için çalışıyor.


1
min api 23 forgetContext()
vigilancer

@vigilancer Min api sorununuza bir çözüm bulmak için bu yanıtı kontrol edin: stackoverflow.com/questions/36736244/…
rm8x

1
Harika çözüm. Kodu, temayı tüm alt parçaya da uygulayan onAttach (Bağlam) 'a
ekledim

Bu, bağlamın (çoğu durumda etkinlik) temasını değiştirdiği için beklenmedik sonuçlara yol açabilir. Faaliyetin gelecekteki bir şişirilmesi (örneğin, bir rotasyondan sonra) her yerde yeni temayı kullanacak
Irhala

12

Ayrıca, parça diyaloğumu etkinliğinden farklı bir temayla göstermeye çalışıyordum ve bu çözümü takip ettim . Yorumlarda bahsedilen bazı kişiler gibi, onu çalıştırmıyordum ve diyalog manifestte belirtilen temayla gösterilmeye devam etti. Sorun şu ki AlertDialog.Builder, onCreateDialogyöntemi kullanarak diyaloğu oluşturuyordum ve bu nedenle onCreateViewbağlantılı olduğum cevapta gösterilen yöntemi kullanmıyordum . Ve ben somutlaştırırken bunun yerine somutlaştırılmış olanı kullanmam gerekirken AlertDialog.Builderbağlamda geçiyordum .getActivity()ConstextThemeWrapper

İşte onCreateDialog'umun kodu:

@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;
}

Başlangıçta AlertDialog.Buildervarlığı şu şekilde somutlaştırdım:

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

ben değiştirdim:

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

Bu değişiklikten sonra parça iletişim kutusu doğru temayla gösterildi. Öyleyse, başka biri benzer bir problem yaşıyorsa ve bunu kullanıyorsa, AlertDialog.Builderkurucuya aktarılan içeriği kontrol edin. Bu yardımcı olur umarım! :)


9

Bildiriminizde android:minSdkVersion="11"belirlediğinizden emin olun . David'in örneğinin sizin için işe yaramamasının nedeni bu olabilir .

Ayrıca, set android:theme="@android:style/Theme.Holo.Light"özelliğine yönelik <application>etiketi ve DEĞİL<activity> etiketi.

Bir başka olası sorun, bir ContextThemeWrapper(). Bunun yerine getActivity().getApplicationContext()sadece yerine koymak gibi bir şey getActivity()kullanırsanız.

Normalde, Theme.Holo, MainActivity ile bağlantılı Parçalara uygulanmalıdır.

Fragment'iniz için farklı bir tema uygulamak istediğinizde bir ContextThemeWrapper kullandığınızı lütfen unutmayın . Parçalarınızı eklediğiniz MainActivity'den bir kod parçası sağlamanız yardımcı olabilir.


Bazı yararlı bağlantılar:

Parçadaki Özel ListView ana temaya bağlı değil


8

David'in işe yaradığını ancak tüm senaryolarda değil önerdiği çözümü denedim:
1. Yığına eklenen ilk parça için, onCrateView'de tanımlanan değil, ikinci parçada etkinlik teması var. bunları yığına ekleyin, parçaya uygulandı.

2. Bunların doğru görüntülendiği ikinci fragmanda aşağıdakileri yaptım, Hafızayı temizleyerek Uygulamayı kapatmaya zorladım, Uygulamayı yeniden açtım ve Aktivite fragman ile yeniden oluşturulduğunda Fragman onları yanlış değiştirdi Etkinlik, parçanın onCrateView'de ayarlananla aynı değil.

Sorunu çözmek için küçük bir değişiklik yaptım ve inflater.inflate'den gelen kapsayıcı argümanını bir null ile değiştirdim.

Şişiricinin bazı senaryolarda kapsayıcı görünümündeki bağlamı nasıl kullandığını bilmiyorum.

Not - android.support.v4.app.Fragment & android.support.v7.app.AppCompatActivity kullanıyorum.

@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);
} 

Teşekkürler, çözümün beni kurtardı. My DialogFragment'ın teması bir şekilde diğer parçalardan farklıydı. Sağlanan inflater kullandığım için EditText'imi tuhaf hale getirdi. ContextThemeWrapper ile ilgili bazı yardımlar buldum ama nasıl yapıldığını göstermediler. Çözümünüz benim için çalışıyor. Çok teşekkürler.
Phuong Dao

4

Biraz geç olduğunu biliyorum ama başka birine yardımcı olabilir çünkü bu bana yardımcı oldu.Ayrıca, parçanın onCreatView işlevinin içine aşağıdaki kod satırını eklemeyi deneyebilirsiniz

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

2

Bir java sınıfı oluşturun ve ardından onCreate yönteminde temasını değiştirmek istediğiniz düzeni kullanın ve ardından bunu manifestte normal olarak belirtin


1

Yalnızca belirli bir parça için stil uygulamak istiyorsanız, bu satırları aramadan onCreateView()veya onAttach()parçadan önce ekleyin ,

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

ve Şeffaf durum çubuğunu ayarlamak istiyorsanız , kök düzeninizin özelliğine false değerini ayarlayın fitsSystemWindows,

android:fitsSystemWindows="false"

1

Şişiriciyi aramadan önce temayı parça bağlamında belirleyerek çalışmasını sağladım.

NOT: Bu, MvvmCross ile birlikte Xamarin.Android için bir örnektir. Bunun Java programcıları için de işe yarayıp yaramayacağından% 100 emin değilim. Ama deneyebilirsin :)

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 uzantı yöntemi kodu

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

    context.SetTheme(themeStyleResId);
}

Umarım bu bazı insanlara yardımcı olur, şerefe!


1

android:theme = "@style/myTheme"Parçanın layout dosyasını kullanarak sorunu çözdüm. Örneğin bu, LinearLayoutve içeriğinin stilini değiştirir, ancak LinearLayout. Bu nedenle, tüm parçayı herhangi bir stille dekore etmek için temayı en dıştaki düzenine uygulayın.

Not: Henüz bir çözüm bulamadıysanız, deneyebilirsiniz.

           <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

Bunu onAttach'ta lolipop için deneyebilirsiniz

son Pencere penceresi = activity.getWindow (); window.setStatusBarColor (myStatusBarColor)

ve ondettach'ta varsayılana geri ayarlayın

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.