Come impostare l'effetto del clic del pulsante in Android?


105

In Android, quando imposto l'immagine di sfondo su Button, non riesco a vedere alcun effetto sul pulsante.

Ho bisogno di qualche effetto sul pulsante in modo che l'utente possa riconoscere che il pulsante è stato cliccato.

Il pulsante dovrebbe essere scuro per alcuni secondi quando ha cliccato, quindi cosa devo fare per questo?

Grazie.



Il seguente metodo ti consente di utilizzare una singola classe di stile per applicare lo skin a tutti i pulsanti, indipendentemente dal loro testo: stackoverflow.com/questions/5327553/…
Zack Marrapese

no Non sto usando il pulsante immagine, sto usando il pulsante normale in qualche modo semplice per questo?
Jignesh Ansodariya

Risposte:


154

Ciò può essere ottenuto creando un file xml disegnabile contenente un elenco di stati per il pulsante. Quindi, ad esempio, se crei un nuovo file xml chiamato "button.xml" con il codice seguente:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/YOURIMAGE" />
    <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:drawable="@drawable/YOURIMAGE" />
</selector>

Per mantenere l'immagine di sfondo con un aspetto più scuro in stampa, creare un secondo file xml e chiamarlo gradiente.xml con il codice seguente:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <bitmap android:src="@drawable/YOURIMAGE"/>
    </item>
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <gradient android:angle="90" android:startColor="#880f0f10" android:centerColor="#880d0d0f" android:endColor="#885d5d5e"/>
        </shape>
    </item>
</layer-list>

Nell'xml del tuo pulsante imposta lo sfondo in modo che sia il pulsante xml es

android:background="@drawable/button"

Spero che questo ti aiuti!

Modifica: modificato il codice sopra per mostrare un'immagine (LA TUA IMMAGINE) nel pulsante anziché un colore a blocchi.


Quindi dove posso impostare l'immagine per lo sfondo del pulsante, per impostare l'immagine è necessario
Jignesh Ansodariya

1
Modificato per mostrare come utilizzare un'immagine di sfondo con lo stato XML. Sostituisci TUAIMMAGINE con la risorsa immagine nella directory disegnabile.
Ljdawson

Funziona solo se la src del pulsante è rettangolare. Se il disegno src ha una forma diversa da quella, il gradiente verrà applicato anche allo sfondo, e questo è triste.
Renato Lochetti

Non proprio, potrebbe sempre utilizzare una forma diversa nell'elenco dei livelli
Ljdawson

2
mentre sto usando un'immagine funziona per me .. ma quando sto usando uno sfondo Xml. non funziona ...
DKV

88

È più semplice quando hai molti pulsanti immagine e non vuoi scrivere xml-s per ogni pulsante.

Versione Kotlin:

fun buttonEffect(button: View) {
    button.setOnTouchListener { v, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                v.background.setColorFilter(-0x1f0b8adf, PorterDuff.Mode.SRC_ATOP)
                v.invalidate()
            }
            MotionEvent.ACTION_UP -> {
                v.background.clearColorFilter()
                v.invalidate()
            }
        }
        false
    }
}

Versione Java:

public static void buttonEffect(View button){
    button.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.getBackground().clearColorFilter();
                    v.invalidate();
                    break;
                }
            }
            return false;
        }
    });
}

2
Lo uso nel mio codice e l'unico problema che ho notato finora è che il pulsante si comporta in modo strano quando viene inserito in una ScrollView.
Finnboy11

È una soluzione davvero eccellente e questa dovrebbe essere la risposta corretta
Biraj Zalavadia

Come va meglio? La progettazione dovrebbe essere mantenuta al di fuori del codice, non è vero?
bug si verificano il

È solo una semplice soluzione per questo problema. Quando hai molti pulsanti e non vuoi creare xml per ognuno di essi, potrebbe essere utile.
András

Oh mio Dio! Immagina di avere 5 pulsanti in un frammento ... Avrai un sacco di questo codice boilerplate ... Come rifattorizzarlo allora? Cambiare il filtro colore per tutti i pulsanti in tutte le attività? Imho è il tuo prossimo sviluppatore non sarà così felice ..
Leo Droidcoder

84

Crea il tuo AlphaAnimationOggetto che decide quanto sarà l'effetto di dissolvenza del pulsante, quindi lascialo iniziare nella parte onClickListenerdei tuoi pulsanti

Per esempio :

private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);

// some code

public void onClick(View v) {
    v.startAnimation(buttonClick);
}

ovviamente questo è solo un modo, non il preferito, è solo più facile


5
Quello che mi piace di questa soluzione è che non richiede la creazione di molti selettori, quando hai molti pulsanti ciascuno con le proprie immagini personalizzate.
Pete

2
Questo non fa sbiadire il pulsante quando viene toccato, lo fa sfumare solo per una frazione di secondo dopo che il clic viene rilevato e il dito dell'utente è già stato sollevato.
Doug Voss

1
Bello e semplice

@Doug Voss, puoi impostare la durata dell'animazione per allungarla
Ahmed Adel Ismail

che dire di onLongClick e "circularReveal"?
Acauã Pitta

44

Puoi semplicemente usare il primo piano per Viewottenere un effetto cliccabile:

android:foreground="?android:attr/selectableItemBackground"


Per l'uso con il tema scuro aggiungi anche il tema al tuo layout(per avere un effetto cliccabile sia chiaro):

android:theme="@android:style/ThemeOverlay.Material.Dark"

5
Il modo più semplice per implementare. Cordiali saluti, attributo android: il primo piano non ha effetto sui livelli API inferiori a 23.
dolgom

1
La soluzione più semplice.
Jerry Chong

2
Questa dovrebbe essere la risposta accettata, molto più semplice e aggiunge il piacevole effetto di animazione a catena.
Tyler

1
@dolgom Per il livello API <23 usalo sull'attributo "background". Quindi: android: background = "? android: attr /
selectableItemBackground

24

Per rendere il tuo articolo coerente con l'aspetto del sistema, prova a fare riferimento all'attributo di sistema android:attr/selectableItemBackgroundnel tag di sfondo o in primo piano della vista desiderata:

<ImageView
    ...
    android:background="?android:attr/selectableItemBackground"      
    android:foreground="?android:attr/selectableItemBackground"
    ...
/>

Utilizza entrambi gli attributi per ottenere l'effetto desiderato rispettivamente prima / dopo il livello API 23.

https://stackoverflow.com/a/11513474/4683601


2
Di gran lunga la soluzione più semplice. Grazie!
tykom

9

Oppure utilizzando una sola immagine di sfondo è possibile ottenere l'effetto clic utilizzando setOnTouchListener

Due strade

((Button)findViewById(R.id.testBth)).setOnTouchListener(new OnTouchListener() {

      @Override
        public boolean onTouch(View v, MotionEvent event) {
          switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN: {
                  Button view = (Button) v;
                  view.getBackground().setColorFilter(0x77000000, PorterDuff.Mode.SRC_ATOP);
                  v.invalidate();
                  break;
              }
              case MotionEvent.ACTION_UP:
                  // Your action here on button click
              case MotionEvent.ACTION_CANCEL: {
                  Button view = (Button) v;
                  view.getBackground().clearColorFilter();
                  view.invalidate();
                  break;
              }
          }
          return true;
        }
});

inserisci qui la descrizione dell'immagine

E se non vuoi usare setOnTouchLister, un altro modo per ottenerlo è

    myButton.getBackground().setColorFilter(.setColorFilter(0xF00, Mode.MULTIPLY);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {android.R.attr.defaultValue}, myButton);

    myButton.setBackgroundDrawable(listDrawable);

ci sono errori nel codice nel secondo modo. Cos'è la funzione getCurrent ()? Inoltre myButton non è un Drawable quindi non può essere aggiunto come stato.
Ehtesham Hasan

Grazie per aver segnalato l'errore. L'ho corretto e myButton è un'istanza della classe Button che fornisce il metodo setBackgroundDrawable e accetta le istanze Drawable, quindi funzionerà.
Vinayak Bevinakatti

Controlla la mia risposta che si basa sul tuo secondo approccio. stackoverflow.com/a/39430738/5229515
Ehtesham Hasan

Questo dovrebbe probabilmente avere "return false" alla fine, quindi non consuma l'evento e possono essere chiamati eventuali onClickListeners aggiuntivi.
Doug Voss

3

voglio solo aggiungere un altro modo semplice per farlo: se il tuo ImageButton rimane il suo sfondo e non lo imposti su null, funzionerà come un pulsante normale e mostrerà l'animazione del clic mentre fai clic esattamente come gli altri pulsanti. lo sfondo mentre è ancora lì:

<ImageButton
    android:id="@+id/imageButton2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingBottom="1dp"
    android:paddingLeft="1dp"
    android:paddingRight="1dp"
    android:paddingTop="1dp"
    android:src="@drawable/squareicon" />

Le imbottiture non rendono visibile lo sfondo e fanno sì che il pulsante si comporti come gli altri pulsanti.


1
questo manterrà il bordo quadrato del pulsante attorno all'immagine se è circolare
MSaudi

3

Questa è la migliore soluzione che ho trovato prendendo spunto dalla risposta di @ Vinayak. Tutte le altre soluzioni presentano diversi inconvenienti.

Prima di tutto crea una funzione come questa.

void addClickEffect(View view)
{
    Drawable drawableNormal = view.getBackground();

    Drawable drawablePressed = view.getBackground().getConstantState().newDrawable();
    drawablePressed.mutate();
    drawablePressed.setColorFilter(Color.argb(50, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {}, drawableNormal);
    view.setBackground(listDrawable);
}

Spiegazione:

getConstantState (). newDrawable () viene utilizzato per clonare il Drawable esistente altrimenti verrà utilizzato lo stesso drawable. Leggi di più da qui: Android: clonazione di un drawable per creare uno StateListDrawable con filtri

mutate () è usato per fare in modo che il clone Drawable non condivida il suo stato con altre istanze di Drawable. Per saperne di più qui: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()

Uso:

È possibile passare qualsiasi tipo di visualizzazione (pulsante, pulsante immagine, visualizzazione ecc.) Come parametro alla funzione e verrà applicato l'effetto clic.

addClickEffect(myButton);
addClickEffect(myImageButton);

2
Step: set a button in XML with onClick Action:

 <Button
android:id="@+id/btnEditUserInfo"
style="?android:borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="@dimen/txt_height"
android:layout_gravity="center"
android:background="@drawable/round_btn"
android:contentDescription="@string/image_view"
android:onClick="edit_user_info"
android:text="Edit"
android:textColor="#000"
android:textSize="@dimen/login_textSize" />

Step: on button clicked show animation point
//pgrm mark ---- ---- ----- ---- ---- ----- ---- ---- -----  ---- ---- -----

    public void edit_user_info(View view) {

        // show click effect on button pressed
        final AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
        view.startAnimation(buttonClick);

        Intent intent = new Intent(getApplicationContext(),  EditUserInfo.class);
        startActivity(intent);

    }// end edit_user_info

2

Usa RippleDrawable per l'effetto di stato premuto / fatto clic su Material Design.

Per ottenere ciò, crea un elemento ripple come una cartella .xml in / drawable e usalo in android: background per qualsiasi visualizzazione.

  • Effetto per icona premuta / cliccata, usa l'effetto increspatura circolare, ad esempio:

    <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@android:color/darker_gray" />

  • Effetto per la vista cliccata con il bordo del rettangolo, possiamo aggiungere increspatura sul disegnabile esistente come sotto:

    <?xml version="1.0" encoding="utf-8"?> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#000000"> <item android:drawable="@drawable/your_background_drawable"/> </ripple>


2

Per tutte le viste

android:background="?android:attr/selectableItemBackground"

Ma per cardview che utilizza l'elevazione

android:foreground="?android:attr/selectableItemBackground"

Per l'effetto clic circolare come nella barra degli strumenti

android:background="?android:attr/actionBarItemBackground"

Inoltre è necessario impostare

 android:clickable="true"
 android:focusable="true"

0

Fare una piccola aggiunta alla risposta di Andràs:

È possibile utilizzare postDelayedper far durare il filtro colorato per un breve periodo di tempo per renderlo più evidente:

        @Override
        public boolean onTouch(final View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            v.getBackground().clearColorFilter();
                            v.invalidate();
                        }
                    }, 100L);
                    break;
                }
            }
            return false;
        }

È possibile modificare il valore del ritardo di 100 litri in base alle proprie esigenze.


0

Se stai usando lo sfondo xml invece di IMG, rimuovi semplicemente questo:

<item>
    <bitmap android:src="@drawable/YOURIMAGE"/>
</item>

dalla prima risposta che ci ha dato @Ljdawson.

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.