Cách đặt thuộc tính kiểu theo cách lập trình trong chế độ xem


107

Tôi nhận được một chế độ xem từ XML với mã bên dưới:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);

Tôi muốn đặt một "style" cho nút bằng cách nào tôi có thể làm điều đó trong java vì tôi muốn sử dụng một số kiểu cho mỗi nút mà tôi sẽ sử dụng.

Câu trả lời:


52

Nói chung, bạn không thể thay đổi kiểu theo chương trình; bạn có thể đặt giao diện của màn hình hoặc một phần của bố cục, hoặc từng nút trong bố cục XML của mình bằng cách sử dụng các chủ đề hoặc kiểu . Tuy nhiên, chủ đề có thể được áp dụng theo chương trình .

Ngoài ra còn có một thứ như StateListDrawablecho phép bạn xác định các ngăn kéo khác nhau cho từng trạng thái mà bạn Buttoncó thể ở, cho dù được lấy nét, chọn, nhấn, tắt, v.v.

Ví dụ: để nút của bạn thay đổi màu khi nó được nhấn, bạn có thể xác định một tệp XML có tên là res/drawable/my_button.xmlthư mục như sau:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:state_pressed="true"
    android:drawable="@drawable/btn_pressed" />
  <item
    android:state_pressed="false"
    android:drawable="@drawable/btn_normal" />
</selector>

Sau đó, bạn có thể áp dụng bộ chọn này cho một Buttonbằng cách đặt thuộc tính android:background="@drawable/my_button".


4
Vấn đề của tôi là tôi tải dữ liệu từ một dịch vụ web mô tả thông tin nút của tôi. Các nút cần có kiểu dáng khác nhau dựa trên danh mục mà chúng thuộc về. Đó là lý do tại sao tôi muốn thiết lập phong cách năng động.
Lint_

3
Chà, bạn không thể thay đổi stylethuộc tính Android , nhưng bạn có thể lập trình nền của một Buttoncái giống như bạn có thể làm với bất kỳ chế độ xem nào khác, nếu điều đó là đủ. Ngoài ra, là một Buttonkế thừa từ TextView, bạn có thể thay đổi các thuộc tính văn bản. Chỉ cần xem tài liệu API cho các mục này ... developer.android.com/reference/android/view/…
Christopher Orr

Tôi chỉ nghĩ về việc làm điều đó, ngay trước khi kiểm tra xem tôi có câu trả lời mới hay không. Cảm ơn rất nhiều.
Lint_

5
Không thể tạo kiểu cho một nút xác định kích thước văn bản, lề, v.v. và sau đó áp dụng kiểu này cho nút theo chương trình. Chắc chắn nó có thể nói nếu tôi có sáu nút muốn có cùng một phong cách?
Chịu vào

thuộc tính nào chúng ta có thể thổi phồng? chúng ta có thể tăng lợi nhuận hay không?
Android Man

49

Trước hết, bạn không cần phải sử dụng một bộ thổi phồng bố cục để tạo một Nút đơn giản. Bạn chỉ có thể sử dụng:

button = new Button(context);

Nếu bạn muốn tạo kiểu cho nút, bạn có 2 lựa chọn: cách đơn giản nhất là chỉ cần chỉ định tất cả các phần tử trong mã, giống như nhiều câu trả lời khác đề xuất:

button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);

Tùy chọn khác là xác định kiểu trong XML và áp dụng nó vào nút. Trong trường hợp chung, bạn có thể sử dụng một ContextThemeWrappercho điều này:

ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);

Để thay đổi các thuộc tính liên quan đến văn bản trên TextView (hoặc các lớp con của nó như Nút), có một phương pháp đặc biệt:

button.setTextAppearance(context, R.style.MyTextStyle);

Cái cuối cùng này không thể được sử dụng để thay đổi tất cả các thuộc tính; ví dụ để thay đổi đệm bạn cần sử dụng a ContextThemeWrapper. Nhưng đối với màu văn bản, kích thước, vv bạn có thể sử dụng setTextAppearance.


1
Chỉ tuyệt vời. ContextThemeWrapper - là thứ mà tôi đã tìm kiếm bấy lâu nay.
Ayaz Alifov

Điều này hoạt động tuyệt vời. Đã tìm kiếm giải pháp này trong một thời gian.
jasonjwwilliams

14

Có, bạn có thể sử dụng ví dụ như trong một nút

Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);

5
Điều đó sẽ đặt nền nhưng một kiểu có thể chỉ định nhiều thứ hơn là chỉ một nền. Rất nhiều Chế độ xem (bao gồm cả Nút) dường như có một hàm tạo lấy ID kiểu làm tham số. Tuy nhiên, tôi đang gặp sự cố để điều đó hoạt động với tôi - nút hiển thị dưới dạng văn bản không có đường viền hoặc bất kỳ thứ gì. Thay vào đó, những gì tôi có thể làm là tạo một bố cục chỉ có một nút trong đó (với một kiểu được chỉ định), thổi phồng bố cục đó, sau đó đặt văn bản cho nút và không.
spaaarky21

11

Bạn có thể thực hiện các thuộc tính kiểu như sau:

Button myButton = new Button(this, null,android.R.attr.buttonBarButtonStyle);

thay cho:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btn"
    style="?android:attr/buttonBarButtonStyle"

    />

7
Câu trả lời tốt khi xem xét một nút sẽ được tạo. Rất vui được biết cách thực hiện điều đó cho một nút hiện có.
Chất lượng Catalyst

Xem câu trả lời từ cesards.
Kristy Welsh

10

Nếu bạn đang sử dụng thư viện Hỗ trợ, bạn chỉ cần sử dụng

TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);

cho TextViews và Buttons. Có các lớp tương tự cho phần còn lại của Chế độ xem :-)


bạn cần sử dụng gói R nào để có được phong cách này?
htafoya

6

Đối với bất kỳ ai đang tìm kiếm câu trả lời Material, hãy xem bài đăng SO này: Các nút màu trong Android với Material Design và AppCompat

Tôi đã sử dụng kết hợp câu trả lời này để đặt màu văn bản mặc định của nút thành màu trắng cho nút của mình: https://stackoverflow.com/a/32238489/3075340

Sau đó, câu trả lời này https://stackoverflow.com/a/34355919/3075340 để đặt màu nền theo chương trình. Mã cho điều đó là:

ViewCompat.setBackgroundTintList(your_colored_button,
 ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));

your_colored_buttoncó thể chỉ là Buttonmột nút thông thường hoặc một nút AppCompat nếu bạn muốn - Tôi đã thử nghiệm đoạn mã trên với cả hai loại nút và nó hoạt động.

CHỈNH SỬA: Tôi thấy rằng các thiết bị tiền kẹo mút không hoạt động với mã trên. Xem bài đăng này về cách thêm hỗ trợ cho các thiết bị tiền kẹo mút: https://stackoverflow.com/a/30277424/3075340

Về cơ bản làm điều này:

Button b = (Button) findViewById(R.id.button);
ColorStateList c = ContextCompat.getColorStateList(mContext, R.color.your_custom_color;
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
    // appcompat button replaces tint of its drawable background
    ((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Lollipop button replaces tint of its drawable background
    // however it is not equal to d.setTintList(c)
    b.setBackgroundTintList(c);
} else {
    // this should only happen if 
    // * manually creating a Button instead of AppCompatButton
    // * LayoutInflater did not translate a Button to AppCompatButton
    d = DrawableCompat.wrap(d);
    DrawableCompat.setTintList(d, c);
    b.setBackgroundDrawable(d);
}

6

Tùy thuộc vào thuộc tính kiểu nào bạn muốn thay đổi, bạn có thể sử dụng thư viện Paris:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);

Nhiều thuộc tính như background, padding, textSize, textColor, v.v. được hỗ trợ.

Tuyên bố từ chối trách nhiệm: Tôi là tác giả của thư viện.


5

Câu trả lời của @Dayerman và @h_rules là đúng. Để đưa ra một ví dụ chi tiết với mã, Trong thư mục có thể vẽ, hãy tạo tệp xml có tên button_disabled.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">   
 <solid android:color="@color/silver"/>
<corners
   android:bottomRightRadius="20dp"
   android:bottomLeftRadius="20dp"
   android:topLeftRadius="20dp"
   android:topRightRadius="20dp"/>
</shape>

Sau đó, trong Java,

((Button) findViewById(R.id.my_button)).setEnabled(false);
((Button) findViewById(R.id.my_button)).setBackgroundResource(R.drawable.button_disabled);

Thao tác này sẽ đặt thuộc tính của nút thành vô hiệu hóa và đặt màu thành bạc.

[Màu được định nghĩa trong color.xml là:

<resources>

    <color name="silver">#C0C0C0</color>

</resources>

4
@Pacerier: câu hỏi không nói lên điều đó chút nào. Thật không rõ ràng liệu kiểu là XML hay trong java. Nó chỉ hỏi cách thiết lập kiểu theo chương trình.
Harvey

3

Trong thời gian chạy, bạn biết bạn muốn nút của mình có kiểu dáng nào. Vì vậy, trước đó, trong xml trong thư mục bố cục, bạn có thể có tất cả các nút sẵn sàng để bắt đầu với các kiểu bạn cần. Vì vậy, trong thư mục bố cục, bạn có thể có một tệp có tên: button_style_1.xml. Nội dung của tệp đó có thể giống như sau:

<?xml version="1.0" encoding="utf-8"?>
<Button
    android:id="@+id/styleOneButton"
    style="@style/FirstStyle" />

Nếu bạn đang làm việc với các phân đoạn, thì trong onCreateView, bạn tăng cường nút đó, như:

Button firstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

trong đó vùng chứa là vùng chứa ViewGroup được liên kết với phương thức onCreateView mà bạn ghi đè khi tạo phân đoạn của mình.

Cần thêm hai nút như vậy? Bạn tạo chúng như thế này:

Button secondFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
Button thirdFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

Bạn có thể tùy chỉnh các nút đó:

secondFirstStyleBtn.setText("My Second");
thirdFirstStyleBtn.setText("My Third");

Sau đó, bạn thêm các nút tùy chỉnh, cách điệu của mình vào vùng chứa bố cục mà bạn cũng đã tăng trong phương thức onCreateView:

_stylizedButtonsContainer = (LinearLayout) rootView.findViewById(R.id.stylizedButtonsContainer);

_stylizedButtonsContainer.addView(firstStyleBtn);
_stylizedButtonsContainer.addView(secondFirstStyleBtn);
_stylizedButtonsContainer.addView(thirdFirstStyleBtn);

Và đó là cách bạn có thể làm việc linh hoạt với các nút cách điệu.


0

Tôi đã tạo giao diện trợ giúp cho việc này bằng cách sử dụng mẫu chủ.

public interface StyleHolder<V extends View> {
    void applyStyle(V view);
}

Bây giờ, đối với mọi phong cách bạn muốn sử dụng thực tế, chỉ cần triển khai giao diện, ví dụ:

public class ButtonStyleHolder implements StyleHolder<Button> {

    private final Drawable background;
    private final ColorStateList textColor;
    private final int textSize;

    public ButtonStyleHolder(Context context) {
        TypedArray ta = context.obtainStyledAttributes(R.style.button, R.styleable.ButtonStyleHolder);

        Resources resources = context.getResources();

        background = ta.getDrawable(ta.getIndex(R.styleable.ButtonStyleHolder_android_background));

        textColor = ta.getColorStateList(ta.getIndex(R.styleable.ButtonStyleHolder_android_textColor));

        textSize = ta.getDimensionPixelSize(
                ta.getIndex(R.styleable.ButtonStyleHolder_android_textSize),
                resources.getDimensionPixelSize(R.dimen.standard_text_size)
        );

        // Don't forget to recycle!
        ta.recycle();
    }

    @Override
    public void applyStyle(Button btn) {
        btn.setBackground(background);
        btn.setTextColor(textColor);
        btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }
}

Khai báo một định dạng trong của bạn attrs.xml, có thể tạo kiểu cho ví dụ này là:

<declare-styleable name="ButtonStyleHolder">
    <attr name="android:background" />
    <attr name="android:textSize" />
    <attr name="android:textColor" />
</declare-styleable>

Đây là kiểu được khai báo trong styles.xml:

<style name="button">
    <item name="android:background">@drawable/button</item>
    <item name="android:textColor">@color/light_text_color</item>
    <item name="android:textSize">@dimen/standard_text_size</item>
</style>

Và cuối cùng là việc triển khai trình giữ kiểu:

Button btn = new Button(context);    
StyleHolder<Button> styleHolder = new ButtonStyleHolder(context);
styleHolder.applyStyle(btn);

Tôi thấy điều này rất hữu ích vì nó có thể dễ dàng được sử dụng lại và giữ cho mã sạch sẽ và dài dòng, tôi khuyên bạn chỉ nên sử dụng biến này làm biến cục bộ để chúng tôi có thể cho phép trình thu gom rác thực hiện công việc của mình sau khi chúng tôi hoàn tất việc thiết lập tất cả các kiểu .


-1

Tôi phải đối mặt với cùng một vấn đề gần đây. đây là cách tôi giải quyết nó.

<?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">

    <!-- This is the special two colors background START , after this LinearLayout, you can add all view that have it for main background-->
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:weightSum="2"

    android:background="#FFFFFF"
    android:orientation="horizontal"
    >

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#0000FF" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#F000F0" />
    </LinearLayout>
    <!-- This is the special two colors background END-->

   <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:text="This Text is centered with a special backgound,
    You can add as much elements as you want as child of this RelativeLayout"
    android:textColor="#FFFFFF"
    android:textSize="20sp" />
</RelativeLayout>
  • Tôi đã sử dụng LinearLayout với android: weightSum = "2"
  • Tôi đã cấp cho hai phần tử con android: layout_weight = "1" (Tôi đã cấp cho mỗi phần tử 50% không gian mẹ (chiều rộng và chiều cao))
  • Và cuối cùng, tôi đã cho hai phần tử con có màu nền khác nhau để có hiệu ứng cuối cùng.

Cảm ơn !

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.