Làm cách nào để tạo hiệu ứng nhấp chuột vào imageview giống như một nút trên Android?


84

Tôi có imageview trong ứng dụng Android của mình mà tôi đang sử dụng giống như một nút với sự kiện onClick được đưa ra, nhưng như bạn có thể đoán, nó không mang lại cho imageview một hiệu ứng có thể nhấp khi được nhấp. Làm thế nào tôi có thể đạt được điều đó?

Câu trả lời:


53

Bạn có thể thiết kế các hình ảnh khác nhau cho các trạng thái được nhấp / không được nhấp và đặt chúng trong onTouchListener như sau

final ImageView v = (ImageView) findViewById(R.id.button0);
        v.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                switch (arg1.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.setImageBitmap(res.getDrawable(R.drawable.img_down));
                    break;
                }
                case MotionEvent.ACTION_CANCEL:{
                    v.setImageBitmap(res.getDrawable(R.drawable.img_up));
                    break;
                }
                }
                return true;
            }
        });

Sự lựa chọn tốt hơn là bạn xác định một bộ chọn như sau

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true"   
        android:drawable="@drawable/img_down" />
    <item android:state_selected="false"   
        android:drawable="@drawable/img_up" />
</selector>

và chọn hình ảnh trong sự kiện:

v.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN);
                return true;
            }
        });

1
bạn có thể giải thích res.getDrawable res nó làm gì không?
VenushkaT

v.setSelected sẽ chỉ == true một lần, ngay lập tức chuyển sang false do MotionEvent.ACTION_MOVE. Khi ngón tay được thả ra, MotionEvent.ACTION_UP sẽ xảy ra. Nếu sử dụng phương pháp bộ chọn, hãy sử dụng logic riêng biệt để setSelected hoặc setPressed. if (arg1.getAction () == MotionEvent.ACTION_DOWN) {v.setPressed (true); } else if (arg1.getAction () == MotionEvent.ACTION_UP) {v.setPressed (false); }
Adam Denoon

Tốt hơn là MotionEvent.ACTION_DOWN || MotionEvent.ACTION_MOVEgiữ cho hình ảnh hiển thị miễn là chúng ta đang nhấn.
Alaa M.

Bạn không cần phải làm vậy setOnTouchListener(.... Bạn có thể chỉ cần tạo <selector ...>và sau đó đặt ImageView có thể nhấp được bằng XML như<ImageView ... android:clickable="true" android:focusable="true" android:src="@drawable/my_selector" />
Pierre

76

Bạn có thể làm điều này với một hình ảnh duy nhất bằng cách sử dụng một cái gì đó như sau:

     //get the image view
    ImageView imageView = (ImageView)findViewById(R.id.ImageView);

    //set the ontouch listener
    imageView.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    ImageView view = (ImageView) v;
                    //overlay is black with transparency of 0x77 (119)
                    view.getDrawable().setColorFilter(0x77000000,PorterDuff.Mode.SRC_ATOP);
                    view.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL: {
                    ImageView view = (ImageView) v;
                    //clear the overlay
                    view.getDrawable().clearColorFilter();
                    view.invalidate();
                    break;
                }
            }

            return false;
        }
    });

Tôi có thể sẽ biến nó thành một lớp con của ImageView (hoặc ImageButton vì nó cũng là một lớp con của ImageView) để dễ sử dụng lại, nhưng điều này sẽ cho phép bạn áp dụng giao diện "đã chọn" cho một lần xem hình ảnh.


2
Tôi cũng đã thêm một trường hợp cho ACTION_CANCEL, nó hoạt động tốt, cảm ơn!
Alan

Cuộc gọi tốt - Tôi đã tự thêm mã đó vào mã riêng của mình nhưng cũng sẽ cập nhật nó ở đây.
Mr Zorn

1
Đây có thể là một câu hỏi khác, nhưng làm cách nào để hủy sau ACTION_UP? Cụ thể ... Người dùng truy cập hình ảnh. Người dùng kéo hình ảnh ngón tay ra để hủy. Nhưng hành động không bị hủy với mã này
sudocoder

Tôi cũng sẽ thêm MotionEvent.ACTION_OUTSIDE;)
bonnyz

3
bạn có thể muốn quay trở lại false, nếu không thực tế của xem onClick()sự kiện sẽ không bị sa thải
Nimrod Dayan

45

Có thể thực hiện chỉ với một tệp hình ảnh bằng phương pháp ColorFilter. Tuy nhiên, ColorFilter dự kiến ​​sẽ hoạt động với ImageViews chứ không phải Buttons, vì vậy bạn phải chuyển đổi các nút của mình thành ImageView. Đây không phải là vấn đề nếu bạn đang sử dụng hình ảnh làm nút của mình, nhưng sẽ khó chịu hơn nếu bạn có văn bản ... Dù sao, giả sử bạn tìm ra cách giải quyết vấn đề với văn bản, đây là mã để sử dụng:

ImageView button = (ImageView) findViewById(R.id.button);
button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);

Điều đó áp dụng lớp phủ màu đỏ cho nút (mã màu là mã hex cho màu đỏ hoàn toàn mờ đục - hai chữ số đầu tiên là độ trong suốt, sau đó là RR GG BB.).


3
Bạn có thể vui lòng giải thích điều gì sẽ xảy ra sau khi mã đó chạy, và nơi nó dự định được gọi không? Tôi đã cố gắng gọi 2 dòng này khi khởi tạo imageView - nó sơn hình ảnh của tôi bằng màu đỏ và không có gì xảy ra sau đó, cả khi nhấp chuột cũng như khi chạm vào. Khi gọi liên lạc cũng vậy.
esteewhy 12/1213

45

CHỈNH SỬA : Mặc dù câu trả lời gốc bên dưới hoạt động và dễ thiết lập, hãy tham khảo bài đăng này bởi Người ủng hộ nhà phát triển Android tại Google nếu bạn muốn / cần triển khai hiệu quả hơn. Cũng lưu ý rằng android:foregroundthuộc tính này sẽ đến với tất cả các Chế độ xem , bao gồm cả ImageView, theo mặc định trong Android M.


Vấn đề với việc sử dụng bộ chọn cho ImageView là bạn chỉ có thể đặt nó làm nền của chế độ xem - miễn là hình ảnh của bạn mờ, bạn sẽ không thấy hiệu ứng của bộ chọn đằng sau nó.

Mẹo là bọc ImageView của bạn trong FrameLayout với thuộc tính android:foregroundcho phép chúng tôi xác định lớp phủ cho nội dung của nó. Nếu chúng tôi đặt android:foregroundthành một bộ chọn (ví dụ: ?android:attr/selectableItemBackgroundđối với API cấp 11+) và đính kèm OnClickListenervào FrameLayout thay vì ImageView, hình ảnh sẽ được phủ lên với bộ chọn có thể vẽ của chúng tôi - hiệu ứng nhấp chuột mà chúng tôi mong muốn!

Hãy chứng kiến:

<FrameLayout
    android:id="@+id/imageButton"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="?android:attr/selectableItemBackground" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/yourImageFile" />

</FrameLayout>

(Lưu ý rằng điều này nên được đặt trong bố cục mẹ của bạn.)

final View imageButton = findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View view) {
        // do whatever we wish!
    }
});

2
Tuyệt quá ! Đây là một giải pháp rất tốt. Giải pháp tương tự được sử dụng trong ứng dụng danh bạ cho các hành động SMS hoặc Cuộc gọi.
Jerry

Sẽ không hoạt động trong API <11.? Android: attr / selectableItemBackground yêu cầu API cấp 11 (tối thiểu hiện tại là 8)
MSaudi

Các selectableItemBackgroundthuộc tính được chỉ thêm vào mức API 11, vì vậy bạn phải sử dụng bộ chọn khác nếu bạn muốn sử dụng giải pháp này cho các cấp API cũ. Ví dụ: đối với một trong các ứng dụng của tôi hỗ trợ API cấp 7, tôi sử dụng @drawable/list_selector_holo_lighttài nguyên được tạo bằng công cụ Android Holo Colors Generator .
justasm

Bạn có thể đạt được cùng một hành vi chỉ bằng 1 <ImageButton>với selectableItemBackground!
Yohan Dahmani

28

Sử dụng style = "? Android: borderlessButtonStyle" trong tệp XML. Nó sẽ hiển thị hiệu ứng nhấp chuột mặc định của Android.

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_launcher" 
    style="?android:borderlessButtonStyle"
/>

1
Đây thực sự là câu trả lời tốt nhất, dễ dàng hơn nhiều
FrankMonza

1
Điều này đặt padding và ngay cả khi bạn đặt padding thành 0, nếu hình ảnh bạn cung cấp cho nó chiếm toàn bộ imageView, bạn sẽ không thấy bất kỳ hiệu ứng nào của việc nhấp chuột.
nhà phát triển android

2
@androiddeveloper sử dụng android:adjustViewBounds="true"để bỏ đặt đệm.
Hafez Divandari

1
Nó được khuyến khích sử dụng style="?android:attr/borderlessButtonStyle": developer.android.com/guide/topics/ui/controls/…
Hafez Divandari.

21

Đơn giản chỉ cần sử dụng một ImageButton .


3
Cá nhân tôi không thể làm cho nó giống như ImageView. Không có đường viền, hãy kéo dài hình ảnh đến kích thước của ImageButton, v.v. Nếu bạn có thể đưa ra vấn đề về đường viền và độ giãn này, đồng thời cập nhật bài đăng của bạn. Khai thác một số danh tiếng sẽ đến với bạn là tiền thưởng =)
tổng cộng vào

15

Đây là cách đơn giản của tôi để giải quyết điều đó:

ImageView iv = (ImageView) findViewById(R.id.imageView);

iv.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        //Agrega porcentajes de cada fraccion de grafica pastel

        Animation animFadein = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade_in);

        iv.startAnimation(animFadein);
    });

Trong hồ sơ res/anim/fade_in.xml:

<?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:fillAfter="true" >

<alpha
    android:duration="100"
    android:fromAlpha="0.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="1.0" />
 </set>

Giải pháp tuyệt vời - cảm ơn! Tôi đã cuộn qua bài đăng này và thử tất cả những bài ngắn gọn - và không thành công. Cuối cùng tôi đã đến đây và nó đã làm việc cho tôi. Một quan sát - nếu bạn có hơn 2 nút muốn áp dụng hoạt ảnh cho .. cho mã của tôi, tôi thấy tôi cần tạo một phiên bản duy nhất của đối tượng Hoạt ảnh cho mỗi nút mà tôi muốn áp dụng hiệu ứng. Việc sử dụng lại cùng một phiên bản đã làm cho tất cả các nút nhấp nháy khi nhấp vào 1 nút.
Gene Bo

9

Đặt nền có thể chọn cho ImageView và thêm một số đệm. Sau đó, đính kèm OnClickListener.

<ImageView
    android:id="@+id/your_image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/your_image"
    android:padding="10dp"
    android:background="?android:attr/selectableItemBackground"/>

Có cách nào để sử dụng nó mà không cần đặt đệm và làm cho toàn bộ ImageView có hiệu ứng chứ không chỉ là vùng trống không?
nhà phát triển android

Điều này sẽ hiển thị gợn sóng trong khối, chúng ta cần gợn sóng trung tâm
Kishan Solanki

8

Để xác định lựa chọn có thể vẽ của bộ chọn

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true"   
        android:drawable="@drawable/img_down" />
    <item android:state_selected="false"   
        android:drawable="@drawable/img_up" />
</selector>

Tôi phải sử dụng android: state_pressed thay vì android: state_selected

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

5

Bạn có thể thử với android:background="@android:drawable/list_selector_background" để có được hiệu ứng tương tự như "Thêm báo thức" trong "Đồng hồ báo thức" mặc định (bây giờ là Đồng hồ để bàn).


5

Nếu bạn muốn gợn sóng khi chạm vào, nó có thể được cung cấp bởi mã này:

<ImageView
    ...
    android:background="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    ...
</ImageView>

Tương tự, bạn có thể triển khai hiệu ứng nhấp chuột cho TextView

<TextView
    ...
    android:background="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    ...
</TextView>

4

Điều này đã làm việc cho tôi:

img.setOnTouchListener(new OnTouchListener(){

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction())
                {
                    case MotionEvent.ACTION_DOWN:
                    {
                        ((ImageView)v).setImageAlpha(200);
                        break;
                    }
                    case MotionEvent.ACTION_MOVE:
                    {
                        // if inside bounds
                        if(event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0 && event.getY() < v.getHeight())
                        {
                            ((ImageView)v).setImageAlpha(200);
                        }
                        else
                        {
                            ((ImageView)v).setImageAlpha(255);
                        }

                        break;
                    }
                    case MotionEvent.ACTION_UP:
                    {
                        ((ImageView)v).setImageAlpha(255);
                    }
                }
                return true;
            }

        });

@Edit: Như Gunhan đã nói sẽ có vấn đề tương thích ngược với phương thức setImageAlpha. Tôi đã sử dụng phương pháp này:

public static void setImageAlpha(ImageView img, int alpha)
    {
        if(Build.VERSION.SDK_INT > 15)
        {
            img.setImageAlpha(alpha);
        }
        else
        {
            img.setAlpha(alpha);
        }
    }

1
setImageAlpha đòi hỏi mức API 16. Do đó, đối với các ứng dụng tương thích ngược của nó không thể sử dụng nó
Gunhan

1
@Gunhan thực sự, bạn có thể sử dụng thư viện "nineOldAndroids" cho phép sử dụng alpha ngay cả trên các API cũ hơn. chỉ cần sử dụng: ViewHelper.setAlpha (view, alpha);
nhà phát triển Android

4

Tôi làm một số việc tương tự Xem phù hợp với bạn hay không

Xem Trình trợ giúp Hiệu ứng Báo chí:

  • sử dụng: thực hiện một số hiệu ứng báo chí đơn giản như iOS

    Cách sử dụng đơn giản:

  • ImageView img = (ImageView) findViewById (R.id.img);

  • ViewPressEffectHelper.attach (img)

https://gist.github.com/extralam/7489370


4

Kết hợp với tất cả các câu trả lời ở trên, tôi muốn ImageView được nhấn và thay đổi trạng thái nhưng nếu người dùng di chuyển thì hãy "hủy" và không thực hiện onClickListener.

Tôi đã kết thúc việc tạo một đối tượng Point trong lớp và thiết lập tọa độ của nó theo thời điểm người dùng đẩy xuống ImageView. Trên MotionEvent.ACTION_UP, tôi ghi lại một điểm mới và so sánh các điểm.

Tôi chỉ có thể giải thích nó rất rõ, nhưng đây là những gì tôi đã làm.

// set the ontouch listener
weatherView.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // Determine what action with a switch statement
        switch (event.getAction()) {

        // User presses down on the ImageView, record the original point
        // and set the color filter
        case MotionEvent.ACTION_DOWN: {
            ImageView view = (ImageView) v;

            // overlay is black with transparency of 0x77 (119)
            view.getDrawable().setColorFilter(0x77000000,
                    PorterDuff.Mode.SRC_ATOP);
            view.invalidate();

            p = new Point((int) event.getX(), (int) event.getY());
            break;
        }

        // Once the user releases, record new point then compare the
        // difference, if within a certain range perform onCLick
        // and or otherwise clear the color filter
        case MotionEvent.ACTION_UP: {
            ImageView view = (ImageView) v;
            Point f = new Point((int) event.getX(), (int) event.getY());
            if ((Math.abs(f.x - p.x) < 15)
                    && ((Math.abs(f.x - p.x) < 15))) {
                view.performClick();
            }
            // clear the overlay
            view.getDrawable().clearColorFilter();
            view.invalidate();
            break;
        }
        }
        return true;
    }
});

Tôi có một bộ onClickListener trên imageView, nhưng đây có thể là một phương thức.


bằng cách thêm trường hợp MotionEvent.ACTION_CANCELcó cùng chức năng như MotionEvent.ACTION_UPvậy có thể "xóa" chế độ xem nếu người dùng thực hiện "kéo" không phải là hành động nhấp chuột.
Mando Stam

4

Bạn có thể Ghi đè setPressedtrong ImageView và thực hiện lọc màu ở đó, thay vì tạo trình nghe onTouchEvent:

@Override
public void setPressed(boolean pressed) {
    super.setPressed(pressed);

    if(getDrawable() == null)
        return;

    if(pressed) {
        getDrawable().setColorFilter(0x44000000, PorterDuff.Mode.SRC_ATOP);
        invalidate();
    }
    else {
        getDrawable().clearColorFilter();
        invalidate();
    }
}

4

Dựa trên câu trả lời của ông Zorn , tôi sử dụng một phương thức tĩnh trong lớp Tiện ích trừu tượng của mình:

public abstract class Utility {
...

    public static View.OnTouchListener imgPress(){
        return imgPress(0x77eeddff); //DEFAULT color
    }

    public static View.OnTouchListener imgPress(final int color){
        return new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch(event.getAction()) {

                    case MotionEvent.ACTION_DOWN: {
                        ImageView view = (ImageView) v;
                        view.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
                        view.invalidate();
                        break;
                    }

                    case MotionEvent.ACTION_UP:
                        v.performClick();

                    case MotionEvent.ACTION_CANCEL: {
                        ImageView view = (ImageView) v;

                        //Clear the overlay
                        view.getDrawable().clearColorFilter();
                        view.invalidate();
                        break;
                    }
                }

                return true;
            }
        };
    }

    ...
}

Sau đó, tôi sử dụng nó với onTouchListener:

ImageView img=(ImageView) view.findViewById(R.id.image);
img.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) { /* Your click action */ }
});
img_zc.setOnTouchListener(Utility.imgPress()); //Or Utility.imgPress(int_color_with_alpha)

Sẽ rất đơn giản nếu bạn có nhiều hình ảnh và bạn muốn có một hiệu ứng onTouch đơn giản, không có bất kỳ tệp XML nào có thể vẽ được và chỉ có một hình ảnh.




3

Tôi nghĩ ImageButton là một giải pháp tốt hơn

<ImageButton
    android:layout_width="96dp"
    android:layout_height="56dp"
    android:src="@mipmap/ic_launcher"
    android:adjustViewBounds="true"
    android:background="@android:color/transparent"
    android:foreground="@drawable/selector" />

2

Tôi có một giải pháp làm đẹp hơn nếu bạn sử dụng hình nền :)

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

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

2

HOẶC LÀ:

Bạn có thể sử dụng biểu mẫu này, với Nút Hình ảnh.

Tạo tệp res/drawable/btn_video.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/image"
        android:state_pressed="true" />
    <item android:drawable="@drawable/ico2"
        android:state_focused="true" />
    <item android:drawable="@drawable/ico2" />
</selector>

res/layout/activity_main.xml:

<ImageButton
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/imageButton"
    android:layout_gravity="center_horizontal"
    android:onClick="eventImageBtn"
    android:background="@drawable/btn_video"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
/>

Hình ảnh của bạn thay đổi bằng một cú nhấp chuột và bạn có thể điều chỉnh bằng bố cục tuyến tính:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="@color/menu_item_background">

        <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"
                      android:paddingLeft="@dimen/main_screen_side_padding" android:paddingRight="@dimen/main_screen_side_padding" android:paddingTop="@dimen/main_screen_side_padding" android:paddingBottom="@dimen/main_screen_side_padding"
                      android:background="#ffb3ff13" android:weightSum="10.00">


            <LinearLayout android:layout_weight="2.50" android:background="#ff56cfcd" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" >

                <ImageButton
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/imageButton"
                    android:layout_gravity="center_horizontal"
                    android:onClick="eventImageBtn"
                    android:background="@drawable/btn_video"
                    android:adjustViewBounds="true"
                    android:scaleType="fitXY"
                />
            </LinearLayout>

            <LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" >
            </LinearLayout>

            <LinearLayout android:layout_weight="4.50" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ff8aa5ff">
            </LinearLayout>

            <LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" >
            </LinearLayout>

            <LinearLayout android:layout_weight="2.00" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ffff7d1a" >
            </LinearLayout>

        </LinearLayout>
    </LinearLayout>
</ScrollView>

2

Đây là giải pháp của tôi, sử dụng thư viện " nineOldAndroids ", cũng hỗ trợ các API cũ:

rootView.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(final View v, final MotionEvent event) {

        switch (event.getAction()) {

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                v.setBackgroundResource(R.drawable.listview_normal);
                ViewHelper.setAlpha(imageView, 1);
                break;

            case MotionEvent.ACTION_DOWN:
                v.setBackgroundResource(0);
                v.setBackgroundColor(getResources().getColor(R.color.listview_pressed));
                ViewHelper.setAlpha(imageView, 0.75f);
                break;
        }
        return false;
    }
});

Nó giả định rootView là chính ô (bố cục) và nó có một imageView duy nhất mà bạn muốn bị ảnh hưởng bởi màu mà bạn muốn áp dụng cho toàn bộ ô.


CHỈNH SỬA: nếu muốn, bạn cũng có thể mở rộng ImageView để xử lý nền trước và đặt nó thành "? Android: attr / selectableItemBackground". Có một thư viện cho điều này ở đây và một hướng dẫn về cách thực hiện nó cho bất kỳ chế độ xem nào bạn muốn, tại đây .


@madlymad cảm ơn bạn đã sửa định dạng mã, mặc dù tôi nghĩ rằng đã xảy ra lỗi với thụt lề. Dù sao, nó đủ tốt để có thể đọc nó ...
nhà phát triển Android

1

Cảm ơn sự giúp đỡ về chủ đề này. Tuy nhiên, bạn đã bỏ lỡ một điều ... bạn cũng cần phải xử lý ACTION_CANCEL. Nếu không thì bạn có thể không khôi phục đúng giá trị alpha của ImageView trong trường hợp chế độ xem chính trong hệ thống phân cấp chế độ xem chặn một sự kiện cảm ứng (hãy nghĩ rằng ScrollView bao bọc bạn ImageView).

Đây là một lớp hoàn chỉnh dựa trên lớp trên nhưng cũng quan tâm đến ACTION_CANCEL. Nó sử dụng lớp trợ giúp ImageViewCompat để tóm tắt sự khác biệt trong API JellyBean trước khi đăng.

public class ChangeAlphaOnPressedTouchListener implements OnTouchListener {

    private final float pressedAlpha;

    public ChangeAlphaOnPressedTouchListener(float pressedAlpha) {
        this.pressedAlpha = pressedAlpha;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        ImageView iv = (ImageView) v;
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            ImageViewCompat.setAlpha(iv, pressedAlpha);
            break;

        case MotionEvent.ACTION_MOVE:
            if (isInsideViewBounds(v, event)) {
                ImageViewCompat.setAlpha(iv, pressedAlpha);
            } else {
                ImageViewCompat.setAlpha(iv, 1f);
            }
            break;
        case MotionEvent.ACTION_UP:
            ImageViewCompat.setAlpha(iv, 1f);
            break;
        case MotionEvent.ACTION_CANCEL:
            ImageViewCompat.setAlpha(iv, 1f);
        }
        return false;
    }

    private static boolean isInsideViewBounds(View v, MotionEvent event) {
        return event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0
                && event.getY() < v.getHeight();
    }
}

1

Đây là mã của tôi. Ý tưởng là ImageView nhận bộ lọc màu khi người dùng chạm vào nó và bộ lọc màu sẽ bị xóa khi người dùng ngừng chạm vào nó.

Martin Booka Weser, András, Ah Lam, altosh, giải pháp không hoạt động khi ImageView cũng có onClickEvent. Giải pháp worawee.s và kcoppock (với ImageButton) yêu cầu nền, không có ý nghĩa gì khi ImageView không trong suốt.

Đây là phần mở rộng của AZ_ ý tưởng về bộ lọc màu.

class PressedEffectStateListDrawable extends StateListDrawable {

    private int selectionColor;

    public PressedEffectStateListDrawable(Drawable drawable, int selectionColor) {
        super();
        this.selectionColor = selectionColor;
        addState(new int[] { android.R.attr.state_pressed }, drawable);
        addState(new int[] {}, drawable);
    }

    @Override
    protected boolean onStateChange(int[] states) {
        boolean isStatePressedInArray = false;
        for (int state : states) {
            if (state == android.R.attr.state_pressed) {
                isStatePressedInArray = true;
            }
        }
        if (isStatePressedInArray) {
            super.setColorFilter(selectionColor, PorterDuff.Mode.MULTIPLY);
        } else {
            super.clearColorFilter();
        }
        return super.onStateChange(states);
    }

    @Override
    public boolean isStateful() {
        return true;
    }
}

sử dụng:

Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));

1

Tôi đã thử với:

<ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/get_started"
        android:src="@drawable/home_started"
        style="?android:borderlessButtonStyle"
        android:adjustViewBounds="true"
        android:clickable="true"
        android:elevation="5dp"
        android:longClickable="true" />

và điều này đã hiệu quả. Xin lưu ý trên dòng:style="?android:borderlessButtonStyle"


Điều này không hoạt động trong trường hợp đệm 0 và hình ảnh chiếm toàn bộ khu vực của chế độ xem.
nhà phát triển android

1

Tôi nghĩ cách dễ nhất là tạo một tệp XML mới. Trong trường hợp này, hãy gọi nó là "example.xml" trong thư mục có thể vẽ và đặt mã sau:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/blue"
          android:state_pressed="true" />

</selector>

Nhưng trước đó bạn phải đặt màu trong tệp color.xml, trong thư mục giá trị, như sau:

<resources>
    <color name="blue">#0000FF</color>
</resources>

Điều đó được thực hiện, bạn chỉ cần đặt Nút / ImageButton để sử dụng bố cục mới, như sau:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/example"
/>

Sau đó, khi bạn nhấp vào hình ảnh đó, nó sẽ thay đổi thành màu được đặt trong

<item android:drawable="@color/blue"
      android:state_pressed="true" />

đưa ra phản hồi mà bạn muốn ...


1

Đây là giải pháp tốt nhất mà tôi từng thấy. Nó chung chung hơn.

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true" >

    <alpha
        android:duration="100"
        android:fromAlpha="0.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toAlpha="1.0" />
</set>

2
Nên tiêm ở đâu và tập nào?
DmitryBoyko

0

Tôi đã làm như sau trong XML - với 0 đệm xung quanh hình ảnh và gợn sóng trên đầu hình ảnh:

<ImageView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@drawable/my_image"
    android:clickable="true"
    android:focusable="true"
    android:src="?android:attr/selectableItemBackground" />


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.