如何在聚焦或点击时突出显示ImageView?

时间:2010-11-15 15:34:36

标签: android focus imageview highlight

这方面的一个很好的例子是在Twitter启动屏幕(首次启动应用程序时看到的带有大图标的屏幕),或者甚至只是在关注应用程序图标时查看应用程序托盘。

基本上我需要突出显示一个ImageView,其中高光轮廓与ImageView中的图像轮廓相似,看起来它是该图像的边框。我还想自定义高光,使其成为一种特定的颜色,并使其淡出。

谢谢,

groomsy

10 个答案:

答案 0 :(得分:80)

您需要为src分配一个状态列表drawable的ImageView属性。换句话说,该状态列表将具有用于选择,按下,未选择等的不同图像 - 这就是Twitter应用程序如何做到的。

所以如果你有一个ImageView:

<ImageView style="@style/TitleBarLogo"
            android:contentDescription="@string/description_logo"
            android:src="@drawable/title_logo" />

src drawable(title_logo.xml)如下所示:

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

Google IO Schedule app就是一个很好的例子。

答案 1 :(得分:25)

如果您没有其他可用状态,您可以使用setColorFilter来获得简单的色调效果。

它的行为就像按下状态选择器一样,所以当按下图像时,它会将背景变为浅灰色。

final ImageView image = (ImageView) findViewById(R.id.my_image);
image.setOnTouchListener(new View.OnTouchListener() {
        private Rect rect;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                image.setColorFilter(Color.argb(50, 0, 0, 0));
                rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
            }
            if(event.getAction() == MotionEvent.ACTION_UP){
                image.setColorFilter(Color.argb(0, 0, 0, 0));
            }
            if(event.getAction() == MotionEvent.ACTION_MOVE){
                if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
                    image.setColorFilter(Color.argb(0, 0, 0, 0));
                } 
            }
            return false;
        }
    });

它处理在视图边界之外移动手指,因此如果它发生,它将恢复默认背景。

当您想支持false时,从onTouch方法返回onClickListner非常重要。

答案 2 :(得分:2)

为了显示动态图像,您可以使用LayerDrawable作为图像源。

LayerDrawable d = new LayerDrawable(new Drawable[]{new BitmapDrawable(myBmp), getResources().getDrawable(R.drawable.my_selector_list)});
imageView.setImageDrawable(d);

答案 3 :(得分:2)

只有完成Josh Clemm的回答。您还可以维护src定义的相同图像,但仅更改或突出显示背景。这或多或少会像这样:

logo_box.xml

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

然后将按钮的背景定义为logo_box:

<ImageView
    android:contentDescription="@string/description_logo"
    android:src="@drawable/logo"
    android:background="@drawable/logo_box" />

其中background_normal和background_pressed可以像你想要的那样复杂,或者像@color一样简单:)

答案 4 :(得分:2)

我的解决方案,ImageView的自定义属性:
https://github.com/henrychuangtw/Android-ImageView-hover  

第1步:声明样式

<declare-styleable name="MyImageViewAttr">
    <attr name="hover_res" format="reference" />
</declare-styleable>


第2步:自定义ImageView

public class MyImageView extends ImageView {

int resID, resID_hover;

public MyImageView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
}
public MyImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub

    TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyImageViewAttr);
    resID_hover = array.getResourceId(R.styleable.MyImageViewAttr_hover_res, -1);
    if(resID_hover != -1){
        int[] attrsArray = new int[] {
                android.R.attr.src 
            };

        TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
        resID = ta.getResourceId(0 , View.NO_ID);           
        ta.recycle();

        setOnTouchListener(listener_onTouch);
    }

    array.recycle();

}
public MyImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
    TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyImageViewAttr);
    resID_hover = array.getResourceId(R.styleable.MyImageViewAttr_hover_res, -1);
    if(resID_hover != -1){
        int[] attrsArray = new int[] {
                android.R.attr.src 
            };

        TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
        resID = ta.getResourceId(0 , View.NO_ID);           
        ta.recycle();

        setOnTouchListener(listener_onTouch);
    }

    array.recycle();
}



OnTouchListener listener_onTouch = new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            setImageResource(resID_hover);
            break;

        case MotionEvent.ACTION_MOVE:

            break;

        case MotionEvent.ACTION_UP:
            setImageResource(resID);
            break;

        default:
            break;
        }


        return false;
    }
};

}


第3步:声明myattr:xmlns:myattr =&#34; http://schemas.android.com/apk/res-auto"在布局xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:myattr="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">


第4步:为myImageView设置myattr:hover_res

<dev.henrychuang.component.MyImageView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        myattr:hover_res="@drawable/icon_home_h"
        android:src="@drawable/icon_home"/>


答案 5 :(得分:2)

这是mklimek的扩展。我无法从他的片段中正常工作。我编辑了一下

 ImageView testImage = (ImageView)findViewById(R.id.imageView);
 testImage.setOnTouchListener(listener);

 View.OnTouchListener listener = new View.OnTouchListener() {
        private Rect rect;
        @Override
        public boolean onTouch(View v, MotionEvent event) {


            ImageView image = (ImageView) v;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    image.getDrawable().setColorFilter(0x77000000,PorterDuff.Mode.SRC_ATOP);
                    image.invalidate();                        
                    break;

                case MotionEvent.ACTION_UP:                        
                case MotionEvent.ACTION_CANCEL: {
                    //clear the overlay
                    image.getDrawable().clearColorFilter();
                    image.invalidate();
                    break;
                }
            }

            return true;
        }
    };

答案 6 :(得分:1)

我把小型图书馆放在一起应该有助于: https://github.com/noveogroup/Highlightify

基本上它在运行时创建选择器,它应该非常容易使用。 虽然,焦点状态尚未得到支持......

答案 7 :(得分:1)

我注意到一个可绘制的xml是不够的:

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

ImageView没有按下。您还应为ImageView分配OnClickListener。然后按下按钮。

答案 8 :(得分:0)

我正在将android:state_selected="true"用于 imageView的状态

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

    <item android:drawable="@drawable/ic_disable" android:state_selected="false" />

    <!--for default-->
    <item android:drawable="@drawable/ic_enable" />

</selector>

使用img_view.setSelected(true) OR img_view.setSelected(false) java / kotlin 代码更改图像状态。

答案 9 :(得分:0)

使用selectableItemBackground作为背景:

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