Làm thế nào để đặt hiệu ứng nhấp vào nút trong Android?


105

Trong Android, khi tôi đặt hình nền thành Nút, tôi không thể thấy bất kỳ hiệu ứng nào trên nút.

Tôi cần một số hiệu ứng trên nút để người dùng có thể nhận ra nút đó được nhấp.

Nút sẽ tối trong vài giây khi nó nhấp vào, vì vậy tôi nên làm gì cho điều này?

Cảm ơn.



Các phương pháp sau đây cho phép bạn sử dụng một styleClass duy nhất để da tất cả các nút của bạn, bất kể văn bản của họ: stackoverflow.com/questions/5327553/...
Zack Marrapese

không Tôi không sử dụng Nút hình ảnh, tôi đang sử dụng Nút bình thường có cách nào dễ dàng cho việc này không?
Jignesh Ansodariya

Câu trả lời:


154

Điều này có thể đạt được bằng cách tạo một tệp xml có thể kéo được chứa danh sách các trạng thái cho nút. Vì vậy, ví dụ: nếu bạn tạo một tệp xml mới có tên "button.xml" với mã sau:

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

Để giữ cho hình nền bị tối khi nhấn, hãy tạo tệp xml thứ hai và gọi nó là gradient.xml với mã sau:

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

Trong xml của nút của bạn, đặt nền là nút xml, ví dụ:

android:background="@drawable/button"

Hi vọng điêu nay co ich!

Chỉnh sửa: Đã thay đổi mã trên để hiển thị hình ảnh (MÌNH HÌNH ẢNH) trong nút trái ngược với màu khối.


Sau đó, nơi tôi có thể thiết lập hình ảnh cho nút Background, để thiết lập hình ảnh là bắt buộc
Jignesh Ansodariya

1
Đã chỉnh sửa để hiển thị cách sử dụng hình nền với XML trạng thái. Thay thế YOURIMAGE bằng tài nguyên hình ảnh trong thư mục có thể vẽ của bạn.
Ljdawson

Điều này chỉ hoạt động nếu src của nút là hình chữ nhật. Nếu src drawable có bất kỳ hình dạng nào khác với hình dạng đó, gradient cũng sẽ được áp dụng cho nền, và điều này thật đáng buồn.
Renato Lochetti

Không thực sự, luôn luôn có thể sử dụng một hình dạng khác nhau trong danh sách lớp
Ljdawson

2
trong khi tôi đang sử dụng một hình ảnh thì nó phù hợp với tôi .. nhưng khi tôi đang sử dụng nền Xml. nó không hoạt động ...
DKV

88

Sẽ đơn giản hơn khi bạn có rất nhiều nút hình ảnh, và bạn không muốn viết xml-s cho mỗi nút.

Phiên bản 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
    }
}

Phiên bản 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
Tôi sử dụng điều này trong mã của mình và vấn đề duy nhất tôi nhận thấy cho đến nay là nút hoạt động kỳ lạ khi được đặt trong ScrollView.
Finnboy 11

Đó là giải pháp thực sự tuyệt vời và điều này nên được câu trả lời đúng
Biraj Zalavadia

Làm thế nào là điều này tốt hơn? Thiết kế nên được giữ bên ngoài mã, phải không?
Lỗi xảy ra vào

Nó chỉ là một giải pháp đơn giản cho vấn đề này. Khi bạn có nhiều nút và bạn không muốn tạo xmls cho từng nút, điều đó có thể hữu ích.
András

Chúa ơi! Hãy tưởng tượng có 5 nút trong một đoạn ... Bạn sẽ có cả đống mã soạn sẵn này ... Làm thế nào để cấu trúc lại nó? Thay đổi bộ lọc màu cho tất cả các nút trong tất cả các hoạt động? Imho đó là nhà phát triển tiếp theo của bạn sẽ không hạnh phúc như vậy ..
Leo Droidcoder

84

Tạo AlphaAnimationĐối tượng của bạn để quyết định mức độ sẽ là hiệu ứng mờ dần của nút, sau đó để nó bắt đầu trong các onClickListenernút của bạn

Ví dụ :

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

// some code

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

tất nhiên đây chỉ là một cách, không phải là cách ưa thích nhất, nó chỉ dễ dàng hơn


5
Điều tôi thích ở giải pháp này là nó không yêu cầu tạo nhiều bộ chọn, khi bạn có nhiều nút, mỗi nút có hình ảnh tùy chỉnh của riêng chúng.
Pete

2
Thao tác này không làm mờ nút khi chạm xuống, nó chỉ làm mờ nút trong tích tắc sau khi phát hiện nhấp chuột và ngón tay của người dùng đã được nhấc lên.
Doug Voss

1
Đẹp và đơn giản

@Doug Voss, bạn có thể thiết lập thời gian của hình ảnh động để làm cho nó dài hơn
Ahmed Adel Ismail

còn onLongClick và 'circleReveal' thì sao?
Acauã Pitta

44

Bạn chỉ có thể sử dụng foreground cho bạn Viewđể đạt được hiệu ứng nhấp được:

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


Để sử dụng với chủ đề tối, hãy thêm chủ đề vào của bạn layout(để hiệu ứng có thể nhấp được rõ ràng):

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

5
Cách dễ nhất để thực hiện. FYI, Thuộc tính android: foreground không ảnh hưởng đến các cấp API thấp hơn 23.
dolgom

1
Giải pháp đơn giản nhất.
Jerry Chong

2
Đây phải là câu trả lời được chấp nhận, đơn giản hơn nhiều và nó thêm hiệu ứng hoạt hình gợn sóng đẹp mắt.
Tyler

1
@dolgom Đối với cấp độ API <23, hãy sử dụng nó trên thuộc tính "background". Vì vậy, android: background = "? android: attr / selectableItemBackground"
Z3R0

24

Để làm cho mặt hàng của bạn nhất quán với giao diện hệ thống, hãy thử tham chiếu thuộc tính hệ thống android:attr/selectableItemBackgroundtrong thẻ nền hoặc thẻ nền của chế độ xem mong muốn của bạn:

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

Sử dụng cả hai thuộc tính để có được hiệu ứng mong muốn trước / sau API cấp 23 tương ứng.

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


2
Bởi cho đến nay giải pháp đơn giản nhất. Cảm ơn!
tykom

9

Hoặc chỉ sử dụng một hình nền, bạn có thể đạt được hiệu ứng nhấp chuột bằng cách sử dụng setOnTouchListener

Hai lối

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

nhập mô tả hình ảnh ở đây

Và nếu bạn không muốn sử dụng setOnTouchLister, một cách khác để đạt được điều này là

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

có lỗi trong mã theo cách thứ 2. Hàm getCurrent () là gì? Ngoài ra myButton không phải là một Drawable nên không thể thêm nó dưới dạng trạng thái.
Ehtesham Hasan

Cảm ơn vì đã chỉ ra lỗi. Tôi đã sửa nó và myButton là một thể hiện của lớp Button cung cấp phương thức setBackgroundDrawable và nó lấy các thể hiện Drawable, do đó điều này sẽ hoạt động.
Vinayak Bevinakatti

Hãy xem câu trả lời của tôi dựa trên cách tiếp cận thứ hai của bạn. stackoverflow.com/a/39430738/5229515
Ehtesham Hasan

Điều này có thể phải có "return false" ở cuối để nó không tiêu thụ sự kiện và bất kỳ onClickListrators bổ sung nào có thể được gọi.
Doug Voss

3

chỉ muốn thêm một cách dễ dàng khác để thực hiện việc này: Nếu ImageButton của bạn vẫn giữ nguyên nền và bạn không đặt nó thành null, nó sẽ hoạt động giống như một nút bình thường và sẽ hiển thị hoạt ảnh nhấp chuột trong khi nhấp chính xác như các nút khác. nền trong khi nó vẫn ở đó:

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

Các phần đệm sẽ không cho phép nhìn thấy nền và làm cho nút hoạt động giống như các nút khác.


1
điều này sẽ giữ cho đường viền nút vuông xung quanh hình ảnh nếu nó là hình tròn
MSaudi

3

Đây là giải pháp tốt nhất mà tôi đưa ra với những gợi ý từ câu trả lời của @ Vinayak. Tất cả các giải pháp khác đều có những nhược điểm khác nhau.

Trước hết hãy tạo một chức năng như thế này.

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

Giải trình:

getConstantState (). newDrawable () được sử dụng để sao chép Drawable hiện có, nếu không, cùng một drawable sẽ được sử dụng. Đọc thêm từ đây: Android: Sao chép một drawable để tạo StateListDrawable với các bộ lọc

mutate () được sử dụng để làm cho bản sao Drawable không chia sẻ trạng thái của nó với các trường hợp khác của Drawable. Đọc thêm về nó tại đây: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate ()

Sử dụng:

Bạn có thể chuyển bất kỳ loại Chế độ xem nào (Nút, ImageButton, Chế độ xem, v.v.) làm tham số cho hàm và chúng sẽ nhận được hiệu ứng nhấp chuột được áp dụng cho chúng.

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

Sử dụng RippleDrawable cho trạng thái Material Design được nhấn / nhấp vào hiệu ứng.

Để đạt được điều này, hãy tạo mục ripple dưới dạng thư mục .xml trong / có thể vẽ và sử dụng nó trong android: background cho mọi chế độ xem.

  • Hiệu ứng cho biểu tượng được nhấn / nhấp, sử dụng hiệu ứng gợn tròn, ví dụ:

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

  • Hiệu ứng cho chế độ xem được nhấp với ranh giới hình chữ nhật, chúng ta có thể thêm gợn sóng trên có thể vẽ hiện có như dưới đây:

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

Đối với tất cả các chế độ xem

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

Nhưng đối với chế độ xem thẻ có sử dụng độ cao

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

Đối với hiệu ứng nhấp chuột tròn như trong thanh công cụ

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

Ngoài ra bạn cần đặt

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

0

Thực hiện một bổ sung nhỏ cho câu trả lời của Andràs:

Bạn có thể sử dụng postDelayedđể làm cho bộ lọc màu tồn tại trong một khoảng thời gian nhỏ để làm cho nó dễ nhận thấy hơn:

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

Bạn có thể thay đổi giá trị độ trễ 100L để phù hợp với nhu cầu của mình.


0

Nếu bạn đang sử dụng nền xml thay vì IMG, chỉ cần xóa phần này:

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

từ câu trả lời đầu tiên mà @Ljdawson cho chúng tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.