Comment puis-je donner un effet de clic imageview comme un bouton sur Android?
j'ai imageview dans mon application Android que j'utilise comme un bouton avec l'événement onClick donné, mais comme vous pouvez deviner qu'il ne donne pas imageview un effet cliquable lorsque cliqué. Comment puis-je y parvenir?
29 réponses
vous pouvez concevoir différentes images pour les États cliqué/Non cliqué et les mettre dans le onTouchListener comme suit
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;
}
});
le meilleur choix est que vous définissiez un sélecteur comme suit
<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>
et sélectionnez l'image dans l'événement:
v.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN);
return true;
}
});
vous pouvez faire cela avec une seule image en utilisant quelque chose comme ceci:
//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;
}
});
je vais probablement en faire une sous-classe D'ImageView (ou ImageButton car C'est aussi une sous-classe D'ImageView) pour une réutilisation plus facile, mais cela devrait vous permettre d'appliquer un look" sélectionné " à un imageview.
il est possible de faire avec juste un fichier image en utilisant la méthode ColorFilter. Cependant, ColorFilter s'attend à travailler avec ImageViews et non avec des boutons, vous devez donc transformer vos boutons en ImageViews. Ce n'est pas un problème si vous utilisez des images comme vos boutons de toute façon, mais c'est plus ennuyeux si vous aviez du texte... Quoi qu'il en soit, en supposant que vous trouviez un moyen de contourner le problème avec le texte, voici le code à utiliser:
ImageView button = (ImageView) findViewById(R.id.button);
button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
qui applique un superposer au bouton (le code de couleur est le code hexadécimal pour le rouge complètement opaque - les deux premiers chiffres sont la transparence, puis C'est RR GG BB.).
modifier : bien que la réponse originale ci-dessous fonctionne et est facile à configurer, se référer à ce post par un développeur Android Advocate chez Google si vous voulez / besoin d'une mise en œuvre plus efficace. Notez également que l'attribut android:foreground
est venant à toutes les vues , y compris ImageView, par défaut dans Android M.
le problème avec l'utilisation d'un sélecteur pour une vue D'image signifie que vous ne pouvez la définir qu'en tant qu'arrière - plan de la vue-tant que votre image est opaque, vous ne verrez pas l'effet du sélecteur derrière elle.
le truc est d'envelopper votre ImageView dans un FrameLayout avec l'attribut android:foreground
qui nous permet de définir un overlay pour son contenu. Si nous définissons android:foreground
à un sélecteur (par exemple ?android:attr/selectableItemBackground
pour le niveau API 11+) et attachez le OnClickListener
au FrameLayout à la place de L'ImageView, l'image sera superposée avec le drawable de notre sélecteur - l'effet de clic que nous désirons!
Voici:
<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>
(notez que ceci doit être placé dans votre mise en page mère.)
final View imageButton = findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
// do whatever we wish!
}
});
Utiliser style="?android: borderlessButtonStyle " dans le fichier XML. Il affichera L'effet de clic par défaut D'Android.
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
style="?android:borderlessButtonStyle"
/>
voici ma façon simple de résoudre cela:
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);
});
dans le fichier 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>
définit le fond sélectionnable à L'ImageView et ajoute du rembourrage. Joindre ensuite le 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"/>
pour définir le choix du sélecteur de traction
<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>
je dois utiliser android: state_pressed au lieu de 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>
je fais des choses similaires Voir adapté pour vous ou non
Afficher Appuyez Sur Effet Helper:
-
usage : certaines de presse simple effet comme iOS
Usage Simple:
-
ImageView img = (ImageView) findViewById (R. id.img);
- ViewPressEffectHelper.attach (img)
en combinaison avec toutes les réponses ci-dessus, je voulais que L'ImageView soit pressé et changé d'état mais si l'Utilisateur a bougé alors" annuler " et ne pas effectuer un onClickListener.
j'ai fini par créer un objet Point au sein de la classe et régler ses coordonnées en fonction du moment où l'Utilisateur a poussé vers le bas sur L'ImageView. Sur le MotionEvent.ACTION_UP I enregistre un nouveau point et compare les points.
je peux seulement l'expliquer si bien, Mais voici ce que Je l'ai fait.
// 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;
}
});
j'ai un onClickListener défini sur l'imageView, mais cela peut être une méthode.
vous pouvez outrepasser setPressed
dans L'ImageView et faire le filtrage de couleur là, au lieu de créer des auditeurs 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();
}
}
, Vous pouvez essayer avec android:background="@android:drawable/list_selector_background"
pour obtenir le même effet que le "Ajouter alarme" dans la valeur par défaut "réveil" (maintenant Réveil de bureau).
basé sur réponse de M. Zorn , j'utilise une méthode statique dans ma classe d'utilité abstraite:
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;
}
};
}
...
}
puis je l'utilise avec 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)
c'est très simple si vous avez beaucoup d'images, et que vous voulez un simple effet onTouch, sans aucun dessin XML et une seule image.
utilisez un android.widget.Button
, et mettez sa propriété background
à un android.graphics.drawable.StateListDrawable
. Tout cela peut se faire en XML ou par programmation. Voir la section du tutoriel "form Stuff .
cela a fonctionné pour moi:
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: comme Gunhan l'a dit, il y aura un problème de rétrocompatibilité avec la méthode setImageAlpha. J'ai utilisé cette méthode:
public static void setImageAlpha(ImageView img, int alpha)
{
if(Build.VERSION.SDK_INT > 15)
{
img.setImageAlpha(alpha);
}
else
{
img.setAlpha(alpha);
}
}
je crée l'échantillon ici , il suffit de changer ImageView en ClickableImageView de votre mise en page. Espérons qu'il l'aide.
j'ai un plus à la beauté de la solution si vous utilisez des images d'arrière-plan :)
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;
}
});
}
ou:
vous pouvez utiliser ce formulaire, avec le bouton Image.
Créer fichier 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>
et 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"
/>
votre image change d'un clic, et vous pouvez ajuster avec un layout linéaire:
<?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>
Merci pour l'aide sur ce fil. Cependant, vous avez raté un truc...vous devez gérer ACTION_CANCEL aussi. Si vous ne le faites pas, vous pourriez ne pas restaurer correctement la valeur alpha de ImageView dans le cas où une vue mère dans la hiérarchie de la vue intercepte un événement tactile (pensez à un ScrollView vous enveloppant D'ImageView).
Voici une classe complète qui est basée sur la classe ci-dessus mais qui s'occupe aussi de ACTION_CANCEL. Il utilise un assistant ImageViewCompat la classe de faire abstraction des différences dans la pré-post 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();
}
}
Voici mon code. L'idée est Qu'ImageView obtient le filtre couleur lorsque l'utilisateur le touche, et le filtre couleur est enlevé lorsque l'utilisateur arrête de le toucher.
Martin Booka Weser, András, Ah Lam, altosh, la solution ne fonctionne pas lors de l'ImageView a également onClickEvent. worawee.s et kcoppock (avec ImageButton) la solution nécessite un arrière-plan, qui n'a aucun sens lorsque ImageView n'est pas transparent.
celui-ci est le prolongement de AZ_ idée au sujet de la couleur du filtre.
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;
}
}
utilisation:
Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));
j'ai essayé avec:
<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" />
et ça a marché. S'il vous plaît noter sur la ligne: style="?android:borderlessButtonStyle"
je pense que la façon la plus facile est de créer un nouveau fichier XML. Dans ce cas, nous allons l'appeler "exemple.xml" dans le dossier à dessiner, et mettre dans le code suivant:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blue"
android:state_pressed="true" />
</selector>
Mais avant cela, vous devez définir les couleurs les couleurs.fichier xml, dans le dossier valeurs, comme ceci:
<resources>
<color name="blue">#0000FF</color>
</resources>
Que fait, vous venez de définir le bouton / ImageButton pour utiliser la nouvelle mise en page, comme ceci:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/example"
/>
puis quand vous cliquez que image, il va changer à la couleur définie dans
<item android:drawable="@color/blue"
android:state_pressed="true" />
donnant le feedback que vous voulez...
.C'est la meilleure solution que j'ai jamais vu. Son plus générique
<?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>
voici ma solution, qui, en utilisant " "nineOldAndroids "bibliothèque, prend en charge les vieux APIs aussi:
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;
}
});
il suppose que le rootView est la cellule elle-même (la mise en page), et qu'il a un imageView simple que vous souhaitez être affecté par la couleur que vous souhaitez appliquer à la cellule entière.
EDIT: si vous le souhaitez, vous pouvez également étendre ImageView pour gérer le premier plan, et "?android: attr / selectable itembackground". Il y a une bibliothèque pour ce ici et un tutoriel sur la façon de le faire pour toute vue que vous souhaitez, ici ".
si vous voulez ripple lorsque vous tapez, il peut être donné par ce code :
<ImageView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</ImageView>
de même, vous pouvez implémenter l'effet click pour TextView
<TextView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</TextView>
j'ai fait comme suit en XML-avec 0 padding autour de l'image et l'ondulation ontop de l'image:
<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" />
il suffit d'ajouter l'attribut XML , android:clickable=" true"...
comme pour l'instant, nous devrions développer conception du matériel pratique. Dans ce cas, vous pouvez ajouter un effet d'ondulation sur une ImageView.