วัสดุที่มีผลต่อปุ่มที่มีสีพื้นหลัง


246

ฉันใช้ห้องสมุดสนับสนุน Android v21

ฉันสร้างปุ่มด้วยสีพื้นหลังที่กำหนดเอง เอฟเฟกต์การออกแบบวัสดุเช่นระลอกคลื่นการเปิดเผยจะหายไป (ยกเว้นระดับความสูงเมื่อคลิก) เมื่อฉันใช้สีพื้นหลัง

 <Button
 style="?android:attr/buttonStyleSmall"
 android:background="?attr/colorPrimary"
 android:textColor="@color/white"
 android:textAllCaps="true"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Button1"
 />

พื้นหลัง ต่อไปนี้เป็นปุ่มปกติและเอฟเฟกต์ใช้งานได้ดี

<Button
 style="?android:attr/buttonStyleSmall"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:textAllCaps="true"
 android:text="Button1"
/>

ปุ่มเริ่มต้น


9
สิ่งนี้เกิดขึ้นเนื่องจากคุณเปลี่ยนพื้นหลังด้วยเอฟเฟ็กต์วัสดุที่ดีทั้งหมดด้วยสีทึบ สำหรับวิธีที่คุณใช้ปุ่มสีอย่างถูกต้องในขณะที่ยังคงลักษณะพิเศษของวัสดุไว้ไม่มีใครใน SO สามารถเข้าใจได้
Nathan Walters

2
@SweetWisher ระลอกและเอฟเฟกต์อื่น ๆ จะไม่ถูกนำไปใช้ในปุ่มเมื่อฉันเปลี่ยนสีพื้นหลัง
Sathesh

1
@NathanWalters แต่สีเทาเริ่มต้นนั้นน่าเกลียด :-(
Sathesh

6
เชื่อฉันสิฉันรู้ว่า ... เราจะเป็นหนี้ก้อนโตสำหรับใครก็ตามที่คิดว่าทำสิ่งนี้ได้อย่างถูกต้อง
Nathan Walters

คำตอบ:


431

เมื่อคุณใช้ android:backgroundคุณจะเปลี่ยนสไตล์และความรู้สึกของปุ่มด้วยสีที่ว่างเปล่า

อัปเดต:ในเวอร์ชัน 23.0.0ของAppCompatมีWidget.AppCompat.Button.Coloredรูปแบบใหม่ที่ใช้ธีมของคุณcolorButtonNormalสำหรับสีที่ปิดใช้งานและcolorAccentที่เปิดใช้งาน

วิธีนี้ช่วยให้คุณสามารถนำไปใช้กับปุ่มของคุณโดยตรงผ่าน

<Button
  ...
  style="@style/Widget.AppCompat.Button.Colored" />

หากคุณต้องการกำหนดเองcolorButtonNormalหรือcolorAccentคุณสามารถใช้ThemeOverlayตามที่อธิบายไว้ในเคล็ดลับนี้และandroid:themeที่ปุ่ม

คำตอบก่อนหน้า

คุณสามารถใช้ drawable ในไดเรกทอรี v21 ของคุณสำหรับพื้นหลังของคุณเช่น:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?attr/colorControlHighlight">
    <item android:drawable="?attr/colorPrimary"/>
</ripple>

วิธีนี้จะทำให้สีพื้นหลังของคุณเป็นแบบเคลื่อนไหว?attr/colorPrimaryและมีภาพเคลื่อนไหวระลอกคลื่นเริ่มต้นโดยใช้ค่าเริ่มต้น?attr/colorControlHighlight(ซึ่งคุณสามารถตั้งค่าในชุดรูปแบบของคุณได้หากต้องการ)

หมายเหตุ: คุณจะต้องสร้างตัวเลือกที่กำหนดเองสำหรับน้อยกว่า v21:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/primaryPressed" android:state_pressed="true"/>
    <item android:drawable="@color/primaryFocused" android:state_focused="true"/>
    <item android:drawable="@color/primary"/>
</selector>

สมมติว่าคุณมีสีที่คุณต้องการสำหรับค่าเริ่มต้นกดและสถานะโฟกัส โดยส่วนตัวแล้วผมจับภาพหน้าจอของระลอกคลื่นกึ่งกลางผ่านการเลือกและดึงสถานะหลัก / โฟกัสออกจากนั้น


13
คำตอบที่ดี! สิ่งที่ฉันกำลังมองหา แต่จำเป็นต้องทำความสะอาดและสร้างใหม่ก่อนที่โครงการจะตัดสินใจระบุ drawable ใน drawable-v21
user1354603


4
@ianhanniballake ฉันสงสัยว่าจะรวมเทคนิคการทำงานนี้โดยไม่สูญเสียการปรับแต่งมุมโค้งมนในปุ่มเหล่านั้นได้อย่างไร
Joaquin Iurchuk

3
@ianhanniballake เพียงแค่แสดงความคิดเห็น, drawable ในระลอกภายใต้ <item android: drawable ... /> ไม่สามารถเป็นสีโปร่งใส ในกรณีนั้นระลอกจะไม่ปรากฏขึ้น ฉันใช้เวลาสักพักกว่าจะรู้ว่า
Ivan Kušt

2
ด้วย appcompat 23.1.1 และ API 22 การปิดใช้งานและสถานะที่เปิดใช้งานทั้งสองใช้สี colorButtonNormal
Rémy DAVID

93

มีอีกวิธีง่ายๆในการให้พื้นหลังที่กำหนดเองสำหรับปุ่ม "แบน" ในขณะที่ยังคงลักษณะพิเศษ "วัสดุ" ไว้

  1. วางปุ่มของคุณใน ViewGroup พร้อมตั้งค่าพื้นหลังที่ต้องการ
  2. ตั้งselectableItemBackgroundจากธีมปัจจุบันเป็นพื้นหลังสำหรับปุ่มของคุณ (API> = 11)

เช่น:

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/blue">
    <Button
        style="?android:attr/buttonStyleSmall"
        android:background="?android:attr/selectableItemBackground"
        android:textColor="@android:color/white"
        android:textAllCaps="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Button1"
        />
</FrameLayout>

สามารถใช้สำหรับแบนปุ่มใช้งานได้กับ API> = 11 และคุณจะได้รับผลกระทบระลอกคลื่นบนอุปกรณ์> = 21 ทำให้ปุ่มปกติในวันที่ 21 จนถึง AppCompat จะได้รับการอัปเดตเพื่อรองรับระลอกที่นั่น

คุณยังสามารถใช้selectableItemBackgroundBorderlessสำหรับปุ่ม> = 21 เท่านั้น


แท้จริงคุณคิดนอกกรอบ :-) แม้ว่านี่จะเป็นวิธีหนึ่งในการทำเช่นนี้ แต่มันอาจเพิ่มการมีเพศสัมพันธ์รหัสและการใช้รูปแบบจะเป็นวิธีที่แนะนำ
Sathesh

3
สิ่งนี้จะสร้างปุ่มแบนพร้อมพื้นหลังสีใช่ แต่ปุ่มที่สร้างขึ้นจะดูเหมือนสี่เหลี่ยมไม่มีมุมมนและเอฟเฟกต์เงา
Sanket Berde

7
@SanketBerde แน่นอน เพราะนั่นคือปุ่ม "แบน"
kiruwka

2
คำถามเดิมไม่ได้พูดถึงแบน btw หากคุณมีพาเรนต์ <CardView> ในโซลูชันแทนที่จะเป็น <FrameLayout> ปุ่มผลลัพธ์จะถูกยกขึ้นและมีเงา สิ่งนี้สามารถใช้งานได้ในเวอร์ชัน pre-lollipop
Sanket Berde

1
@SanketBerde ที่ดีที่จะรู้เกี่ยวกับCardViewวิธีการขอบคุณสำหรับการแบ่งปัน!
kiruwka

88

นี่เป็นวิธีที่ใช้งานง่ายและย้อนกลับเพื่อส่งเอฟเฟกต์ระลอกคลื่นไปยังปุ่มยกระดับพร้อมพื้นหลังที่กำหนดเอง

เค้าโครงของคุณควรมีลักษณะเช่นนี้

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/my_custom_background"
    android:foreground="?android:attr/selectableItemBackground"/>

9
นี่เป็นวิธีที่ง่ายที่สุดในการทำสิ่งนี้ให้สำเร็จ คำตอบที่ดี.
Tyler Pfaff

1
API 21+ แต่ไม่ทำงาน ใช้กับรูปแบบเชิงเส้นที่สามารถคลิกได้จริงพื้นหลัง - สีที่ต่างกันระบุเบื้องหน้า
อเล็กซ์

3
เนื่องจาก Button เป็น TextView และไม่ใช่ FrameLayout foregroundจึงไม่มีผลกระทบใด ๆ ก่อน 23. google.com/…
androidguy

2
NICE! ฉันไม่รู้ด้วยซ้ำว่า "เบื้องหน้า" เป็นเรื่อง!
Eric Schlenz

2
ทำงานเหมือนมีเสน่ห์ .. !
Kannan

25

ฉันพบปัญหาในวันนี้จริง ๆ แล้วเล่นกับไลบรารี v22

สมมติว่าคุณใช้สไตล์คุณสามารถตั้งค่าcolorButtonNormalคุณสมบัติและปุ่มจะใช้สีนั้นตามค่าเริ่มต้น

<style name="AppTheme" parent="BaseTheme">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>
    <item name="colorAccent">@color/accentColor</item>
    <item name="colorButtonNormal">@color/primaryColor</item>
</style>

นอกเหนือจากนั้นคุณยังสามารถสร้างสไตล์ให้กับปุ่มจากนั้นใช้ปุ่มนั้นต่อปุ่มหากคุณต้องการการแบ่งประเภทของสี (ยังไม่ได้ทดสอบเพียงแค่คาดเดา)

อย่าลืมเพิ่มandroid:ก่อนชื่อรายการของคุณในรูปแบบ V21


สำหรับปุ่มสีที่หลากหลายให้ดูคำตอบอื่น ๆ ของ Robert: stackoverflow.com/a/31825439/1617737
ban-geoengineering

เมื่อตั้งค่าสีพื้นหลังแล้วยังมีคุณสมบัติทั่วไปที่ฉันสามารถใช้ในบล็อกรหัสด้านบนเพื่อระบุสีข้อความของปุ่มได้หรือไม่
บ้าน geoengineering

24

ด้วย AppCompat (22.1.1+) คุณสามารถเพิ่มสไตล์ดังนี้:

<style name="MyGreenButton">
    <item name="colorButtonNormal">#009900</item>
</style>

และใช้เพียงแค่ใช้สไตล์:

<android.support.v7.widget.AppCompatButton
    style="@style/MyGreenButton"
    android:layout_width="match_width"
    android:layout_height="wrap_content"
    android:text="A Green Button"
    />

การเปลี่ยนสีโดยทางโปรแกรมฉันพบว่าวิธีเดียวที่จะอัปเดตสี (บน API 15 หรือ 16) คือการใช้ 'รายการสีพื้นหลัง' แทน และจะไม่ลบภาพเคลื่อนไหวรัศมีที่ดีบนอุปกรณ์ API 21:

ColorStateList colorStateList = new ColorStateList(new int[][] {{0}}, new int[] {0xFF009900}); // 0xAARRGGBB
button.setSupportBackgroundTintList(colorStateList);

เพราะbutton.setBackground(...)และbutton.getBackground().mutate().setColorFilter(...)ไม่เปลี่ยนสีปุ่มบน API 15 และ 16 เช่นเดียวกับที่ทำบน API 21


1
ขอบคุณมากมันทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน (แม้ว่าการใช้ปุ่มในรูปแบบ xml เนื่องจาก AppCompat Inflater แทนที่ด้วย AppCompatButton)
Louis CAD

1
ใช้ColorStateList.valueOf( ... )เพื่อสร้างความเรียบง่ายColorStateListเพียงสีเดียว
Taig

colorAccent และ rippleColor ไม่ทำงานในรูปแบบ
Yar

ขอบคุณสำหรับโพสต์นี้ ทำงานได้ดีสำหรับฉัน: ViewCompat.setBackgroundTintList(myButton, ColorStateList.valueOf(myColor); Javadoc สำหรับsetSupportBackgroundTintListบอกว่ามันควรจะเรียกว่าวิธีนี้
JerabekJakub

22

คำตอบของ @ ianhanniballake นั้นถูกต้องและเรียบง่ายอย่างแน่นอน แต่ฉันต้องเข้าใจสองสามวัน สำหรับคนที่ไม่เข้าใจคำตอบของเขานี่คือรายละเอียดเพิ่มเติมในการใช้งาน

<Button
        android:id="@+id/btn"
        style="@style/MaterialButton"
        ... />


<style name="MaterialButton" parent="Widget.AppCompat.Button.Colored">
    <item name="android:theme">@style/Theme.MaterialButton</item>
   ...
</style>


<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>

=== === หรือ

<Button
        android:id="@+id/btn"
        style="@style/Widget.AppCompat.Button.Colored"
        android:theme="@style/Theme.MaterialButton" />

<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>

5
คำตอบของคุณคือชิ้นส่วนสุดท้ายของปริศนาสำหรับฉัน หนึ่งยังสามารถเขียนcolorButtonNormalในชุดรูปแบบฐาน@style/AppThemeในรูปแบบฐานสิ่งนี้จะให้สีเริ่มต้นกับ AppCompat เพื่อกำหนดสีของปุ่มตามความเหมาะสม และจากนั้นสามารถใช้คำตอบของคุณเพื่อกำหนดมุมมองเป็นรายบุคคล
Siddharth Pant

1
มันเป็นandroid:theme="Theme.MaterialButton"หรือandroid:theme="@style/Theme.MaterialButton"
osrl

1
@osrl มัน android:theme="@style/Theme.MaterialButton"มัน ขอบคุณสำหรับความถูกต้องของคุณ
แฟรงก์เหงียน

12

ฉันใช้ backgroundTint และเบื้องหน้า:

<Button
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:backgroundTint="@color/colorAccent"
    android:foreground="?android:attr/selectableItemBackground"
    android:textColor="@android:color/white"
    android:textSize="10sp"/>

afaik ไม่จำเป็นต้องมีแอตทริบิวต์ foreground เนื่องจาก backgroundTint ไม่ได้แทนที่ระลอกคลื่นมาตรฐาน
Julian Os

7

ฉันมาที่โพสต์นี้เพื่อหาวิธีที่จะมีสีพื้นหลังของListViewรายการของฉันแต่ยังคงระลอกคลื่น

ฉันเพิ่มสีของฉันเป็นพื้นหลังและ selectableItemBackground เป็นพื้นหน้า:

<style name="my_list_item">
    <item name="android:background">@color/white</item>
    <item name="android:foreground">?attr/selectableItemBackground</item>
    <item name="android:layout_height">@dimen/my_list_item_height</item>
</style>

และมันใช้งานได้อย่างมีเสน่ห์ ฉันเดาว่าเทคนิคเดียวกันนี้สามารถใช้กับปุ่มได้เช่นกัน โชคดี :)



6

หากคุณมีความสนใจใน ImageButton คุณสามารถลองทำสิ่งนี้ได้ง่ายๆ:

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:drawable/ic_button"
    android:background="?attr/selectableItemBackgroundBorderless"
/>

5

v22.1ของการappcompat-v7แนะนำความเป็นไปได้ใหม่ ๆ ตอนนี้เป็นไปได้ที่จะกำหนดธีมเฉพาะให้กับมุมมองเดียวเท่านั้น

เลิกใช้งานแอพ: ธีมสำหรับ Toolbar สไตล์ ตอนนี้คุณสามารถใช้ android: theme สำหรับแถบเครื่องมือบน API ระดับ 7 และอุปกรณ์ที่สูงกว่าทั้งหมดและ android: การสนับสนุนชุดรูปแบบสำหรับวิดเจ็ตทั้งหมดใน API ระดับ 11 และอุปกรณ์ที่สูงกว่า

ดังนั้นแทนที่จะตั้งค่าสีที่ต้องการในชุดรูปแบบส่วนกลางเราสร้างขึ้นใหม่และกำหนดให้กับ Button

ตัวอย่าง:

<style name="MyColorButton" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorButtonNormal">@color/myColor</item>
</style>

และใช้สไตล์นี้เป็นธีมของคุณ Button

<Button
 style="?android:attr/buttonStyleSmall"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Button1"
 android:theme="@style/MyColorButton"/>

4

หากคุณกำลังตกลงกับการใช้ห้องสมุดของบุคคลที่สามตรวจสอบtraex / RippleEffect มันช่วยให้คุณเพิ่มเอฟเฟกต์ระลอกคลื่นลงในมุมมองใดก็ได้ด้วยโค้ดเพียงไม่กี่บรรทัด คุณเพียงแค่ตัดคำในไฟล์เลย์เอาท์ xml ของคุณองค์ประกอบที่คุณต้องการให้เอฟเฟกต์ระลอกคลื่นกับcom.andexert.library.RippleViewคอนเทนเนอร์

ในฐานะที่เป็นโบนัสที่เพิ่มเข้ามานั้นจะต้องใช้ SDK ขั้นต่ำ 9 เพื่อให้คุณสามารถมีความสอดคล้องในการออกแบบในทุกเวอร์ชั่นของระบบปฏิบัติการ

นี่เป็นตัวอย่างที่นำมาจาก repo GitHub ของห้องสมุด

<com.andexert.library.RippleView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:rv_centered="true">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@android:drawable/ic_menu_edit"
        android:background="@android:color/holo_blue_dark"/> 

</com.andexert.library.RippleView>

คุณสามารถเปลี่ยนสีระลอกได้โดยการเพิ่มแอททริบิวนี้ในองค์ประกอบ RippleView: app:rv_color="@color/my_fancy_ripple_color


3
<android.support.v7.widget.AppCompatButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:backgroundTint="#fff"
    android:textColor="#000"
    android:text="test"/>

ใช้

xmlns:app="http://schemas.android.com/apk/res-auto"

และสีจะรับกับ pre-lolipop


2

มีสองวิธีที่อธิบายไว้ในบทช่วยสอนที่ดีคือ Alex Lockwood: http://www.androiddesignpatterns.com/2016/08/coloring-buttons-with-themeoverlays-background-tints.html :

วิธีที่ # 1: การปรับเปลี่ยนสีพื้นหลังของปุ่มด้วย ThemeOverlay

<!-- res/values/themes.xml -->
<style name="RedButtonLightTheme" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorAccent">@color/googred500</item>
</style>

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:theme="@style/RedButtonLightTheme"/>

วิธีที่ # 2: การตั้งค่าสีพื้นหลังของ AppCompatButton

<!-- res/color/btn_colored_background_tint.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Disabled state. -->
    <item android:state_enabled="false"
          android:color="?attr/colorButtonNormal"
          android:alpha="?android:attr/disabledAlpha"/>

    <!-- Enabled state. -->
    <item android:color="?attr/colorAccent"/>

</selector>

<android.support.v7.widget.AppCompatButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:backgroundTint="@color/btn_colored_background_tint"/>

2

ใช้สีโดยทางโปรแกรม:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {

    ColorStateList colorStateListRipple = new ColorStateList(
            new int[][] {{0}},
            new int[] {Color.WHITE} // ripple color
            );

    RippleDrawable rippleDrawable = (RippleDrawable) myButton.getBackground();
    rippleDrawable.setColor(colorStateListRipple);
    myButton.setBackground(rippleDrawable); // applying the ripple color
}

ColorStateList colorStateList = new ColorStateList(
        new int[][]{
                new int[]{android.R.attr.state_pressed}, // when pressed
                new int[]{android.R.attr.state_enabled}, // normal state color
                new int[]{} // normal state color
        },
        new int[]{
                Color.CYAN, // when pressed
                Color.RED, // normal state color
                Color.RED // normal state color
        }
);

ViewCompat.setBackgroundTintList(myButton, colorStateList); // applying the state colors

-1

ฉันลองสิ่งนี้:

android:backgroundTint:"@color/mycolor"

แทนที่จะเปลี่ยนคุณสมบัติพื้นหลัง สิ่งนี้ไม่ได้ลบผลกระทบของวัสดุ


สิ่งนี้จะไม่ทำงานกับอุปกรณ์ pre-Lollipop (ส่วนแบ่งการตลาด 70%) จริงๆแล้วมันได้รับการ backported แต่ Android Studio ณ ตอนนี้ยังคงแสดงข้อผิดพลาดเมื่อใช้งานโดยไม่มีคำนำหน้า android
Siddharth Pant
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.