Aggiungere l'effetto a catena al mio pulsante con il colore di sfondo del pulsante?


127

Ho creato un pulsante e voglio aggiungere un effetto a catena a quel pulsante!

Ho creato un file XML button bg: (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>

E questo è il mio file di effetti a catena: (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>

E questo è il mio pulsante a cui voglio aggiungere l'effetto a catena:

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

Ma dopo aver aggiunto l'effetto a catena lo sfondo del pulsante è trasparente e il pulsante viene visualizzato solo quando viene cliccato, in questo modo:

Prima del clic

Al clic

Ma ho bisogno sia del colore di sfondo del pulsante che dell'effetto a catena, ho trovato parte di questo codice in diversi blog di Stack Overflow, ma ancora non funziona!


per favore ridimensiona gli screenshot la prossima volta .. (ridimensiona prima del caricamento)
user25

@ user25, puoi anche aggiungere semplicemente un lo mal link dell'immagine. (vedi la mia modifica)
Suragch

Risposte:


156

Ecco un altro xml disegnabile per coloro che desiderano aggiungere tutti insieme sfondo sfumato, raggio dell'angolo ed effetto a catena:

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

Aggiungilo allo sfondo del tuo pulsante.

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

PS: questa risposta funziona per Android api 21 e versioni successive.


4
@pei Come avete ricevuto queste informazioni da ragazzi? Voglio dire, come fai a sapere che c'è un elemento XML chiamato ripple per fare questo lavoro?

1
È uno dei concetti utilizzati nel material design. Inizia a digitare un nuovo tag radice in un xml disegnabile in Android Studio, quindi dovresti essere in grado di vedere tutti i tag disponibili, inclusi ripple.
Pei

1
a che serve l'elemento maschera?
Prashant

10
questo richiede api livello 21
M.kazem Akhgary

2
funziona ma non viene spiegato come funziona. dovrebbe essere correlato all'ID dell'oggetto. Dovrebbe essere referenziato.
oiyio

155

Aggiungi l' attributo "?attr/selectableItemBackground"alla tua vista android:foregroundse ha già uno sfondo insieme a android:clickable="true".


non sempre funziona, ma puoi aggiungere uno sfondo all'effetto a catena come indicato nei commenti della risposta accettata
Tyler

Ho dovuto utilizzare questa soluzione poiché ho utilizzato uno sfondo personalizzato per il mio pulsante. Ha funzionato benissimo.
bnayagrawal

@ROAR, è vero, ma almeno: "Questo non è un errore; l'applicazione ignorerà semplicemente l'attributo. Tuttavia, se l'attributo è importante per l'aspetto o la funzionalità dell'applicazione, dovresti considerare di trovare un modo alternativo per ottenere lo stesso risultato con solo gli attributi disponibili, quindi puoi facoltativamente creare una copia del layout in una cartella layout-vNN che verrà utilizzata su API NN o versioni successive dove puoi sfruttare l'attributo più recente. " Quindi funziona bene su dispositivi sopra l'API 23 e viene ignorato quando sotto (possiamo solo tools:ignore="UnusedAttribute).
JorgeAmVF

senza la libreria di supporto Android, sarebbe ?android:attr/selectableItemBackground( android:attrinvece di attr)
Weekend

1
android:foregroundl'attributo non ha effetto sui livelli API inferiori a 23
Vadim Kotov

67

Aggiungi effetto increspatura / animazione a un pulsante Android

Sostituisci l'attributo di sfondo del pulsante con android: background = "? Attr / selectableItemBackground" e il tuo codice avrà questo aspetto.

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

Un altro modo per aggiungere effetti / animazioni a catena a un pulsante Android

Utilizzando questo metodo, puoi personalizzare il colore dell'effetto increspatura. Innanzitutto, devi creare un file xml nella directory delle risorse disegnabili. Crea un file ripple_effect.xml e aggiungi il codice seguente. 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>

E imposta lo sfondo del pulsante sopra il file di risorse disegnabili

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_effect"
    android:padding="16dp"
    android:text="New Button" />

1
Per me, l'effetto a catena non è apparso. era solo un cambio di colore per il pulsante: / La mia versione di Android è 5.1.1 quindi dovrebbe funzionare. Potresti aiutare? Ho seguito i tuoi passi
UrviG

android: il colore dovrebbe essere diverso dall'albero android: color, o vuoi vedere l'effetto a
catena

2
se desideri uno sfondo, aggiungi un altro elemento all'ondulazione, ad esempio: <item android: drawable = "? attr / colorPrimary" />
Tyler

36

Oltre alla soluzione di Jigar Patel , aggiungila a ripple.xml per evitare lo sfondo trasparente dei pulsanti.

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

XML completo :

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

Usa questo ripple.xml come sfondo nel tuo pulsante:

android:background="@drawable/ripple"

2
Non abbiamo bisogno di usare il file <item android:id="@android:id/mask"> [...]. A meno che tu non voglia una maschera ovale. Grazie per la tua risposta!
Filipe Brito

Che cosa fa questo <item android: id = "@ android: id / mask"> comunque? Ho creato 2 elementi simili con e senza
quell'attributo

@SartherisStormhammer da documenti ufficiali: Se è impostato un livello maschera, l'effetto a catena verrà mascherato rispetto a quel livello prima di essere disegnato sul composto dei restanti livelli figlio. Se non è impostato alcun livello maschera, l'effetto increspatura viene mascherato rispetto al composto dei livelli figlio. Questo è il link, developer.android.com/reference/android/graphics/drawable/…
Sudheesh R

@SudheeshR che rende tutto più confuso
Sartheris Stormhammer

@SartherisStormhammer Da quella documentazione ufficiale è abbastanza chiaro, credo. L'effetto increspatura verrà disegnato sui livelli figlio / mascherati. Per favore leggi di nuovo il documento, capirai il punto.
Sudheesh R

33

Quando il pulsante ha uno sfondo dal disegnabile, possiamo aggiungere un effetto a catena al parametro in primo piano .. Controlla sotto il codice che funziona per il mio pulsante con uno sfondo diverso

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

Aggiungi sotto il parametro per l'effetto a catena

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

Per riferimento fare riferimento al seguente link https://jascode.wordpress.com/2017/11/11/how-to-add-ripple-effect-to-an-android-app/


2
Attributo Android: il primo piano non ha effetto sui livelli API inferiori a 23
Ali Khaki

1
Uno svantaggio di questo approccio è che, anche se lo sfondo del mio pulsante era ovale, l'increspatura si è propagata fino ai bordi rettangolari.
iCantC

14

AppCompat v7 +

Se non inserisci il prefisso con la ?android:tua app, andrà in crash.

Dovresti usare "?android:attr/selectableItemBackground"o "?android:attr/selectableItemBackgroundBorderless", in base alle tue preferenze. Io preferisco Borderless.

Puoi inserirlo android:backgroundo android:foregroundper mantenere le proprietà esistenti.

L'elemento deve avere android:clickable="true"e android:focusable="true"affinché funzioni, ma molti elementi, come i pulsanti, li hanno trueper impostazione predefinita.

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

A livello di codice (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

A livello di codice (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

Funzione di estensione Kotlin riutilizzabile

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
}

7

L'aggiunta di attributi in primo piano e cliccabili ha funzionato per me.

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

6

Oltre a Sudheesh R

Aggiungi effetto increspatura / animazione a un pulsante Android con forma rettangolo pulsante con angolo

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

4

Quando usi android: background, sostituisci gran parte dello stile e dell'aspetto di un pulsante con un colore vuoto.

Aggiornamento: a partire dalla versione 23.0.0 di AppCompat, è disponibile un nuovo stile Widget.AppCompat.Button. Uno stile colorato che utilizza colorButtonNormal del tema per il colore disabilitato e colorAccent per il colore abilitato.

Ciò ti consente di applicarlo al tuo pulsante direttamente tramite

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

Puoi usare un disegnabile nella tua directory v21 per il tuo sfondo come:

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

Ciò garantirà che il colore di sfondo sia? Attr / colorPrimary e abbia l'animazione di increspatura predefinita utilizzando il valore predefinito? Attr / colorControlHighlight (che puoi anche impostare nel tuo tema se lo desideri).

Nota: dovrai creare un selettore personalizzato per meno di 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>

Sto usando minSDK lvl 21
rakcode

non esiste una cartella disegnabile v21, solo una cartella nella stessa cartella cartella
v21

sì, ho usato anche questa API, se uso questa API dopo aver fatto clic sulla mia app si blocca
rakcode

in realtà, sto testando la mia app sul mio telefono con la modalità di debug e il mio sistema operativo è CyanogenMod13 (Android 6, Marshmellow)
rakcode

4

prova questo

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

4

Un approccio semplice consiste nell'impostare un tema di visualizzazione come descritto qui .

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>

3

Usa solo:

android:backgroundTint="#f816a463"

Invece di:

android:background="#f816a463"

Non dimenticare di cambiare il tuo Buttoninandroid.support.v7.widget.AppCompatButton


1
Il male è che se hai bisogno di un pulsante per riempire al 100% lo schermo orizzontale non lo farai.
Filipe Brito

1

Una soluzione alternativa all'utilizzo del <ripple>tag (che personalmente preferisco non fare, perché i colori non sono "predefiniti"), è la seguente:

Crea un disegnabile per lo sfondo del pulsante e includi <item android:drawable="?attr/selectableItemBackground">nel file<layer-list>

Quindi (e penso che questa sia la parte importante) impostato backgroundResource(R.drawable.custom_button)a livello di codice sull'istanza del pulsante.

Attività / Frammento

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

disposizione

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

Perché dovrebbe impostare nuovamente backgroundResource a livello di codice, mentre il layout xml definisce lo sfondo di Button?
SunnyShiny9
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.