Đặt chủ đề cho một mảnh


117

Tôi đang cố gắng thiết lập chủ đề cho một đoạn.

Đặt chủ đề trong tệp kê khai không hoạt động:

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

Từ việc xem các blog trước đó, có vẻ như tôi phải sử dụng ContextThemeWrapper. Bất cứ ai có thể giới thiệu tôi đến một ví dụ mã hóa? Tôi không thể tìm thấy bất cứ điều gì.

Câu trả lời:


187

Cài đặt Theme trong tệp kê khai thường được sử dụng cho Activity.

Nếu bạn muốn đặt Theme cho Fragment, hãy thêm mã tiếp theo vào onCreateView () của Fragment:

@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
Điều này không làm việc cho tôi. Đoạn này vẫn có cùng một chủ đề được chỉ định trong tệp kê khai.
Giorgi

1
Trong tệp kê khai, bạn chỉ định Chủ đề cho hoạt động, không phải là đoạn. bạn đang sử dụng đoạn hoặc đoạnActivity?
David

1
Đã làm cho tôi. Với mảnh vỡ cổ điển trong Hoạt động.
David

8
@David "Cài đặt chủ đề trong tệp kê khai được sử dụng cho Hoạt động". Điều này không hoàn toàn đúng. Nếu bạn sử dụng FragmentTransaction để thêm Fragment của mình khi chạy, chủ đề đó cũng được áp dụng cho Fragment.
sebster

4
Điều này dường như không hoạt động đối với SherlockFragmentActivity từ thư viện ActionBarSherlock.
toobsco42

18

Fragment lấy chủ đề từ Hoạt động của nó. Mỗi phân đoạn được gán chủ đề của Hoạt động mà nó tồn tại.

Chủ đề được áp dụng trong phương thức Fragment.onCreateView, nơi mã của bạn tạo ra các khung nhìn, thực sự là các đối tượng nơi chủ đề được sử dụng.

Trong Fragment.onCreateView, bạn nhận được tham số LayoutInflater, làm tăng các khung nhìn và nó giữ Bối cảnh được sử dụng cho chủ đề, thực sự đây là Activity. Vì vậy, lượt xem tăng cao của bạn sử dụng chủ đề Hoạt động.

Để ghi đè chủ đề, bạn có thể gọi LayoutInflater.cloneInContext , trong đó đề cập đến Docs rằng nó có thể được sử dụng để thay đổi chủ đề. Bạn có thể sử dụng ContextThemeWrapper tại đây. Sau đó, sử dụng dòng nhân bản vô tính để tạo ra các khung nhìn của mảnh.


Như các tài liệu của google tuyên bố: "... Trả về một thương hiệu sắp xếp đối tượng LayoutInflater mới được liên kết với Bối cảnh đã cho ..." - developer.android.com/reference/android/view/âu
Chris

bổ sung rất hữu ích cho giải pháp mã Davids. Cảm ơn!
muetzenflo

13

Để áp dụng một kiểu duy nhất tôi đã sử dụng

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

trong onCreateView()đoạn trước khi thổi phồng gốc của đoạn và nó hoạt động với tôi.


1
tối thiểu 23 chogetContext()
vigilancer

@vigilancer Kiểm tra câu trả lời này để khắc phục sự cố api tối thiểu của bạn: stackoverflow.com/questions/36736244/ory
rm8x

1
Giải pháp tuyệt vời. Tôi đã thêm mã trong onAttach (Ngữ cảnh) cũng áp dụng chủ đề trên tất cả các đoạn con
crysxd

Điều này có thể có hậu quả không mong muốn vì nó sửa đổi chủ đề (hoạt động trong hầu hết các trường hợp) bối cảnh. Một lạm phát trong tương lai (ví dụ: sau một vòng quay) của Hoạt động sẽ sử dụng chủ đề mới ở mọi nơi
Irhala

12

Tôi cũng đã cố gắng để hộp thoại phân đoạn của mình hiển thị với chủ đề khác với hoạt động của nó và theo giải pháp này . Giống như một số người được đề cập trong các bình luận, tôi đã không làm cho nó hoạt động và hộp thoại tiếp tục hiển thị với chủ đề được chỉ định trong tệp kê khai. Vấn đề bật ra được rằng tôi đã xây dựng thoại sử dụng AlertDialog.Buildertrong onCreateDialogphương pháp và do đó đã không được tận dụng các onCreateViewphương pháp như trong các câu trả lời mà tôi liên kết với. Và khi tôi đang khởi tạo thì AlertDialog.Buildertôi đã chuyển qua ngữ cảnh getActivity()khi tôi nên sử dụng tính năng khởi tạo ConstextThemeWrapperthay thế.

Đây là mã cho onCreateDialog của tôi:

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

Ban đầu tôi đã AlertDialog.Builderđược khởi tạo như sau:

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

mà tôi đã đổi thành:

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

Sau khi thay đổi, hộp thoại đoạn được hiển thị với chủ đề chính xác. Vì vậy, nếu bất cứ ai khác đang gặp vấn đề tương tự và đang sử dụng AlertDialog.Builderthì hãy kiểm tra bối cảnh được chuyển đến trình xây dựng. Hi vọng điêu nay co ich! :)


9

Hãy chắc chắn rằng bạn đã android:minSdkVersion="11"thiết lập trong bảng kê khai của bạn. Đây có thể là nguyên nhân tại sao ví dụ của David không làm việc cho bạn.

Ngoài ra, thiết lập các android:theme="@android:style/Theme.Holo.Light"thuộc tính cho <application>thẻ và KHÔNG các <activity>thẻ.

Một vấn đề khác có thể xảy ra là cách bạn có được Bối cảnh khi sử dụng a ContextThemeWrapper(). Nếu bạn sử dụng một cái gì đó như getActivity().getApplicationContext()chỉ cần thay thế nó getActivity()thay thế.

Thông thường, Theme.Holo nên áp dụng cho các Đoạn được liên kết với MainActivity.

Xin lưu ý rằng bạn sử dụng ContextThemeWrapper khi bạn muốn áp dụng một chủ đề khác cho Mảnh vỡ của mình. Nó có thể hữu ích nếu bạn cung cấp đoạn mã, từ MainActivity của bạn, nơi bạn thêm các Đoạn của mình.


Một số liên kết hữu ích:

ListView tùy chỉnh trong Fragment không tuân thủ chủ đề gốc


8

Tôi đã thử giải pháp mà David đề xuất rằng nó đã hoạt động nhưng không phải trong tất cả các kịch bản:
1. cho đoạn đầu tiên được thêm vào ngăn xếp có chủ đề của hoạt động và không phải là phần được xác định trong onCrateView, nhưng trên đoạn thứ hai mà tôi thêm vào ngăn xếp chính xác chúng đã được áp dụng trên đoạn.

2. Trên đoạn thứ hai mà chúng được hiển thị chính xác, tôi đã làm như sau, tôi buộc phải đóng Ứng dụng bằng cách dọn sạch bộ nhớ, mở lại Ứng dụng và khi Hoạt động được tạo lại bằng đoạn Đoạn đó đã thay đổi chúng sai Hoạt động và không giống với Hoạt động được đặt trong onCrateView của đoạn.

Để khắc phục sự cố, tôi đã thực hiện một thay đổi nhỏ và thay thế đối số vùng chứa từ Inflater.inflate bằng null.

Tôi không biết cách mà người sử dụng sử dụng trong một số tình huống bối cảnh từ chế độ xem container.

Lưu ý - tôi đang sử dụng 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);
} 

Cảm ơn, giải pháp của bạn cứu tôi. Chủ đề DialogFragment của tôi bằng cách nào đó khác với các đoạn khác. Nó làm cho EditText của tôi trở nên kỳ lạ bởi vì tôi đã sử dụng được cung cấp. Tôi đã tìm thấy một số trợ giúp liên quan đến ContextThemeWrapper nhưng họ đã không chỉ ra cách thức thực hiện. Giải pháp của bạn làm việc cho tôi. Cảm ơn nhiều.
Phương Dao

4

Tôi biết hơi muộn nhưng nó có thể giúp người khác vì điều này đã giúp tôi. Bạn cũng có thể thử thêm dòng mã bên dưới bên trong hàm onCreatView của đoạn

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

2

Tạo một lớp java và sau đó sử dụng bố cục mà bạn muốn thay đổi chủ đề trong phương thức onCreate. Sau đó, hãy đề cập đến nó trong tệp kê khai như bình thường


1

Nếu bạn chỉ muốn áp dụng kiểu cho đoạn cụ thể thì chỉ cần thêm dòng này trước khi gọi onCreateView()hoặc onAttach()của đoạn,

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

và Nếu bạn muốn đặt thanh trạng thái trong suốt thì đặt false thành fitsSystemWindowsthuộc tính của bố cục gốc của bạn,

android:fitsSystemWindows="false"

1

Tôi đã làm cho nó hoạt động bằng cách đặt chủ đề trên bối cảnh phân đoạn trước khi gọi bộ lọc.

LƯU Ý: Đây là một ví dụ cho Xamarin.Android kết hợp với MvvmCross. Tôi không chắc chắn 100% nếu điều này cũng sẽ làm việc cho các lập trình viên Java. Nhưng bạn có thể thử :)

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

Mã phương thức mở rộng 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);
}

Tôi hy vọng điều này sẽ giúp một số người ra ngoài, chúc mừng!


1

Tôi đã giải quyết vấn đề bằng cách sử dụng android:theme = "@style/myTheme"tệp bố cục của đoạn. Ví dụ, điều này thay đổi phong cách của LinearLayoutnội dung và nội dung nhưng không có bất kỳ điều gì bên ngoài LinearLayout. Vì vậy, để trang trí toàn bộ đoạn với bất kỳ phong cách nào, hãy áp dụng chủ đề cho bố cục bên ngoài nhất của nó.

Lưu ý: Chỉ trong trường hợp nếu bạn chưa tìm thấy giải pháp, bạn có thể dùng thử.

           <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

bạn có thể thử cái này cho kẹo mút trong onAttach

cửa sổ cuối cùng cửa sổ = Activity.getWindow (); window.setStatusBarColor (myStatusBarColor)

và đặt nó trở lại mặc định trong ondettach

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.