Efek material pada tombol dengan warna latar belakang

246

Saya menggunakan perpustakaan dukungan Android v21.

Saya telah membuat tombol dengan warna latar belakang khusus. Efek desain Material seperti riak, mengungkapkan hilang (kecuali ketinggian saat klik) ketika saya menggunakan warna tanah belakang.

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

Latar Belakang Berikut ini adalah tombol normal dan efeknya berfungsi dengan baik.

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

Tombol standar

Sathesh
sumber
9
Ini terjadi karena Anda mengganti latar belakang dengan semua efek Material yang bagus dengan warna solid. Mengenai cara Anda benar-benar mewarnai tombol sambil menjaga efek Material, belum ada seorang pun di SO yang dapat mengetahuinya.
Nathan Walters
2
@SweetWisher Riak dan efek lainnya tidak diterapkan pada tombol ketika saya mengubah warna latar belakang.
Sathesh
1
@NathanWalters Tapi warna abu-abu standar jelek. :-(
Sathesh
6
Percayalah, saya tahu ... Kami akan berhutang budi kepada siapa pun yang tahu bagaimana melakukan ini dengan benar.
Nathan Walters
1
Jawaban mengagumkan stackoverflow.com/a/32238489/1318946
Pratik Butani

Jawaban:

431

Saat Anda menggunakan android:background, Anda mengganti banyak gaya dan tampilan dan nuansa tombol dengan warna kosong.

Update: Sampai dengan rilis versi 23.0.0 dari appcompat , ada yang baru Widget.AppCompat.Button.Coloredgaya yang menggunakan tema Anda colorButtonNormaluntuk warna cacat dan colorAccentuntuk warna diaktifkan.

Ini memungkinkan Anda menerapkannya ke tombol Anda langsung melalui

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

Jika Anda memerlukan kustom colorButtonNormalatau colorAccent, Anda dapat menggunakan ThemeOverlayseperti yang dijelaskan dalam pro-tip ini dan android:themepada tombol.

Jawaban Sebelumnya

Anda dapat menggunakan drawable di direktori v21 Anda untuk latar belakang Anda seperti:

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

Ini akan memastikan warna latar belakang Anda ?attr/colorPrimarydan memiliki animasi riak default menggunakan default ?attr/colorControlHighlight(yang Anda juga dapat mengatur dalam tema Anda jika Anda mau).

Catatan: Anda harus membuat pemilih khusus kurang dari 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>

Dengan asumsi Anda memiliki beberapa warna yang Anda inginkan untuk keadaan default, ditekan, dan fokus. Secara pribadi, saya mengambil screenshot dari riak di tengah dipilih dan menarik negara / fokus utama dari itu.

ianhanniballake
sumber
13
Jawaban bagus! Persis apa yang saya cari, namun perlu dibersihkan dan dibangun kembali sebelum proyek memutuskan untuk mengidentifikasi drawable di drawable-v21.
user1354603
4
@ianhanniballake Saya ingin tahu bagaimana cara menggabungkan teknik kerja ini tanpa kehilangan kustomisasi sudut membulat di tombol tersebut
Joaquin Iurchuk
3
@ianhanniballake hanya sebuah komentar, dapat digambar dalam riak di bawah <item android: drawable ... /> tidak bisa menjadi warna transparan. Jika demikian, riak tidak akan ditampilkan. Butuh beberapa saat untuk menyadari hal itu.
Ivan Kušt
2
Dengan appcompat 23.1.1 dan API 22, keadaan dinonaktifkan dan diaktifkan, keduanya mengambil warna colorButtonNormal tema.
Rémy DAVID
93

Ada solusi sederhana lain untuk memberikan latar belakang kustom untuk tombol "Flat" sambil tetap mempertahankan efek "Material".

  1. Tempatkan tombol Anda di ViewGroup dengan latar belakang yang diinginkan diatur di sana
  2. setel selectableItemBackground dari tema saat ini sebagai latar belakang untuk tombol Anda (API> = 11)

yaitu:

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

Dapat digunakan untuk tombol Flat , itu berfungsi pada API> = 11, dan Anda akan mendapatkan efek riak pada> = 21 perangkat, menjaga tombol biasa pada pra-21 hingga AppCompat diperbarui untuk mendukung riak di sana juga.

Anda juga dapat menggunakan selectableItemBackgroundBorderless untuk> = 21 tombol saja.

Kiruwka
sumber
Anda benar-benar berpikir di luar kotak :-) Meskipun ini adalah salah satu cara untuk melakukan ini, itu mungkin meningkatkan kopling kode dan menggunakan gaya akan menjadi cara yang disarankan.
Sathesh
3
Ini menciptakan tombol datar dengan latar belakang warna, ya. Tapi tombol yang dibuat terlihat seperti kotak, tidak ada sudut membulat dan efek bayangan.
Sanket Berde
7
@SanketBerde Tepat. Karena itulah tombol "flat".
kiruwka
2
Pertanyaan aslinya tidak menyebutkan datar. btw, jika Anda memiliki orang tua <CardView> dalam solusi Anda alih-alih <FrameLayout>, tombol yang dihasilkan akan dinaikkan dan memiliki bayangan. Ini bahkan berfungsi di versi pre-lollipop.
Sanket Berde
1
@SanketBerde senang mengetahui tentang CardViewpendekatan, terima kasih telah berbagi!
kiruwka
88

Berikut ini adalah cara yang kompatibel sederhana dan terbelakang untuk memberikan efek riak ke tombol terangkat dengan latar belakang khusus.

Tata letak Anda akan terlihat seperti ini

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/my_custom_background"
    android:foreground="?android:attr/selectableItemBackground"/>
Bolein95
sumber
9
Ini adalah cara termudah untuk menyelesaikan ini. Jawaban yang bagus.
Tyler Pfaff
1
api 21+ tetapi tidak berfungsi. Diterapkan pada tata letak linier dengan dapat diklik-benar, latar belakang - warna berbeda, ditentukan-depan
Alex
3
Karena Button adalah TextView dan bukan FrameLayout, foregroundtidak ada efek sebelum 23. google.com/...
androidguy
2
BAGUS! Aku bahkan tidak tahu "latar depan" adalah suatu hal!
Eric Schlenz
2
Bekerja seperti pesona ..!
Kannan
25

Saya mengalami masalah ini hari ini sebenarnya bermain dengan perpustakaan v22.

Dengan asumsi bahwa Anda menggunakan gaya Anda dapat mengatur colorButtonNormalproperti dan tombol akan menggunakan warna itu secara default.

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

Di luar itu Anda masih bisa membuat gaya untuk tombol kemudian gunakan itu per tombol jika Anda membutuhkan berbagai macam warna (belum diuji, hanya berspekulasi).

Ingatlah untuk menambahkan android:sebelum nama item dalam gaya v21 Anda .

Robert Rose
sumber
Untuk bermacam-macam tombol berwarna, lihat jawaban Robert lainnya: stackoverflow.com/a/31825439/1617737
ban-geoengineering
Dengan warna latar belakang yang sekarang ditetapkan, apakah ada atribut umum yang dapat saya gunakan di blok kode di atas untuk menentukan warna teks tombol?
Larangan geoengineering
24

Dengan AppCompat (22.1.1+) Anda dapat menambahkan gaya seperti ini:

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

Dan gunakan dengan hanya menerapkan gaya:

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

Secara terprogram mengubah warna, saya menemukan bahwa satu-satunya cara untuk memperbarui warna (pada API 15 atau 16) adalah dengan menggunakan 'daftar warna latar belakang'. Dan itu tidak menghapus animasi radial yang bagus di perangkat API 21:

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

Karena button.setBackground(...)dan button.getBackground().mutate().setColorFilter(...)tidak mengubah warna tombol pada API 15 dan 16 seperti yang mereka lakukan pada API 21.

Robert
sumber
1
Terima kasih banyak, ini bekerja dengan baik untuk saya (bahkan jika menggunakan Tombol dalam tata letak xml sebagai inflater AppCompat menggantikannya dengan AppCompatButton)
Louis CAD
1
Gunakan ColorStateList.valueOf( ... )untuk membangun sederhana ColorStateListhanya satu warna.
Taig
colorAccent dan rippleColor tidak berfungsi dengan gaya
Yar
Terima kasih untuk posting ini. Apa yang berhasil untuk saya: ViewCompat.setBackgroundTintList(myButton, ColorStateList.valueOf(myColor); Javadoc untuk setSupportBackgroundTintListmengatakan itu harus dipanggil dengan cara ini.
JerabekJakub
22

Jawaban @ ianhanniballake benar-benar benar dan sederhana. Tapi saya butuh beberapa hari untuk mengerti. Untuk seseorang yang tidak mengerti jawabannya, berikut ini adalah implementasi yang lebih detail

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

=== Atau ===

<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>
Frank Nguyen
sumber
5
Jawaban Anda adalah potongan terakhir dari teka-teki untuk saya. Anda juga dapat menulis colorButtonNormaldi tema dasar @style/AppTheme. Ini memberikan warna default untuk AppCompat untuk mewarnai tombol yang sesuai. Dan kemudian dapat menggunakan jawaban Anda untuk tema tampilan secara individual.
Siddharth Pant
1
Apakah android:theme="Theme.MaterialButton"atauandroid:theme="@style/Theme.MaterialButton"
osrl
1
@osrl Ini android:theme="@style/Theme.MaterialButton". Terima kasih atas kebenarannya.
Frank Nguyen
12

Saya menggunakan backgroundTint dan foreground:

<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"/>
SpyZip
sumber
afaik tidak ada keharusan untuk atribut foreground karena backgroundTint tidak mengesampingkan riak standar
Julian Os
7

Saya datang ke pos ini mencari cara untuk memiliki warna latar belakang ListViewItem saya , namun tetap mempertahankan riaknya.

Saya cukup menambahkan warna saya sebagai latar belakang dan selectableItemBackground sebagai latar depan:

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

dan itu bekerja seperti pesona. Saya kira teknik yang sama bisa digunakan untuk tombol juga. Semoga berhasil :)

Joakim
sumber
6

Jika Anda tertarik dengan ImageButton, Anda dapat mencoba hal sederhana ini:

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

v22.1dari appcompat-v7memperkenalkan beberapa kemungkinan baru. Sekarang mungkin untuk menetapkan tema tertentu hanya untuk satu tampilan.

Penggunaan aplikasi yang sudah tidak digunakan: tema untuk menata Toolbar. Anda sekarang dapat menggunakan android: theme untuk toolbar pada semua perangkat API level 7 dan lebih tinggi dan android: dukungan tema untuk semua widget di API level 11 dan perangkat yang lebih tinggi.

Jadi alih-alih mengatur warna yang diinginkan dalam tema global, kami membuat yang baru dan menetapkannya hanya untuk Button

Contoh:

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

Dan gunakan gaya ini sebagai tema Anda Button

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

Jika Anda setuju menggunakan perpustakaan pihak ketiga, lihat traex / RippleEffect . Ini memungkinkan Anda untuk menambahkan efek Ripple ke tampilan APAPUN hanya dengan beberapa baris kode. Anda hanya perlu membungkus, dalam file tata letak xml Anda, elemen yang Anda inginkan memiliki efek riak dengan sebuah com.andexert.library.RippleViewwadah.

Sebagai bonus tambahan, ini membutuhkan Min SDK 9 sehingga Anda dapat memiliki konsistensi desain di seluruh versi OS.

Berikut ini contoh yang diambil dari repo GitHub perpustakaan:

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

Anda dapat mengubah warna riak dengan menambahkan atribut ini elemen RippleView: app:rv_color="@color/my_fancy_ripple_color

guy.gc
sumber
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"/>

Menggunakan

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

dan warnanya akan diterima pada pra-lolipop

André Bäuml
sumber
2

Ada dua pendekatan yang dijelaskan dalam tutorial yang bagus menjadi Alex Lockwood: http://www.androiddesignpatterns.com/2016/08/coloring-buttons-with-themeoverlays-background-tints.html :

Pendekatan # 1: Memodifikasi warna latar belakang tombol dengan 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"/>

Pendekatan # 2: Mengatur warna latar belakang 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"/>
makovkastar
sumber
2

Secara terprogram menerapkan warna:

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
Marlon
sumber
-1

Saya mencoba ini:

android:backgroundTint:"@color/mycolor"

alih-alih mengubah properti latar belakang. Ini tidak menghilangkan efek material.

shiladitya
sumber
Ini tidak akan berfungsi untuk perangkat pra-Lollipop (pangsa pasar 70%). Sebenarnya sudah di-backport tetapi Android Studio sampai sekarang masih menunjukkan kesalahan saat menggunakannya tanpa awalan android.
Siddharth Pant