Cách truy xuất các thuộc tính kiểu theo cách lập trình từ styles.xml


81

Hiện tại, tôi đang sử dụng WebView hoặc TextView để hiển thị một số dữ liệu động đến từ dịch vụ web trong một trong các ứng dụng của tôi. Nếu dữ liệu chứa văn bản thuần túy, nó sử dụng TextView và áp dụng kiểu từ styles.xml. Nếu dữ liệu chứa HTML (chủ yếu là văn bản và hình ảnh), nó sẽ sử dụng WebView.

Tuy nhiên, WebView này chưa được phân loại. Vì vậy, nó trông rất khác so với TextView thông thường. Tôi đã đọc rằng có thể tạo kiểu văn bản trong WebView chỉ bằng cách chèn một số HTML trực tiếp vào dữ liệu. Điều này nghe có vẻ dễ dàng, nhưng tôi muốn sử dụng dữ liệu từ Styles.xml của mình làm giá trị bắt buộc trong HTML này, vì vậy tôi sẽ không cần phải thay đổi màu vân vân trên hai vị trí nếu tôi thay đổi kiểu của mình.

Vì vậy, làm thế nào tôi có thể làm điều này? Tôi đã thực hiện một số tìm kiếm rộng rãi nhưng tôi không tìm thấy cách nào thực sự truy xuất các thuộc tính kiểu khác nhau từ styles.xml của bạn. Tôi có thiếu thứ gì đó ở đây hay thực sự không thể truy xuất những giá trị này?

Kiểu tôi đang cố lấy dữ liệu là như sau:

<style name="font4">
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">#E3691B</item>
    <item name="android:paddingLeft">5dp</item>
    <item name="android:paddingRight">10dp</item>
    <item name="android:layout_marginTop">10dp</item>
    <item name="android:textStyle">bold</item>
</style>

Tôi chủ yếu quan tâm đến textSize và textColor.


Tại sao bạn không phân tích cú pháp XML (ví dụ: trình phân tích cú pháp SAX của Android)?
m0skit0 19/12/12

Câu trả lời:


174

Có thể truy xuất các kiểu tùy chỉnh từ styles.xmllập trình.

Xác định một số kiểu tùy ý trong styles.xml:

<style name="MyCustomStyle">
    <item name="android:textColor">#efefef</item>
    <item name="android:background">#ffffff</item>
    <item name="android:text">This is my text</item>
</style>

Bây giờ, truy xuất các kiểu như thế này

// The attributes you want retrieved
int[] attrs = {android.R.attr.textColor, android.R.attr.background, android.R.attr.text};

// Parse MyCustomStyle, using Context.obtainStyledAttributes()
TypedArray ta = obtainStyledAttributes(R.style.MyCustomStyle, attrs);

// Fetch the text from your style like this.     
String text = ta.getString(2);

// Fetching the colors defined in your style
int textColor = ta.getColor(0, Color.BLACK);
int backgroundColor = ta.getColor(1, Color.BLACK);

// Do some logging to see if we have retrieved correct values
Log.i("Retrieved text:", text);
Log.i("Retrieved textColor as hex:", Integer.toHexString(textColor));
Log.i("Retrieved background as hex:", Integer.toHexString(backgroundColor));

// OH, and don't forget to recycle the TypedArray
ta.recycle()

Bạn làm việc tuyệt vời. Sau khi được nói (và đọc nó rất nhiều) rằng nó không thể được thực hiện, bạn đã hoàn toàn thể hiện nó có thể. Chỉ cần dùng thử và tôi đã có thể lấy màu chữ theo phong cách của mình. Vẫn chưa thể có được kích thước văn bản nhưng tôi sẽ tìm ra nó. 100 điểm sẽ đến với bạn ngay khi tôi có thể gửi tiền thưởng (18 giờ kể từ bây giờ). Cảm ơn rất nhiều!
Sander van't Veer 19/12/12

4
là nó cũng có thể thay đổi các giá trị được xác định trong kiểu tại thời gian chạy?
ekjyot

Điều gì sẽ xảy ra nếu tôi muốn thay đổi màu của các thuộc tính được truy xuất? Giống như thay đổi màu nền hoặc màu văn bản động trong mã này?
MSIslam

2
Tôi gặp sự cố với dòng này: 'TypedArray ta = getStyledAttributes (R.style.MyCustomStyle, attrs);', Android studio cho tôi biết rằng nó mong đợi tài nguyên thuộc loại có thể định kiểu và tôi không thể thấy bất kỳ cách nào để chặn các chú thích trong thư viện hỗ trợ. Tôi giả sử rằng getStyledAttributes có chú thích @ResStyleable đang ngăn tôi chuyển một kiểu dưới dạng int qua. Có ý kiến ​​gì không?
Ben Pearson

1
@BenPearson - Tôi đã gặp sự cố tương tự khi bạn cố gắng lấy thuộc tính textSize. Câu trả lời của PrivatMamtora hoạt động và phải là câu trả lời được chấp nhận.
thecoolmacdude

52

Câu trả lời mà @Ole đưa ra dường như bị phá vỡ khi sử dụng một số thuộc tính nhất định, chẳng hạn như shadowColor, shadowDx, shadowDy, shadowRadius (đây chỉ là một số ít tôi tìm thấy, có thể có nhiều hơn)

Tôi không biết tại sao vấn đề này lại xảy ra, điều mà tôi đang hỏi ở đây , nhưng kiểu mã @AntoineMarques dường như giải quyết được vấn đề.

Để làm cho điều này hoạt động với bất kỳ thuộc tính nào, nó sẽ giống như thế này


Đầu tiên, xác định một stylable để chứa các id tài nguyên như vậy

attrs.xml

<resources>     
    <declare-styleable name="MyStyle" >
        <attr name="android:textColor" />
        <attr name="android:background" />
        <attr name="android:text" />
    </declare-styleable>
</resources>

Sau đó, trong mã, bạn sẽ làm điều này để lấy văn bản.

TypedArray ta = obtainStyledAttributes(R.style.MyCustomStyle, R.styleable.MyStyle);  
String text = ta.getString(R.styleable.MyStyle_android_text);

Ưu điểm của việc sử dụng phương pháp này là bạn đang truy xuất giá trị theo tên chứ không phải chỉ mục.


3
Đây phải là câu trả lời được chấp nhận vì câu trả lời của Ole đã tạo ra cảnh báo "tài nguyên dự kiến ​​thuộc loại có thể định kiểu" cho tôi.
thecoolmacdude

1
Hoạt động đối với tôi, nhưng với Android Studio, tôi cần thêm tiền tố đó bằng a @SuppressWarnings("ResourceType").
trước

2
Câu trả lời này nên được chấp nhận. Nó phù hợp với tất cả các thuộc tính của tôi, và cái được bình chọn nhiều nhất đã làm lãng phí thời gian của tôi.
jerry

1
Cảm ơn chú cá heo dũng mãnh vì giải pháp của bạn. Câu trả lời được chấp nhận đã tạo ra vấn đề cho tôi đối với các thuộc tính như nền (khi sử dụng có thể vẽ) và kích thước văn bản. Giải pháp này không chỉ hoạt động cho tất cả các thuộc tính tôi cần mà còn cung cấp mã rõ ràng hơn.
Marius P.

2
R.style.MyCustomStyle được cho là gì?
janosch

1

Câu trả lời từ Ole và PrivatMamtora không phù hợp với tôi, nhưng điều này đã làm được.

Giả sử tôi muốn đọc kiểu lập trình này:

<style name="Footnote">
    <item name="android:fontFamily">@font/some_font</item>
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">@color/black</item>
</style>

Tôi có thể làm như thế này:

fun getTextColorSizeAndFontFromStyle(
    context: Context, 
    textAppearanceResource: Int // Can be any style in styles.xml like R.style.Footnote
) {
    val typedArray = context.obtainStyledAttributes(
        textAppearanceResource,
        R.styleable.TextAppearance // These are added to your project automatically.
    )
    val textColor = typedArray.getColorStateList(
        R.styleable.TextAppearance_android_textColor
    )
    val textSize = typedArray.getDimensionPixelSize(
        R.styleable.TextAppearance_android_textSize
    )

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val typeface = typedArray.getFont(R.styleable.TextAppearance_android_fontFamily)

        // Do something with the typeface...

    } else {
        val fontFamily = typedArray.getString(R.styleable.TextAppearance_fontFamily)
            ?: when (typedArray.getInt(R.styleable.TextAppearance_android_typeface, 0)) {
                1 -> "sans"
                2 -> "serif"
                3 -> "monospace"
                else -> null
            }

        // Do something with the fontFamily...
    }
    typedArray.recycle()
}

Tôi lấy một số cảm hứng từ lớp TextAppearanceSpan của Android, bạn có thể tìm thấy nó ở đây: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/style/TextAppearanceSpan.java


-3

Nếu giải pháp được chấp nhận không hoạt động, hãy thử đổi tên attr.xml thành attrs.xml (phù hợp với tôi)

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.