2011-12-03 19 views
34

Nếu bạn muốn đặt kiểu của Nút mà bạn tạo từ mã, bạn phải làm một cái gì đó như thế này;Tại sao quá phức tạp để đặt kiểu từ mã trong Android

Button btn = new Button (mActivity, null, R.attr.someattribute); 

trong attrs.xml, bạn thiết lập một tham chiếu

<attr name="someStyleRef" format="reference"/> 

Trong styles.xml, bạn xác định một chủ đề

<resources> 
    <style name="Theme.SomeTheme" parent="android:style/Theme.Black"> 
    <item name="someStyleRef">@style/someStyle</item> 
    </style> 
</resources> 

Đó lates trong styles.xml được xác định như đối với ví dụ

<style name="someStyle"> 
     <item name="android:layout_width">2px</item> 
     <item name="android:layout_height">fill_parent</item> 
     <item name="android:background">@drawable/actionbar_compat_separator</item> 
</style> 

Công trình này, và đây là, theo sự hiểu biết của tôi, cách để thiết lập một phong cách trên một View từ mã trong Android. Điều này có vẻ quá phức tạp. Trình tạo hàm thứ ba của nút Argument có thể dễ dàng chấp nhận một kiểu ID R.style.XXX

Bất cứ ai có thể giải thích tại sao cần thêm độ phức tạp này?

+1

Cảm ơn bạn đã giải thích cách hoạt động trong tài nguyên hệ thống của Android, nó đã giúp tôi trả lời câu hỏi của riêng mình (http://stackoverflow.com/questions/11023335/how-to-set-android-button-background -color/11024343 # 11024343) – Qwertie

Trả lời

64

Nó có liên quan đến các mẫu được khuyến khích trong Android xung quanh bằng cách sử dụng Chế độ xem. Đây không phải là phương pháp dự định cho những gì nó trông giống như bạn đang cố gắng làm. Trước tiên, tôi sẽ giải thích cơ chế này là gì và sau đó đề xuất phương pháp tiếp cận cho ứng dụng của bạn.

Đối số thứ ba cho Xem hàm tạo attr thường được sử dụng khi triển khai Xem lớp con và như bạn đã hiển thị, cho phép bạn chỉ định thuộc tính chủ đề để sử dụng làm tham chiếu đến kiểu mặc định của Chế độ xem. Nếu bạn đã có một loại đặc biệt nút gọi AwesomeButton bạn có thể thực hiện constructor của nó như thế này:

public class AwesomeButton extends Button { 
    public AwesomeButton(Context context) { 
     this(context, null); 
    } 

    public AwesomeButton(Context context, AttributeSet attrs) { 
     this(context, attrs, R.attr.awesomeButtonStyle); 
    } 

    public AwesomeButton(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr) { 
     final TypedArray a = context.obtainStyledAttributes(attrs, 
       R.styleable.AwesomeButton, defStyleAttr, 0); 
     // Read AwesomeButton-specific style attributes from a 
     a.recycle(); 
    } 

    // More code 
} 

Khi Android của LayoutInflater bung xem nó sử dụng các nhà xây dựng 2-tranh cãi với những lập luận (Context, AttributeSet). Hằng số R.attr được chuyển qua phiên bản 3 đối số và sau đó xuống đến hàm tạo 3-đối số của Button trong cuộc gọi super. Điều này có nghĩa là Button sẽ đọc thông tin kiểu dáng mặc định cho những thứ mà nó đóng gói theo kiểu mặc định của AwesomeButton như được chỉ định trong chủ đề của bạn. Một số Chế độ xem trong Android khác với chế độ siêu lớp của chúng chỉ theo kiểu mặc định mà chúng sử dụng. (Button thực sự là một trong số này.)

Bạn chỉ định android:layout_widthandroid:layout_height theo phong cách của mình nhưng điều này có thể có vấn đề. LayoutParams (bất kỳ thuộc tính nào bắt đầu bằng layout_) đều dành riêng cho chế độ xem gốc chứ không phải chế độ xem mà chúng xuất hiện. Đây là lý do tại sao bạn luôn vượt qua chế độ xem cha mẹ dự định làm thông số thứ hai cho số LayoutInflater#inflate - nó cho biết người thổi phồng lớp nào chịu trách nhiệm giải thích LayoutParams. Nếu bạn bỏ qua điều này, bạn sẽ thường thấy rằng LayoutParams của bạn không hoạt động như bạn mong đợi và thường bị bỏ qua hoàn toàn. Theo quy ước, chúng tôi không đặt LayoutParams theo kiểu mặc dù trong một số trường hợp đặc biệt, loại công việc đó.

Dường như bạn đang cố sử dụng kiểu như một loại mẫu. Có lý do nào để không sử dụng tài nguyên bố cục cho điều này và chỉ định kiểu dáng ở đó không?

final LayoutInflater inflater = LayoutInflater.from(mActivity); 
Button btn = (Button) inflater.inflate(R.layout.styled_button, parentView, false); 

res/layout/styled_button.xml:

<Button android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:background="@drawable/my_button_background" 
     [...] /> 
+0

Đây là câu trả lời rất hay và mã của tôi bây giờ đơn giản hơn nhiều. Tôi đã không thực sự cần phải đi "tất cả các cách" và tạo ra một chủ đề mới. Tôi đã kết thúc việc giữ Android của mình: layout_height = "@ dimen/actionbar_compat_height". Một tùy chọn khác có thể đã được tạo ra khác nhau styled_button.xml cho bố trí-xlarge vv Cảm ơn bạn đã dành thời gian. Bây giờ tôi hiểu rồi. –

+0

Tuyệt vời, vui vì nó đã giúp mọi thứ rõ ràng cho bạn. – adamp

+0

Chà. Tôi đã thích câu trả lời này rất nhiều Tôi đã upvoted này và khác từ cùng một người dùng :-) – SJuan76

Các vấn đề liên quan