我在Android应用程序中使用了imageview,就像给定了onClick事件的按钮一样,但是您可能会猜测单击它时没有给imageview提供可点击的效果。我该如何实现?
Answers:
您可以为单击/未单击状态设计不同的图像,并在onTouchListener中进行如下设置
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;
}
});
更好的选择是按如下方式定义选择器
<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.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN);
return true;
}
});
MotionEvent.ACTION_DOWN || MotionEvent.ACTION_MOVE
我们按下时一直保持图像显示。
setOnTouchListener(...
。您可以简单地创建<selector ...>
,然后将XML中的ImageView设置为可点击,例如<ImageView ... android:clickable="true" android:focusable="true" android:src="@drawable/my_selector" />
您可以使用以下图像处理单个图像:
//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;
}
});
我可能会将其设置为ImageView的子类(或ImageButton也是ImageView的子类),以便更轻松地重用,但是这应允许您将“选定的”外观应用于imageview。
false
,否则视图的实际onClick()
事件将不会触发
使用ColorFilter方法可以只处理一个图像文件。但是,ColorFilter希望使用ImageViews而不是Buttons,因此您必须将按钮转换为ImageViews。如果您还是将图像用作按钮,这不是问题,但是如果您有文本,这会更令人讨厌...无论如何,假设您找到了解决文本问题的方法,请使用以下代码:
ImageView button = (ImageView) findViewById(R.id.button);
button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
这会将红色覆盖层应用于按钮(颜色代码是完全不透明的红色的十六进制代码-前两位数字是透明的,然后是RR GG BB。)。
编辑:尽管下面的原始答案有效并且易于设置,但是如果您想要/需要更有效的实现,请参阅Google的Android开发者倡导者的这篇文章。另请注意,默认情况下,Android M中的所有视图(包括ImageView)都具有该android:foreground
属性。
将选择器用于ImageView的问题在于,您只能将其设置为视图的背景-只要图像是不透明的,您就看不到选择器的效果。
诀窍是将ImageView包裹在具有属性的FrameLayout中,该属性android:foreground
使我们能够为其内容定义一个叠加层。如果我们设置android:foreground
一个选择器(例如,?android:attr/selectableItemBackground
针对API级别11+)并将其附加OnClickListener
到FrameLayout而不是ImageView,则图像将被我们选择器的drawable覆盖-我们想要的点击效果!
看哪:
<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>
(请注意,这应该放在您的父级布局中。)
final View imageButton = findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
// do whatever we wish!
}
});
selectableItemBackground
属性仅在API级别11中添加,因此如果要将此解决方案用于较早的API级别,则必须使用另一个选择器。例如,对于我的一个支持API级别7的应用程序,我使用@drawable/list_selector_holo_light
通过Android Holo Colors Generator工具生成的资源。
<ImageButton>
和selectableItemBackground来实现相同的行为!
在XML文件中使用style =“?android:borderlessButtonStyle”。它将显示Android默认的点击效果。
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
style="?android:borderlessButtonStyle"
/>
android:adjustViewBounds="true"
取消设置填充。
style="?android:attr/borderlessButtonStyle"
:developer.android.com/guide/topics/ui/controls/...
这是我解决此问题的简单方法:
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);
});
在文件中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>
将可选背景设置为ImageView并添加一些填充。然后附上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"/>
用于定义选择器可绘制的选择
<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>
我必须使用android:state_pressed而不是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>
您可以尝试使用与android:background="@android:drawable/list_selector_background"
默认“闹钟”(现在为桌面时钟)中的“添加闹钟”相同的效果。
这对我有用:
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:正如Gunhan所说,setImageAlpha方法将存在向后兼容性问题。我用这种方法:
public static void setImageAlpha(ImageView img, int alpha)
{
if(Build.VERSION.SDK_INT > 15)
{
img.setImageAlpha(alpha);
}
else
{
img.setAlpha(alpha);
}
}
我做了一些类似的事情,看是否适合你
查看新闻特效助手:
用法:做一些简单的新闻效果,例如iOS
简单用法:
ImageView img =(ImageView)findViewById(R.id.img);
结合以上所有答案,我希望按下并更改ImageView的状态,但是如果用户移动了,则“取消”并且不执行onClickListener。
我最终在类中制作了一个Point对象,并根据用户按下ImageView的时间设置了它的坐标。在MotionEvent.ACTION_UP上,我记录了一个新点并比较了这些点。
我只能解释得很好,但这就是我所做的。
// 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;
}
});
我在imageView上设置了onClickListener,但这可以是一种方法。
MotionEvent.ACTION_CANCEL
具有相同功能的大小写,MotionEvent.ACTION_UP
然后在用户执行不是单击操作的“拖动”操作时可以“清除”视图。
您可以覆盖setPressed
ImageView并在那里进行颜色过滤,而不是创建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();
}
}
基于Zorn先生的回答,我在抽象的Utility类中使用了静态方法:
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;
}
};
}
...
}
然后,将它与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)
如果您有很多图像,并且想要一个简单的onTouch效果,而没有任何XML可绘制对象,并且只有一个图像,这将非常简单。
我在这里创建示例,只需从布局中将ImageView更改为ClickableImageView。希望对您有所帮助。
我认为ImageButton是更好的解决方案
<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" />
如果您使用背景图片,我还有一个更美丽的解决方案:)
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;
}
});
}
要么:
您可以通过“图像”按钮使用此表单。
创建文件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"
/>
单击即可更改图像,并且可以使用线性布局进行调整:
<?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>
这是我的解决方案,它使用“ nineOldAndroids ”库也支持旧的API:
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;
}
});
它假定rootView是单元格本身(布局),并且它具有单个imageView,并且希望该颜色受希望应用于整个单元格的颜色的影响。
编辑:如果您愿意,还可以扩展ImageView来处理前景,并将其设置为“?android:attr / selectableItemBackground”。这里有一个用于此的库,以及关于如何针对您希望的任何视图执行此操作的教程,在此处。
感谢您对此线程的帮助。但是,您错过了一件事...您也需要处理ACTION_CANCEL。如果不这样做,则在视图层次结构中的父视图拦截触摸事件的情况下,您可能无法正确还原ImageView的Alpha值(以ScrollView封装ImageView)。
这是一个基于上述类的完整类,但还要注意ACTION_CANCEL。它使用ImageViewCompat帮助器类抽象出JellyBean API前后的差异。
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();
}
}
这是我的代码。这个想法是当用户触摸ImageView时会获得滤色器,而当用户停止触摸它时便会删除滤色器。
当ImageView也具有onClickEvent时,Martin Booka Weser,András,Ah Lam,altosh的解决方案不起作用。worawee.s和kcoppock(带有ImageButton)解决方案需要背景,当ImageView不透明时,这是没有意义的。
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;
}
}
用法:
Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));
我尝试了:
<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" />
这有效。请在行上注明:style="?android:borderlessButtonStyle"
我认为最简单的方法是创建一个新的XML文件。在这种情况下,我们在drawable文件夹中将其称为“ example.xml”,并输入以下代码:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blue"
android:state_pressed="true" />
</selector>
但是在此之前,您必须在values.xml文件的values文件夹中设置颜色,如下所示:
<resources>
<color name="blue">#0000FF</color>
</resources>
这样,您只需将Button / ImageButton设置为使用新的布局,如下所示:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/example"
/>
然后,当您单击该图像时,它将更改为在
<item android:drawable="@color/blue"
android:state_pressed="true" />
提供您想要的反馈...
这是我见过的最好的解决方案。它更通用。
<?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>
只需添加XML属性,android:clickable =“ true” ...