กำหนดรูปแบบสำหรับ TextView โดยทางโปรแกรม


249

ฉันพยายามที่จะใช้ตัวTextViewสร้างที่มีสไตล์เช่นนี้:

TextView myText = new TextView(MyActivity.this, null, R.style.my_style);

อย่างไรก็ตามเมื่อฉันทำเช่นนี้มุมมองข้อความดูเหมือนจะไม่ใช้สไตล์ (ฉันตรวจสอบสไตล์โดยการตั้งค่าบนวัตถุคงที่)

ฉันได้ลองใช้myText.setTextAppearance(MyActivity.this, R.style.my_style)แต่ก็ใช้ไม่ได้

คำตอบ:


318

ฉันไม่เชื่อว่าคุณสามารถกำหนดรูปแบบได้ ในการหลีกเลี่ยงปัญหานี้คุณสามารถสร้างไฟล์เทมเพลต xml ของเท็มเพลตพร้อมกับสไตล์ที่กำหนดตัวอย่างเช่นใน res / layout create tvtemplate.xml เช่นเดียวกับเนื้อหาต่อไปนี้:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="This is a template"
        style="@style/my_style" />

จากนั้นขยายสิ่งนี้เพื่อยกตัวอย่าง TextView ใหม่ของคุณ:

TextView myText = (TextView)getLayoutInflater().inflate(R.layout.tvtemplate, null);

หวังว่านี่จะช่วยได้


1
เมื่อสิ่งนี้ชนะเหนือคำตอบของ Dandre Allison คือไม่ต้องใช้ API v11
Martin Capodici

2
อาจใช้ได้ แต่ก็ไม่สมเหตุสมผล จะสามารถตั้งค่าด้วยไฟล์ xml ได้อย่างไร? หากไม่ได้เขียนโปรแกรม มีเหตุผลที่จะไม่ใช้ไฟล์ xml หนึ่งในนั้นคือฉันใช้ในการเขียนรหัสเพื่อสร้าง UI ดังนั้นฉันไม่ต้องการเรียนรู้วิธีการใหม่ในการทำเนื่องจากหน่วยความจำของฉันมี จำกัด และฉันต้องการเก็บห้องไว้ สิ่งอื่น ๆ.
Iharob Al Asimi

@IharobAlAsimi ถูกต้องทุกสิ่งสามารถเขียนโปรแกรมได้และ LayoutInflater รู้ทุกอย่างเกี่ยวกับการเปลี่ยน XML ให้เป็นวัตถุ น่าเศร้าที่สิ่งต่าง ๆ มากมายถูกซ่อนอยู่ภายใต้ API ส่วนบุคคลและวิธีเดียวในการสร้างวัตถุบางอย่างคือการจัดหา AttributeSet ให้กับตัวสร้าง
Miha_x64

ต่างจากคำตอบอื่น ๆ ทั้งหมดนี้ใช้งานได้จริงกับนักปั่นดังนั้นดาวสีทองสำหรับคุณ
Rowan Berry

121

คุณสามารถสร้างสไตล์ทั่วไปและนำกลับมาใช้ใหม่ใน textviews หลาย ๆ แบบตามด้านล่าง:

textView.setTextAppearance(this, R.style.MyTextStyle);

แก้ไข: นี่หมายถึงบริบท


50
คำตอบของคุณจะทำงานได้ตราบใดที่คุณทำอย่างนั้นก็คือการใช้ "สไตล์" ของข้อความ ไม่ทำงานหากคุณพยายามทำสิ่งอื่น ๆ กับ TextView เช่นเพิ่มการขยายหรือระยะขอบ ดังนั้นฉันไม่ได้บอกว่าคุณผิด แต่คำตอบของคุณมี จำกัด การขยายมุมมองที่รันไทม์เป็นวิธีเดียวที่จะใช้สไตล์ที่ครอบคลุม
Bill Mote

1
โซลูชันทั้งสองของการใช้เท็มเพลตที่สูงเกินจริงและการใช้ setTextAppearance นั้นสมเหตุสมผล ในการแก้ไขปัญหาช่องว่างภายใน / ระยะขอบสำหรับโซลูชันที่ 2 คุณสามารถโทร textView.setLayoutParams (layoutParams)
AlanKley

วิธีนี้เลิกใช้แล้วใน API ระดับ 23 ใช้ setTextAppearance (int) แทนใน API 23+
Sergii

ตรวจสอบให้แน่ใจว่าเวอร์ชันนี้เป็นอย่างน้อย API 23 (M)
Br0thazS0ul

4
ใช้วิธีการจากไลบรารีสนับสนุนTextViewCompat.setTextAppearance
Rubin Yoo

97

คุณสามารถส่งContextThemeWrapperไปที่นวกรรมิกเช่นนี้:

TextView myText = new TextView(new ContextThemeWrapper(MyActivity.this, R.style.my_style));

1
สิ่งที่ดี! วิธีเดียวที่ฉันสามารถตั้งค่ารูปแบบโดยทางโปรแกรมในขณะที่สนับสนุน API 8
tbraun

ด้วยเหตุผลบางอย่างมันไม่ส่งผลต่อสไตล์ของปุ่มของฉัน <style name="TabButton"><item name="android:background">@drawable/tabbar_button_bkgnd</item>...</style>ฉันได้กำหนดสไตล์ของผมที่ชอบ: จากนั้นฉันก็เรียกมันด้วยสิ่งก่อสร้าง: new Button(new ContextThemeWrapper(context, R.style.TabButton));. แต่ปุ่มจะเพิกเฉยต่อการตั้งค่าของฉัน ฉันกำลังทำอะไรผิดที่นี่?
Aleks N.

@ AlaksiejN คุณควรสืบทอดจาก Widget.Button สไตล์เช่นนี้parent="@android:style/Widget.Button"
maxcanna

@ maxcanna ด้วยเหตุผลบางประการการเพิ่มparentไม่ได้เปลี่ยนสักเล็กน้อย ดังนั้นฉันจึงไปข้างหน้ากับinflateวิธีแก้ปัญหา
Aleks N.

11
@AliakseiN คุณจำเป็นต้องใช้ 3 new Button(new ContextThemeWrapper(context, R.style.TabButton), null, 0)หาเรื่องคอนสตรัคเช่น มิฉะนั้นจะใช้รูปแบบปุ่มเริ่มต้นและสไตล์นี้จะแทนที่ลักษณะปุ่มที่คุณได้ผสานเข้ากับธีมผ่าน ContextThemeWrapper
Newtonx

17

คุณสามารถตั้งค่าสไตล์ในตัวสร้าง (แต่สไตล์ไม่สามารถเปลี่ยน / ตั้งค่าแบบไดนามิก)

View(Context, AttributeSet, int)( intคือแอตทริบิวต์ในชุดรูปแบบปัจจุบันที่มีการอ้างอิงถึงสไตล์)

คำตอบจาก Romain Guy

การอ้างอิง


คำตอบของคุณทำให้เข้าใจผิด - คุณลองอ่านหัวข้อนี้จนจบหรือไม่?
Andr

3
มันทำให้เข้าใจผิดได้อย่างไร? คำตอบที่ยอมรับนั้นทำให้เข้าใจผิดเพราะ Romain Guy บอกอย่างชัดเจนว่าคุณสามารถ "กำหนด" สไตล์การเขียนโปรแกรมได้ ไม่มีสิ่งอำนวยความสะดวกในการเปลี่ยนแปลงแบบไดนามิก เธรดนี้ดูเหมือนจะไม่คิดว่าเป็นอย่างนั้น
Dandre Allison

1
ระวังการโทรนี้ต้องใช้ระดับ API 11
Martin Capodici

1
@PaulVerest ไม่ใช่คำพูด
Dandre Allison

6
int สุดท้ายไม่ใช่ทรัพยากรสไตล์ มันคือ "แอตทริบิวต์ในชุดรูปแบบปัจจุบันที่มีการอ้างอิงถึงทรัพยากรสไตล์ที่ให้ค่าเริ่มต้นสำหรับมุมมอง"
rve

11

พารามิเตอร์ int defStyleAttrไม่ได้ระบุสไตล์ จากเอกสาร Android:

defStyleAttr - แอททริบิวในชุดรูปแบบปัจจุบันที่มีการอ้างอิงถึงทรัพยากรสไตล์ที่ให้ค่าเริ่มต้นสำหรับมุมมอง สามารถเป็น 0 เพื่อไม่หาค่าเริ่มต้น

ในการตั้งค่าสไตล์ในตัวสร้างมุมมองเรามีวิธีแก้ไขที่เป็นไปได้ 2 แบบ:

  1. ด้วยการใช้ ContextThemeWrapper:

    ContextThemeWrapper wrappedContext = new ContextThemeWrapper(yourContext, R.style.your_style);
    TextView textView = new TextView(wrappedContext, null, 0);
  2. ด้วยตัวสร้างสี่อาร์กิวเมนต์ (เริ่มต้นจาก LOLLIPOP):

    TextView textView = new TextView(yourContext, null, 0, R.style.your_style);

สิ่งสำคัญสำหรับทั้งสองวิธี - defStyleAttrพารามิเตอร์ควรเป็น 0 เพื่อใช้สไตล์ของเรากับมุมมอง


5

ไม่รองรับสไตล์ที่เปลี่ยนแปลงแบบไดนามิก (ยัง) คุณต้องตั้งค่าสไตล์ก่อนที่จะสร้างมุมมองผ่าน XML


20
ซึ่งเกิดขึ้นเป็นสิ่งเดียวกันจริง ๆ แล้ว
njzk2

@ njzk2 ขอบคุณ ... เห็นได้ชัดว่าไม่ได้คิดเกี่ยวกับความคิดเห็นของเขาก่อนโพสต์ ไม่มีวิธีในการตั้งค่ารูปแบบโดยทางโปรแกรมก่อนที่จะสร้าง UI ดังนั้นรหัสเดียวกันนี้จะถูกใช้เพื่อเปลี่ยนหรือตั้งค่าสไตล์โดยทางโปรแกรม
Chris Cashwell

3

คำตอบที่ได้รับการยอมรับเป็นทางออกที่ดีสำหรับฉัน สิ่งเดียวที่จะเพิ่มเป็นเรื่องเกี่ยวกับinflate()วิธีการ

ในคำตอบที่ยอมรับandroid:layout_*พารามิเตอร์ทั้งหมดจะไม่ถูกนำไปใช้

เหตุผลก็คือวิธีการที่จะปรับมันไม่มีสาเหตุก็ผ่านไปเป็นnullViewGroup parent

คุณสามารถใช้สิ่งนี้:

View view = inflater.inflate(R.layout.view, parent, false);

และparentเป็นจากที่คุณชอบที่จะปรับViewGroupandroid:layout_*

ในกรณีนี้คุณสมบัติที่เกี่ยวข้องทั้งหมดจะถูกตั้งค่า

หวังว่ามันจะมีประโยชน์สำหรับใครบางคน


2

เมื่อใช้มุมมองที่กำหนดเองที่อาจใช้การสืบทอดสไตล์ (หรือแอตทริบิวต์สไตล์เหตุการณ์) คุณต้องแก้ไขตัวสร้างที่สองเพื่อไม่ให้สูญเสียสไตล์ สิ่งนี้ใช้ได้สำหรับฉันโดยไม่จำเป็นต้องใช้setTextAppearence () :

public CustomView(Context context, AttributeSet attrs) {
    this(context, attrs, attrs.getStyleAttribute());
}

2

ฉันพบปัญหาด้วยเช่นกันและฉันก็พบวิธีการกำหนดรูปแบบโดยทางโปรแกรม บางทีคุณอาจต้องการมันทั้งหมดดังนั้นฉันจึงอัพเดทที่นั่น

พารามิเตอร์ที่สามของวิวคอนสตรัคเตอร์ยอมรับประเภทของ attr ในธีมของคุณเป็นซอร์สโค้ดด้านล่าง:

public TextView(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.textViewStyle);
}

ดังนั้นคุณต้องผ่านประเภทของ R.attr ** แทน R.style **

ในรหัสของฉันฉันทำตามขั้นตอน:

ก่อนอื่นให้ปรับแต่ง attr ที่กำหนดเองเพื่อใช้โดยธีมใน attr.xml

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

ขั้นที่สองระบุสไตล์ของคุณในธีมที่ใช้ใน style.xml

 <style name="AppTheme" parent="android:Theme.Translucent">
    <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    <item name="radio_button_style">@style/radioButtonStyle</item>
</style>
<style name="radioButtonStyle" parent="@android:style/Widget.CompoundButton.RadioButton">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">64dp</item>
    <item name="android:background">#000</item>
    <item name="android:button">@null</item>
    <item name="android:gravity">center</item>
    <item name="android:saveEnabled">false</item>
    <item name="android:textColor">@drawable/option_text_color</item>
    <item name="android:textSize">9sp</item>
</style>

ในตอนท้ายใช้มัน!

            RadioButton radioButton = new RadioButton(mContext, null, R.attr.radio_button_style);

มุมมองที่สร้างโดยทางโปรแกรมจะใช้สไตล์ที่ระบุในธีมของคุณ

คุณสามารถลองและหวังว่ามันจะทำงานได้อย่างสมบูรณ์แบบสำหรับคุณ


0

ฉันทดสอบกับ EditText เท่านั้น แต่คุณสามารถใช้วิธีนี้ได้

โมฆะสาธารณะ setBackgroundResource (ส่วนที่เหลือ int)

เพื่อใช้สไตล์ที่กำหนดไว้ในไฟล์ XML

Sine วิธีนี้เป็นของ View ฉันเชื่อว่ามันจะทำงานกับองค์ประกอบ UI ใด ๆ

ความนับถือ.


ตามเอกสารอธิบายสิ่งนี้ควรใช้กับ drawable ไม่ใช่แบบ ดังนั้นหากใช้งานได้จริงมันเป็นเพียง "โดยบังเอิญ" และคุณไม่ควรเชื่อถือ
Heinzi

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.