Android imageview更改色调以模拟按钮单击

Posted

技术标签:

【中文标题】Android imageview更改色调以模拟按钮单击【英文标题】:Android imageview change tint to simulate button click 【发布时间】:2012-06-21 03:40:40 【问题描述】:

我有一个图像视图,我在其上设置了从 url 获取的位图。 在 imageview 上,我设置了一个 onClickListener,它会打开一个对话框。

我想在按下 imageview 时以某种方式更改色调(使其更暗)以提供一种按钮点击的感觉。

你有什么建议?

【问题讨论】:

【参考方案1】:

happydude 的回答是处理这个问题的最优雅的方式,但不幸的是(正如 cmets 中所指出的)ImageView 的源代码只接受一个整数(纯色)。 Issue 18220 已经存在了几年来解决这个问题,我在那里发布了一个解决方法,我将在这里总结一下:

扩展 ImageView 并使用根据新状态设置色调的代码包装 drawableStateChanged():

TintableImageView.java

package com.example.widgets;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.support.v7.widget.AppCompatImageView;

import com.example.R;

public class TintableImageView extends AppCompatImageView 

    private ColorStateList tint;

    public TintableImageView(Context context) 
        super(context);
    

    public TintableImageView(Context context, AttributeSet attrs) 
        super(context, attrs);
        init(context, attrs, 0);
    

    public TintableImageView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    

    private void init(Context context, AttributeSet attrs, int defStyle) 
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintableImageView, defStyle, 0);
        tint = a.getColorStateList(R.styleable.TintableImageView_tintColorStateList);
        a.recycle();
    

    @Override
    protected void drawableStateChanged() 
        super.drawableStateChanged();
        if (tint != null && tint.isStateful())
            updateTintColor();
        

    private void updateTintColor() 
        int color = tint.getColorForState(getDrawableState(), 0);
        setColorFilter(color);
    


定义一个自定义属性:

attrs.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources>

    <declare-styleable name="TintableImageView">
        <attr name="tintColorStateList" format="reference|color" />
    </declare-styleable>

</resources>

将小部件和自定义属性与您的本地命名空间一起使用,而不是 Android 的:

example_layout.xml

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_
    android:layout_
    android:orientation="horizontal">

    <com.example.widgets.TintableImageView
        android:layout_
        android:layout_
        android:src="@drawable/example"
        android:clickable="true"
        app:tintColorStateList="@color/color_selector"/>

</LinearLayout>

然后您可以使用如 happydude 建议的颜色选择器:

color_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/pressed_color"/>
    <item android:color="#00000000"/>
</selector>

【讨论】:

我正在尝试您的解决方案,但是当TintableImageView 中的构造函数调用它的超级时仍然得到java.lang.NumberFormatException: Invalid int: "@2130837701"...我需要通过new int[]R.styleable.TintableImageView_tint 因为obtainStyledAttributes 要求一个数组,并在 colors.xml 中声明 &lt;drawable name="tab_icon_selector"&gt;@drawable/tab_icon_selector&lt;/drawable&gt; 以便能够从 android:tint 引用它 这就是我的答案在 attrs.xml 中定义自定义色调属性的原因。您必须在布局中使用自定义 app:tint 而不是 android:tint。本质上,您正在创建一个新属性,该属性包装原生属性并一次为其提供一种颜色。 感谢您的回答!我已更改为app:tint 并且异常消失了...但是仍然没有使用选择器,即我的图标一直是黑色的...是我在colors.xml中的可绘制声明正确的方法是吗? 请回答我关于 SO 的问题,以便我接受 ***.com/questions/19500039/… 我粘贴了您的代码并检查了所有内容,但它不起作用。【参考方案2】:

一种方法是使用ColorFilterColorStateList 的组合,其中包含按下按钮时的色调颜色。 res/color 目录中ColorStateList 的 xml 如下所示:

button_pressed.xml

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

    <item android:state_pressed="true" android:color="@color/pressed_color"/>
    <item android:color="#00000000"/>

</selector>

@color/pressed_color 是您的色调(应该是部分透明的)。然后在 ImageView 子类中,通过覆盖 drawableStateChanged() 来应用颜色。

@Override
protected void drawableStateChanged() 
    super.drawableStateChanged();

    ColorStateList list = getResources().getColorStateList(R.color.button_pressed);
    int color = list.getColorForState(getDrawableState(), Color.TRANSPARENT);
    setColorFilter(color);
    invalidate();

每当按钮的状态发生变化时,都会调用此代码并根据需要自动设置色调。

【讨论】:

我尝试了你的建议。它似乎没有做任何事情。使用调试器我注意到 drawableStateChanged() 方法没有在 onPress 上触发,但似乎只在 onClick 上触发。 嗯,我在上面的代码中看不到任何错误。根据定义,当按下状态发生变化时,应该调用该方法。我一直在我自己的代码中使用这个结构,它工作正常。作为测试,在您的 ImageView XML 中添加 android:tint="@color/pressed_color"。这应该为您的图像添加永久色调,因为它调用与上述代码相同的颜色过滤器设置方法。这样你至少可以排除你选择的颜色有问题。 对不起,我很笨。您可以直接将您的颜色状态列表添加到您的ImageView XML 文件中。请参阅上面的编辑。 好的。所以这是当我设置 android:tint="@drawable/button_pressed" 时出现的错误,我在编译期间收到此错误,06-19 20:22:54.222: E/AndroidRuntime(2338): Caused by: java. lang.NumberFormatException:无法将“res/drawable/button_pressed.xml”解析为整数 06-19 20:22:54.222: E/AndroidRuntime(2338): at java.lang.Integer.parse(Integer.java:383) 06 -19 20:22:54.222: E/AndroidRuntime(2338): 在 java.lang.Integer.parseInt(Integer.java:372) 06-19 20:22:54.222: E/AndroidRuntime(2338): 在 com.android .internal.util.XmlUtils.convertValueToInt(XmlUtils.java:12s) 首先,请忽略“编辑”。我查看了源代码,果然tint 只接受纯色。很抱歉让你走错了路。其次,我在我创建的自定义ImageView 中尝试了上面原始帖子中的代码,它对我有用。我通过使用setImageResource(int) 设置图像对其进行了测试,但我不明白为什么其他图像设置方法不起作用。最后,确保在您的 XML 定义中添加android:clickable="true"。如果没有这条线,它将无法工作。【参考方案3】:

我必须对其进行测试,但您应该能够将具有该行为的 xml 设置为 ImageView 可绘制对象,然后将您的位图设置为 ImageView 背景。

【讨论】:

【参考方案4】:

对我来说,一个简单的解决方案是有效的,在 onClick 事件中使用 setAlpha(180) 会使图像变暗,给用户一个点击或触摸的反馈。

final ImageView myImage = (ImageView) findViewById(R.id.ivDocument);
myImage.setImage...(... your image ...); // load your ImageView
myImage.setClickable(true);
myImage.setFocusable(true);
myImage.setOnClickListener(new OnClickListener() 
    @Override
    public void onClick(View v) 
        myImage.setAlpha(180);
        doWhateverYouWantHere(v);
    
);

关于你的 XML 布局,没什么特别的。

【讨论】:

【参考方案5】:

这段代码 sn-p 为我工作:

porterDuffColorFilter = newPorterDuffColorFilter(getResources().getColor(R.color.cardview_dark_background),PorterDuff.Mode.MULTIPLY);

imgView.getDrawable().setColorFilter(porterDuffColorFilter);
imgView.setBackgroundColor(Color.TRANSPARENT);

【讨论】:

以上是关于Android imageview更改色调以模拟按钮单击的主要内容,如果未能解决你的问题,请参考以下文章

GridLayout中的ImageViews

在 Android 中以编程方式更改 ImageView 的图像

更改 Java Android Widget 中 ImageView 的 xml 值 android:layout_marginStart

按钮上的透明色调

根据状态更改 UIButton 中 ImageView 的 tint 颜色

摆脱 UITableViewCell 中 UIButton 上的 imageView 色调