Dodać efekt falowania do mojego przycisku z kolorem tła przycisku?

128

Utworzyłem przycisk i chcę do niego dodać efekt tętnienia!

Utworzyłem plik XML bg przycisku: (bg_btn.xml)

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#FFFFFF" android:endColor="#00FF00" android:angle="270" />
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
</shape>

A to jest mój plik efektu ripple: (ripple_bg.xml)

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

A to jest mój przycisk, do którego chcę dodać efekt tętnienia:

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="173dp"
android:textColor="#fff"
android:background="@drawable/ripple_bg"
android:clickable="true" />

Ale po dodaniu efektu tętnienia tło przycisku jest przezroczyste, a przycisk wyświetla się tylko po kliknięciu, na przykład:

Przed kliknięciem

Na kliknięcie

Ale potrzebuję zarówno koloru tła przycisku, jak i efektu tętnienia. Znalazłem część tego kodu na różnych blogach Stack Overflow, ale nadal nie działa!

rakcode
źródło
następnym razem zrób zrzuty ekranu znacznie mniejsze ... (zmień rozmiar przed załadowaniem)
użytkownik25
@ user25, możesz także po prostu dodać llub mdo łącza do obrazu. (zobacz moją edycję)
Suragch

Odpowiedzi:

157

Oto kolejny plik XML do rysowania dla tych, którzy chcą dodać wszystko razem gradientowe tło, promień narożnika i efekt tętnienia:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorPrimaryDark">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorPrimaryLight"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>
</ripple>

Dodaj to do tła swojego przycisku.

<Button
    ...
    android:background="@drawable/button_background" />

PS: ta odpowiedź działa na Androidzie API 21 i nowszych.

Pei
źródło
4
@pei Skąd macie te informacje? Chodzi mi o to, skąd wiesz, że istnieje element XML o nazwie ripple do wykonania tej pracy?
1
To jedna z koncepcji stosowanych w projektowaniu materiałów. Zacznij wpisywać nowy znacznik główny w pliku XML do rysowania w Android Studio, wtedy powinieneś być w stanie zobaczyć wszystkie dostępne tagi, w tym ripple.
Pei
1
jaki jest pożytek z maski?
Prashant,
10
wymaga to api poziomu 21
M.kazem Akhgary
2
to działa, ale nie wyjaśniono, jak to działa. powinno być powiązane z identyfikatorem przedmiotu. Należy odwołać się.
oiyio
157

Dodaj "?attr/selectableItemBackground"do android:foregroundatrybutu widoku, jeśli ma już tło wraz z android:clickable="true".

ukośnik odwrotnyN
źródło
nie zawsze działa, ale można dodać tło do odzew jak zauważono w komentarzach Zaakceptowanych odpowiedź
Tyler
Musiałem skorzystać z tego rozwiązania, ponieważ użyłem niestandardowego tła dla mojego przycisku. Działało świetnie.
bnayagrawal
@ROAR, zgadza się, ale przynajmniej: „To nie jest błąd; aplikacja po prostu zignoruje atrybut. Jeśli jednak atrybut jest ważny dla wyglądu lub funkcjonalności aplikacji, należy rozważyć znalezienie alternatywnego sposobu osiągnięcia ten sam wynik z tylko dostępnymi atrybutami, a następnie możesz opcjonalnie utworzyć kopię układu w folderze layout-vNN, który będzie używany w interfejsie API NN lub wyższym, gdzie możesz skorzystać z nowszego atrybutu. " Działa więc dobrze na urządzeniach powyżej API 23 i jest ignorowane, gdy jest poniżej (możemy po prostu tools:ignore="UnusedAttribute).
JorgeAmVF
bez biblioteki obsługującej Androida byłoby to ?android:attr/selectableItemBackground( android:attrzamiast attr)
weekend
1
android:foregroundatrybut nie ma wpływu na poziomy API niższe niż 23
Vadim Kotov
68

Dodaj efekt falowania / animację do przycisku Androida

Po prostu zamień atrybut tła przycisku na android: background = "? Attr / selectableItemBackground", a Twój kod będzie wyglądał następująco.

      <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackground"
        android:text="New Button" />

Inny sposób na dodanie efektu falowania / animacji do przycisku Androida

Korzystając z tej metody, możesz dostosować kolor efektu tętnienia. Najpierw musisz utworzyć plik xml w katalogu zasobów do rysowania. Utwórz plik ripple_effect.xml i dodaj następujący kod. res / drawable / ripple_effect.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

I ustaw tło przycisku na powyższy plik zasobów do rysowania

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_effect"
    android:padding="16dp"
    android:text="New Button" />
Jigar Patel
źródło
1
U mnie efekt tętnienia nie pojawił się. to był tylko przełącznik koloru dla przycisku: / Moja wersja Androida to 5.1.1, więc powinna działać. Możesz mi pomóc?
Podążałem
android: kolor powinien być inny niż na maszcie android: color lub chcesz zobaczyć efekt tętnienia
SpyZip
2
jeśli chcesz mieć tło, po prostu dodaj kolejny element do ripple, na przykład: <item android: drawable = "? attr / colorPrimary" />
Tyler
36

Oprócz rozwiązania Jigara Patela dodaj to do ripple.xml, aby uniknąć przezroczystego tła przycisków.

<item
    android:id="@android:id/background"
    android:drawable="@color/your-color" />

Kompletny xml :

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/your-color"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/your-color" />
        </shape>
    </item>
    <item
        android:id="@android:id/background"
        android:drawable="@color/your-color" />
</ripple>

Użyj tego ripple.xml jako tła w swoim przycisku:

android:background="@drawable/ripple"
Sudheesh R
źródło
2
Nie musieliśmy używać <item android:id="@android:id/mask"> [...]. Chyba że chcesz owalną maskę. Dziękuję za odpowiedź!
Filipe Brito
Co w każdym razie robi ten <item android: id = "@ android: id / mask">, utworzyłem 2 podobne elementy z tym atrybutem i bez niego, i wyglądają dokładnie tak samo
Sartheris Stormhammer
@SartherisStormhammer z oficjalnej dokumentacji: Jeśli ustawiono warstwę maski, efekt tętnienia zostanie zamaskowany na tej warstwie, zanim zostanie narysowany na kompozycie pozostałych warstw potomnych. Jeśli żadna warstwa maski nie jest ustawiona, efekt tętnienia jest maskowany względem kompozytu warstw potomnych. To jest link, developer.android.com/reference/android/graphics/drawable/ ...
Sudheesh R
@SudheeshR to tylko sprawia, że ​​jest to bardziej zagmatwane
Sartheris Stormhammer
@SartherisStormhammer Z tej oficjalnej dokumentacji Myślę, że jest całkiem jasne. Efekt marszczenia zostanie nałożony na warstwy podrzędne / zamaskowane. Przeczytaj dokument jeszcze raz, zrozumiesz, o co chodzi.
Sudheesh R
33

Gdy przycisk ma tło z elementu rysowalnego, możemy dodać efekt ripple do parametru pierwszego planu .. Sprawdź poniżej kod, jak działa dla mojego przycisku z innym tłem

    <Button
    android:layout_width="wrap_content"
    android:layout_height="40dp"
    android:gravity="center"
    android:layout_centerHorizontal="true"                                                             
    android:background="@drawable/shape_login_button"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:text="@string/action_button_login"
     />

Dodaj poniższy parametr dla efektu tętnienia

   android:foreground="?attr/selectableItemBackgroundBorderless"
   android:clickable="true"

W celach informacyjnych patrz poniższy link https://jascode.wordpress.com/2017/11/11/how-to-add-ripple-effect-to-an-android-app/

Jasmine John
źródło
2
Atrybut android: foreground nie ma wpływu na poziomy API niższe niż 23
Ali Khaki
1
Jedną z wad tego podejścia jest to, że chociaż tło mojego przycisku było owalne, tętnienie rozchodziło się do prostokątnych krawędzi.
iCantC
14

AppCompat v7 +

Jeśli nie podasz prefiksu, ?android:aplikacja ulegnie awarii.

W zależności od preferencji należy użyć "?android:attr/selectableItemBackground"lub "?android:attr/selectableItemBackgroundBorderless". Wolę Borderless.

Możesz go umieścić w istniejących nieruchomościach android:backgroundlub android:foregroundje zachować.

Element musi mieć android:clickable="true"i android:focusable="true", aby to działało, ale wiele elementów, takich jak przyciski, ma je truedomyślnie.

<Button
    ...
    android:background="@color/white"
    android:foreground="?android:attr/selectableItemBackgroundBorderless"
/>
<TextView
    ...
    android:background="?android:attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:focusable="true"
/>

Programowo (Java)

TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
myView.setBackgroundResource(value.resourceId);
myView.setFocusable(true); // If needed for view type

Programowo (Kotlin)

val value = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
myView.setBackgroundResource(value.resourceId)
myView.setFocusable(true) // If needed for view type

Funkcja rozszerzenia Kotlin wielokrotnego użytku

myView.ripple()

fun View.ripple(): View {
    val value = TypedValue()
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
    setBackgroundResource(value.resourceId)
    isFocusable = true // Required for some view types
    return this
}
Gibolt
źródło
7

Dodanie atrybutów pierwszego planu i klikalnych atrybutów zadziałało.

<Button
    ... 
    android:background="@color/your_color"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true" />
Ashwin
źródło
6

Oprócz Sudheesh R

Dodaj efekt falowania / animację do przycisku Android z kształtem prostokąta przycisku z rogiem

Utwórz plik xml res / drawable / your_file_name.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/colorWhite"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="50dp" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorAccent"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="50dp" />
        </shape>
    </item>
</ripple>
Digvijay Machale
źródło
4

Używając android: background, zamieniasz znaczną część stylu oraz wyglądu przycisku na pusty kolor.

Aktualizacja: od wersji 23.0.0 AppCompat dostępny jest nowy Widget.AppCompat.Button.Kolorowy styl, który używa colorButtonNormal Twojego motywu dla wyłączonego koloru i colorAccent dla włączonego koloru.

Pozwala to zastosować go bezpośrednio do przycisku za pomocą

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

Możesz użyć drawable w katalogu v21 jako tła, takiego jak:

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

Zapewni to, że kolor tła to? Attr / colorPrimary i będzie mieć domyślną animację tętnienia przy użyciu domyślnego? Attr / colorControlHighlight (które możesz również ustawić w swoim motywie, jeśli chcesz).

Uwaga: musisz utworzyć selektor niestandardowy dla wersji wcześniejszej niż 21:

<?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>
Atman Bhatt
źródło
używam minSDK lvl 21
rakcode
nie ma folderu do rysowania v21, tylko jeden folder, który sam folder folder
v21
tak, użyłem również tego API, jeśli używam tego API po kliknięciu, moja aplikacja się zawiesza
rakcode
właściwie
testuję
4

Spróbuj tego

<Button
            android:id="@+id/btn_location"
            android:layout_width="121dp"
            android:layout_height="38dp"
            android:layout_gravity="center"
            android:layout_marginBottom="24dp"
            android:layout_marginTop="24dp"
            android:foreground="?attr/selectableItemBackgroundBorderless"
            android:clickable="true"
            android:background="@drawable/btn_corner"
            android:gravity="center_vertical|center_horizontal"
            android:paddingLeft="13dp"
            android:paddingRight="13dp"
            android:text="Save"
            android:textColor="@color/color_white" />
Raveendra
źródło
4

Prostym podejściem jest ustawienie motywu widoku, jak opisano tutaj .

some_view.xml

<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="?attr/selectableItemBackgroundBorderless"
   android:focusable="true"
   android:src="@drawable/up_arrow"
   android:theme="@style/SomeButtonTheme"/>

some_style.xml

<style name="SomeButtonTheme" >
   <item name="colorControlHighlight">@color/someColor</item>
</style>
Adam Hurwitz
źródło
3

Po prostu użyj :

android:backgroundTint="#f816a463"

Zamiast:

android:background="#f816a463"

Nie zapomnij zmienić Buttonnaandroid.support.v7.widget.AppCompatButton

Gilad Shapira
źródło
1
Złe jest to, że jeśli potrzebujesz przycisku do wypełnienia w 100% poziomego ekranu, nie będziesz.
Filipe Brito
1

Alternatywne rozwiązanie do korzystania z <ripple> tagu (którego osobiście wolę nie robić, ponieważ kolory nie są „domyślne”) jest następujące:

Utwórz element do rysowania dla tła przycisku i uwzględnij <item android:drawable="?attr/selectableItemBackground">w<layer-list>

Następnie (i myślę, że jest to ważna część) ustawiane programowo backgroundResource(R.drawable.custom_button)w instancji przycisku.

Aktywność / fragment

Button btn_temp = view.findViewById(R.id.btn_temp);
btn_temp.setBackgroundResource(R.drawable.custom_button);

Układ

<Button
    android:id="@+id/btn_temp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/custom_button"
    android:text="Test" />

custom_button.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <corners android:radius="10dp" />
        </shape>
    </item>
    <item android:drawable="?attr/selectableItemBackground" />
</layer-list>
Aidan Host
źródło
Po co programowo ustawić backgroundResource ponownie, podczas gdy układ XML definiuje tło przycisku?
SunnyShiny9