Bagaimana cara mengatur efek klik tombol di Android?

105

Di Android, saat saya menyetel gambar latar belakang ke Tombol, saya tidak bisa melihat efek apa pun pada tombol.

Saya membutuhkan beberapa efek pada tombol sehingga pengguna dapat mengenali tombol yang diklik.

Tombol harus gelap selama beberapa detik saat diklik, jadi apa yang harus saya lakukan untuk ini?

Terima kasih.

Jignesh Ansodariya
sumber
Metode berikut memungkinkan Anda menggunakan satu styleclass untuk menguliti semua tombol Anda, apa pun teksnya: stackoverflow.com/questions/5327553/…
Zack Marrapese
tidak Saya tidak menggunakan Tombol Gambar, apakah saya menggunakan Tombol Normal dengan cara yang mudah untuk ini?
Jignesh Ansodariya
3
Tutorialnya yang sangat bagus: dibbus.com/2011/02/gradient-buttons-for-android
Pratik Butani

Jawaban:

154

Ini dapat dicapai dengan membuat file xml drawable yang berisi daftar status untuk tombol tersebut. Jadi misalnya jika Anda membuat file xml baru bernama "button.xml" dengan kode berikut:

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

Untuk menyimpan gambar latar belakang dengan tampilan yang digelapkan saat dicetak, buat file xml kedua dan beri nama gradient.xml dengan kode berikut:

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

Dalam xml tombol Anda atur latar belakang menjadi tombol xml misalnya

android:background="@drawable/button"

Semoga ini membantu!

Edit: Mengubah kode di atas untuk menampilkan gambar (GAMBAR ANDA) di tombol sebagai lawan dari warna blok.

Ljdawson
sumber
Lalu di mana saya dapat mengatur Gambar untuk Latar Belakang Tombol, untuk mengatur Gambar adalah harus
Jignesh Ansodariya
1
Diedit untuk menunjukkan cara menggunakan gambar latar belakang dengan status XML. Ganti GAMBAR ANDA dengan sumber daya gambar di direktori drawable Anda.
Ljdawson
Ini hanya berfungsi jika src dari tombol berbentuk persegi panjang. Jika src drawable memiliki bentuk yang berbeda dari itu, gradien akan diterapkan ke latar belakang juga, dan ini menyedihkan.
Renato Lochetti
Tidak juga, selalu bisa menggunakan bentuk yang berbeda dalam daftar lapisan
Ljdawson
2
sementara saya menggunakan gambar, itu berfungsi untuk saya .. tetapi ketika saya menggunakan latar belakang Xml. tidak bekerja ...
DKV
88

Ini lebih sederhana ketika Anda memiliki banyak tombol gambar, dan Anda tidak ingin menulis xml-s untuk setiap tombol.

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

Versi 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;
        }
    });
}
András
sumber
2
Saya menggunakan ini dalam kode saya dan satu-satunya masalah yang saya perhatikan sejauh ini adalah tombol berperilaku aneh ketika ditempatkan di ScrollView.
Finnboy11
Ini benar-benar solusi yang luar biasa dan ini harus menjadi jawaban yang benar
Biraj Zalavadia
Bagaimana ini lebih baik? Mendesain harus disimpan di luar kode, bukan?
Bug Terjadi
Ini hanya solusi sederhana untuk masalah ini. Bila Anda memiliki banyak tombol dan Anda tidak ingin membuat xml untuk setiap tombol, ini bisa membantu.
András
Oh Tuhan! Bayangkan memiliki 5 tombol dalam sebuah fragmen ... Anda akan memiliki sejumlah besar kode boilerplate ini ... Lalu bagaimana cara merefaktornya? Ubah filter warna untuk semua tombol di semua aktivitas? Imho, pengembang Anda berikutnya tidak akan begitu senang ..
Leo Droidcoder
84

Buat AlphaAnimationObjek Anda yang menentukan seberapa banyak efek memudar dari tombol, lalu biarkan mulai dionClickListener dari tombol Anda

Sebagai contoh :

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

// some code

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

tentu saja ini hanya cara, bukan yang paling disukai, hanya lebih mudah

Ahmed Adel Ismail
sumber
5
Yang saya suka tentang solusi ini, adalah tidak memerlukan banyak pemilih untuk dibuat, ketika Anda memiliki banyak tombol dengan gambar kustomnya masing-masing.
Pete
2
Ini tidak memudarkan tombol pada satu sentuhan, itu hanya memudarkannya selama sepersekian detik setelah klik terdeteksi dan jari pengguna telah terangkat.
Doug Voss
1
Bagus dan sederhana
@Doug Voss, Anda dapat mengatur durasi animasi menjadi lebih lama
Ahmed Adel Ismail
bagaimana dengan onLongClick dan 'circularReveal'?
Acauã Pitta
44

Anda cukup menggunakan latar depan untuk Viewmendapatkan efek yang dapat diklik:

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


Untuk digunakan dengan tema gelap, tambahkan juga tema ke Anda layout(agar efek yang dapat diklik menjadi jelas):

android:theme="@android:style/ThemeOverlay.Material.Dark"
Francis
sumber
5
Cara termudah untuk menerapkan. Untuk diketahui, Atribut android: latar depan tidak berpengaruh pada level API yang lebih rendah dari 23.
dolgom
1
Solusi paling sederhana.
Jerry Chong
2
Ini harus menjadi jawaban yang diterima, jauh lebih sederhana dan menambahkan efek animasi riak yang bagus.
Tyler
1
@dolgom Untuk API level <23 gunakanlah pada atribut "background". Jadi: android: background = "? android: attr / selectableItemBackground"
Z3R0
24

Untuk membuat item Anda konsisten dengan tampilan dan nuansa sistem, coba referensi atribut sistem android:attr/selectableItemBackgrounddi tag latar depan atau latar depan tampilan yang Anda inginkan:

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

Gunakan kedua atribut untuk mendapatkan efek yang diinginkan sebelum / sesudah API level 23 masing-masing.

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

Ely Dantas
sumber
2
Sejauh ini solusi paling sederhana. Terima kasih!
tykom
9

Atau hanya dengan menggunakan satu gambar latar belakang Anda dapat memperoleh efek klik dengan menggunakan setOnTouchListener

Dua arah

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

masukkan deskripsi gambar di sini

Dan jika Anda tidak ingin menggunakan setOnTouchLister, cara lain untuk mencapainya adalah

    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
sumber
ada kesalahan dalam kode dengan cara ke-2. Apa itu fungsi getCurrent ()? Juga myButton bukan Drawable sehingga tidak bisa ditambahkan sebagai status.
Ehtesham Hasan
Terima kasih telah menunjukkan kesalahannya. Saya telah memperbaikinya, dan myButton adalah turunan dari kelas Tombol yang menyediakan metode setBackgroundDrawable dan mengambil contoh Drawable, maka ini akan berhasil.
Vinayak Bevinakatti
Lihat jawaban saya yang didasarkan pada pendekatan kedua Anda. stackoverflow.com/a/39430738/5229515
Ehtesham Hasan
Ini mungkin harus memiliki "return false" di akhir sehingga tidak mengkonsumsi acara dan onClickListeners tambahan apa pun dapat dipanggil.
Doug Voss
3

hanya ingin menambahkan cara lain yang mudah untuk melakukan ini: Jika ImageButton Anda tetap menjadi latar belakang dan Anda tidak menyetelnya ke null, ini akan berfungsi seperti tombol normal dan akan menampilkan animasi klik saat mengklik persis seperti tombol lainnya. latar belakang saat masih ada:

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

Paddings tidak akan membiarkan background terlihat dan membuat tombol tersebut berfungsi seperti tombol lainnya.

arianoo
sumber
1
ini akan mempertahankan batas tombol persegi di sekitar gambar jika berbentuk lingkaran
MSaudi
3

Ini adalah solusi terbaik yang saya dapatkan dengan mengambil petunjuk dari jawaban @ Vinayak. Semua solusi lainnya memiliki kekurangan yang berbeda.

Pertama-tama buat fungsi seperti ini.

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

Penjelasan:

getConstantState (). newDrawable () digunakan untuk menggandakan Drawable yang ada, jika tidak, drawable yang sama akan digunakan. Baca lebih lanjut dari sini: Android: Menggandakan drawable untuk membuat StateListDrawable dengan filter

mutate () digunakan untuk membuat klon Drawable tidak membagikan statusnya dengan instance Drawable lainnya. Baca lebih lanjut di sini: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()

Pemakaian:

Anda dapat meneruskan semua jenis View (Button, ImageButton, View dll) sebagai parameter ke fungsi dan mereka akan mendapatkan efek klik yang diterapkan padanya.

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

Gunakan RippleDrawable untuk efek ditekan / diklik dengan status Desain Material.

Untuk melakukannya, buat item ripple sebagai folder .xml di bawah / drawable dan gunakan di android: background untuk tampilan apa pun.

  • Efek untuk ikon ditekan / diklik, gunakan efek riak melingkar, misalnya:

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

  • Efek untuk tampilan diklik dengan batas persegi panjang, kita bisa menambahkan riak pada drawable yang ada seperti di bawah ini:

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

Untuk semua tampilan

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

Tetapi untuk cardview yang memiliki penggunaan elevasi

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

Untuk efek klik melingkar seperti pada toolbar

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

Anda juga perlu mengatur

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

Membuat tambahan kecil pada jawaban Andràs:

Anda dapat menggunakan postDelayeduntuk membuat filter warna bertahan selama beberapa waktu agar lebih terlihat:

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

Anda dapat mengubah nilai penundaan 100L sesuai dengan kebutuhan Anda.

hiddeneyes02
sumber
0

Jika Anda menggunakan latar belakang xml dan bukan IMG, hapus saja ini:

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

dari jawaban pertama yang diberikan @Ljdawson kepada kami.

RastaPopuloS
sumber