Wie stelle ich den Button-Klick-Effekt in Android ein?

105

Wenn ich in Android das Hintergrundbild auf "Schaltfläche" setze, kann ich keine Auswirkung auf die Schaltfläche sehen.

Ich brauche einen Effekt auf die Schaltfläche, damit der Benutzer erkennen kann, dass auf die Schaltfläche geklickt wird.

Die Schaltfläche sollte einige Sekunden lang dunkel sein, wenn sie angeklickt wurde. Was soll ich also tun?

Vielen Dank.

Jignesh Ansodariya
quelle
Die folgende Methode ermöglicht es Ihnen, eine einzige Stilklasse zu verwenden, um alle Ihre Schaltflächen unabhängig von ihrem Text zu häuten
Zack Marrapese
Nein, ich verwende nicht die Bildschaltfläche. Ich verwende die Normalschaltfläche auf einfache Weise.
Jignesh Ansodariya
3
Es ist ein sehr schönes Tutorial: dibbus.com/2011/02/gradient-buttons-for-android
Pratik Butani

Antworten:

154

Dies kann erreicht werden, indem eine zeichnbare XML-Datei erstellt wird, die eine Liste der Status für die Schaltfläche enthält. Wenn Sie beispielsweise eine neue XML-Datei mit dem Namen "button.xml" mit dem folgenden Code erstellen:

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

Um das Hintergrundbild mit einem abgedunkelten Erscheinungsbild beim Drücken beizubehalten, erstellen Sie eine zweite XML-Datei und nennen Sie sie gradient.xml mit dem folgenden Code:

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

Stellen Sie im XML Ihrer Schaltfläche den Hintergrund als Schaltflächen-XML ein, z

android:background="@drawable/button"

Hoffe das hilft!

Bearbeiten: Der obige Code wurde geändert, um ein Bild (YOURIMAGE) in der Schaltfläche anstelle einer Blockfarbe anzuzeigen.

Ljdawson
quelle
Wo kann ich dann Bild für
Schaltflächenhintergrund einstellen
1
Bearbeitet, um zu zeigen, wie ein Hintergrundbild mit dem Status XML verwendet wird. Ersetzen Sie YOURIMAGE durch die Bildressource in Ihrem Zeichenverzeichnis.
Ljdawson
Dies funktioniert nur, wenn der Quellcode der Schaltfläche rechteckig ist. Wenn das zu zeichnende src eine andere Form hat, wird der Farbverlauf auch auf den Hintergrund angewendet, und das ist traurig.
Renato Lochetti
Nicht wirklich, könnte immer eine andere Form in der
Ebenenliste verwenden
2
Während ich ein Bild verwende, funktioniert es für mich. Aber wenn ich einen XML-Hintergrund verwende. es funktioniert nicht ...
DKV
87

Es ist einfacher, wenn Sie viele Bildschaltflächen haben und nicht für jede Schaltfläche XML-s schreiben möchten.

Kotlin Version:

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

Java-Version:

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;
        }
    });
}
András
quelle
2
Ich verwende dies in meinem Code und das einzige Problem, das ich bisher bemerkt habe, ist, dass sich die Schaltfläche beim Platzieren in einer ScrollView seltsam verhält.
Finnboy11
Es ist wirklich eine hervorragende Lösung und dies sollte die richtige Antwort sein
Biraj Zalavadia
Wie ist das besser Das Entwerfen sollte außerhalb des Codes bleiben, nicht wahr?
Bugs passieren
Es ist nur eine einfache Lösung für dieses Problem. Wenn Sie viele Schaltflächen haben und nicht für jede einzelne XML-Datei erstellen möchten, kann dies hilfreich sein.
András
Oh mein Gott! Stellen Sie sich vor, Sie haben 5 Schaltflächen in einem Fragment ... Sie werden eine ganze Reihe dieses Boilerplate-Codes haben ... Wie kann ich ihn dann umgestalten? Farbfilter für alle Schaltflächen in allen Aktivitäten ändern? Imho es ist dein nächster Entwickler wird nicht so glücklich sein ..
Leo Droidcoder
84

Erstellen Sie Ihr AlphaAnimationObjekt, das entscheidet, wie stark der Fading-Effekt der Schaltfläche sein soll, und lassen Sie es dann in den onClickListenerSchaltflächen beginnen

Zum Beispiel :

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

// some code

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

Natürlich ist dies nur ein Weg, nicht der am meisten bevorzugte, es ist einfach einfacher

Ahmed Adel Ismail
quelle
5
Was mir an dieser Lösung gefällt, ist, dass nicht viele Selektoren erstellt werden müssen, wenn Sie viele Schaltflächen mit jeweils eigenen benutzerdefinierten Bildern haben.
Pete
2
Dadurch wird die Schaltfläche bei einem Touchdown nicht ausgeblendet, sondern nur für den Bruchteil einer Sekunde ausgeblendet, nachdem der Klick erkannt wurde und der Finger des Benutzers bereits angehoben wurde.
Doug Voss
1
Schön und einfach
@ Doug Voss, können Sie die Dauer der Animation einstellen, um sie länger zu machen
Ahmed Adel Ismail
Was ist mit onLongClick und 'CircularReveal'?
Acauã Pitta
44

Sie können einfach Vordergrund verwenden für Ihre Viewklickbare Wirkung zu erzielen:

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


Fügen Sie zur Verwendung mit einem dunklen Thema auch ein Thema zu Ihrem hinzu layout(um einen anklickbaren Effekt zu erzielen):

android:theme="@android:style/ThemeOverlay.Material.Dark"
Francis
quelle
5
Der einfachste Weg zu implementieren. Zu
Ihrer Information
1
Einfachste Lösung.
Jerry Chong
2
Dies sollte die akzeptierte Antwort sein, viel einfacher und fügt den schönen Wellenanimationseffekt hinzu.
Tyler
1
@dolgom Verwenden Sie für API-Level <23 das Attribut "Hintergrund". So: android: background = "? android: attr / selectableItemBackground"
Z3R0
24

Um Ihr Element mit dem Erscheinungsbild des Systems in Einklang zu bringen, verweisen Sie auf das Systemattribut android:attr/selectableItemBackgroundim Hintergrund- oder Vordergrund-Tag Ihrer gewünschten Ansicht:

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

Verwenden Sie beide Attribute, um den gewünschten Effekt vor / nach API-Level 23 zu erzielen.

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

Ely Dantas
quelle
2
Mit Abstand die einfachste Lösung. Vielen Dank!
tykom
9

Wenn Sie nur ein Hintergrundbild verwenden, können Sie den Klickeffekt mithilfe von erzielen setOnTouchListener

Zwei Wege

((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;
        }
});

Geben Sie hier die Bildbeschreibung ein

Und wenn Sie nicht verwenden möchten setOnTouchLister ist der andere Weg, dies zu erreichen

    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);
Vinayak Bevinakatti
quelle
Es gibt Fehler im Code auf die 2. Art. Was ist die Funktion getCurrent ()? Außerdem ist myButton kein Drawable, sodass es nicht als Status hinzugefügt werden kann.
Ehtesham Hasan
Vielen Dank für den Hinweis auf den Fehler. Ich habe es korrigiert, und myButton ist eine Instanz der Button-Klasse, die die Methode setBackgroundDrawable bereitstellt und die Drawable-Instanzen verwendet. Daher funktioniert dies.
Vinayak Bevinakatti
Schauen Sie sich meine Antwort an, die auf Ihrem zweiten Ansatz basiert. stackoverflow.com/a/39430738/5229515
Ehtesham Hasan
Dies sollte wahrscheinlich am Ende "return false" haben, damit das Ereignis nicht verbraucht wird und zusätzliche onClickListeners aufgerufen werden können.
Doug Voss
3

Ich möchte nur einen weiteren einfachen Weg hinzufügen, um dies zu tun: Wenn Ihr ImageButton seinen Hintergrund behält und Sie ihn nicht auf Null setzen, funktioniert er wie eine normale Schaltfläche und zeigt die Klickanimation an, während Sie genau wie andere Schaltflächen klicken der Hintergrund, solange er noch da ist:

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

Durch die Auffüllungen wird der Hintergrund nicht sichtbar und die Schaltfläche verhält sich wie andere Schaltflächen.

Arianoo
quelle
1
Dies wird den quadratischen
Knopfrand
3

Dies ist die beste Lösung, die ich gefunden habe, um Hinweise aus der Antwort von @ Vinayak zu erhalten. Alle anderen Lösungen haben unterschiedliche Nachteile.

Erstellen Sie zunächst eine solche Funktion.

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);
}

Erläuterung:

getConstantState (). newDrawable () wird verwendet, um das vorhandene Drawable zu klonen, andernfalls wird dasselbe Drawable verwendet. Lesen Sie hier mehr: Android: Klonen eines Drawable, um ein StateListDrawable mit Filtern zu erstellen

mutate () wird verwendet, um den Drawable-Klon dazu zu bringen, seinen Status nicht mit anderen Instanzen von Drawable zu teilen. Lesen Sie hier mehr darüber: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()

Verwendung:

Sie können jede Art von Ansicht (Button, ImageButton, View usw.) als Parameter an die Funktion übergeben, und sie erhalten den auf sie angewendeten Klickeffekt.

addClickEffect(myButton);
addClickEffect(myImageButton);
Ehtesham Hasan
quelle
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
Vinod Joshi
quelle
2

Verwenden Sie RippleDrawable für den Status "Material Design".

Um dies zu erreichen, erstellen Sie ein Ripple-Element als XML-Ordner unter / drawable und verwenden Sie es in android: background für alle Ansichten.

  • Effekt für gedrücktes / geklicktes Symbol. Verwenden Sie den kreisförmigen Welleneffekt, zum Beispiel:

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

  • Effekt für die Ansicht, auf die mit einer Rechteckgrenze geklickt wird, können wir eine Welligkeit über das vorhandene Zeichenelement wie unten hinzufügen:

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

Giang Nguyen
quelle
2

Für alle Ansichten

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

Aber für Kartenansicht, die Höhenverwendung hat

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

Für kreisförmigen Klickeffekt wie in der Symbolleiste

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

Auch müssen Sie einstellen

 android:clickable="true"
 android:focusable="true"
Faizan Khan
quelle
0

Eine kleine Ergänzung zu Andrs Antwort:

Sie können verwenden postDelayed, um den Farbfilter für einen kurzen Zeitraum haltbar zu machen, damit er besser sichtbar wird:

        @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;
        }

Sie können den Wert der Verzögerung 100L an Ihre Bedürfnisse anpassen.

hiddeneyes02
quelle
0

Wenn Sie XML-Hintergrund anstelle von IMG verwenden, entfernen Sie einfach Folgendes:

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

von der ersten Antwort, die @Ljdawson uns gab.

RastaPopuloS
quelle