Ho imageview nella mia app Android che sto usando come un pulsante con l'evento onClick dato, ma come puoi immaginare non dà a imageview un effetto cliccabile quando cliccato. Come posso ottenerlo?
Ho imageview nella mia app Android che sto usando come un pulsante con l'evento onClick dato, ma come puoi immaginare non dà a imageview un effetto cliccabile quando cliccato. Come posso ottenerlo?
Risposte:
È possibile progettare immagini diverse per gli stati cliccato / non cliccato e impostarle in onTouchListener come segue
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;
}
});
La scelta migliore è definire un selettore come segue
<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>
e seleziona l'immagine nell'evento:
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
mantenere l'immagine visibile finché stiamo premendo.
setOnTouchListener(...
. Puoi semplicemente creare <selector ...>
e quindi impostare ImageView cliccabile in XML come<ImageView ... android:clickable="true" android:focusable="true" android:src="@drawable/my_selector" />
Puoi farlo con una singola immagine usando qualcosa del genere:
//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;
}
});
Probabilmente lo trasformerò in una sottoclasse di ImageView (o ImageButton in quanto è anche una sottoclasse di ImageView) per una più facile riutilizzabilità, ma questo dovrebbe consentire di applicare un aspetto "selezionato" a un'immagine.
false
, altrimenti l' onClick()
evento effettivo della visualizzazione non verrà attivato
È possibile fare con un solo file immagine utilizzando il metodo ColorFilter. Tuttavia, ColorFilter si aspetta di lavorare con ImageViews e non con i pulsanti, quindi devi trasformare i tuoi pulsanti in ImageViews. Questo non è un problema se stai comunque usando le immagini come pulsanti, ma è più fastidioso se hai del testo ... Comunque, supponendo che tu trovi un modo per aggirare il problema con il testo, ecco il codice da usare:
ImageView button = (ImageView) findViewById(R.id.button);
button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
Ciò applica una sovrapposizione rossa al pulsante (il codice colore è il codice esadecimale per il rosso completamente opaco - le prime due cifre sono trasparenti, quindi è RR GG BB.).
EDIT : Sebbene la risposta originale di seguito funzioni ed è facile da configurare, fare riferimento a questo post di un Android Developer Advocate di Google se si desidera / è necessaria un'implementazione più efficiente. Si noti inoltre che l' android:foreground
attributo arriva a tutte le visualizzazioni , incluso ImageView, per impostazione predefinita in Android M.
Il problema con l'utilizzo di un selettore per un ImageView è che puoi solo impostarlo come sfondo della vista: finché l'immagine è opaca, non vedrai l'effetto del selettore dietro di essa.
Il trucco è racchiudere il tuo ImageView in un FrameLayout con l'attributo android:foreground
che ci permette di definire una sovrapposizione per il suo contenuto. Se impostiamo android:foreground
un selettore (ad es. ?android:attr/selectableItemBackground
Per il livello API 11+) e OnClickListener
colleghiamo al FrameLayout invece che a ImageView, l'immagine verrà sovrapposta al disegnabile del nostro selettore - l'effetto clic che desideriamo!
Ecco:
<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>
(Nota che questo dovrebbe essere inserito nel layout genitore.)
final View imageButton = findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
// do whatever we wish!
}
});
selectableItemBackground
attributo è stato aggiunto solo nel livello API 11, quindi è necessario utilizzare un altro selettore se si desidera utilizzare questa soluzione per i livelli API precedenti. Ad esempio, per una delle mie applicazioni che supporta il livello API 7, utilizzo la @drawable/list_selector_holo_light
risorsa generata utilizzando lo strumento Android Holo Colors Generator .
<ImageButton>
con selectableItemBackground!
Usa style = "? Android: borderlessButtonStyle" nel file XML. Mostrerà l'effetto clic predefinito di 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"
per annullare il riempimento.
style="?android:attr/borderlessButtonStyle"
: developer.android.com/guide/topics/ui/controls/…
style="?android:actionButtonStyle"
per un ImageView selezionabile su una ActionBar o ToolBar.
Usa semplicemente un ImageButton .
Ecco il mio modo semplice per risolverlo:
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);
});
Nel file 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>
Imposta lo sfondo selezionabile su ImageView e aggiungi un po 'di riempimento. Quindi allegare il file 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"/>
Per definire la scelta disegnabile del selettore
<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>
Devo usare android: state_pressed invece di 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>
Se vuoi ondeggiare quando viene toccato, può essere dato da questo codice:
<ImageView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</ImageView>
Allo stesso modo, puoi implementare l'effetto clic per TextView
<TextView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</TextView>
Puoi provare con android:background="@android:drawable/list_selector_background"
per ottenere lo stesso effetto di "Aggiungi sveglia" nella "Sveglia" predefinita (ora Orologio da tavolo).
Questo ha funzionato per me:
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: come ha detto Gunhan, ci sarà un problema di compatibilità con le versioni precedenti con il metodo setImageAlpha. Ho usato questo metodo:
public static void setImageAlpha(ImageView img, int alpha)
{
if(Build.VERSION.SDK_INT > 15)
{
img.setImageAlpha(alpha);
}
else
{
img.setAlpha(alpha);
}
}
Faccio alcune cose simili Vedi adatto a te o no
Visualizza Press Effect Helper:
utilizzo: esegui alcuni semplici effetti di stampa come iOS
Utilizzo semplice:
ImageView img = (ImageView) findViewById (R.id.img);
In combinazione con tutte le risposte precedenti, volevo che ImageView venisse premuto e cambiasse stato, ma se l'utente si spostava, "annulla" e non esegue un onClickListener.
Ho finito per creare un oggetto Point all'interno della classe e impostare le sue coordinate in base a quando l'utente ha premuto su ImageView. Su MotionEvent.ACTION_UP ho registrato un nuovo punto e ho confrontato i punti.
Posso solo spiegarlo così bene, ma ecco cosa ho fatto.
// 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;
}
});
Ho un onClickListener impostato su imageView, ma questo può essere un metodo.
MotionEvent.ACTION_CANCEL
con la stessa funzionalità di MotionEvent.ACTION_UP
allora è possibile "svuotare" la vista se l'utente esegue un "trascinamento" che non è un'azione di clic.
Puoi eseguire l'override setPressed
in ImageView e filtrare i colori lì, invece di creare listener 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();
}
}
Sulla base della risposta del signor Zorn , utilizzo un metodo statico nella mia classe di utilità astratta:
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;
}
};
}
...
}
Quindi lo uso con 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)
È molto semplice se si hanno molte immagini e si desidera un semplice effetto onTouch, senza alcun disegno XML e una sola immagine.
Usa un android.widget.Button
e imposta la sua background
proprietà su un android.graphics.drawable.StateListDrawable
. Tutto questo può essere fatto in XML o in modo programmatico. Vedi la sezione Pulsante personalizzato del tutorial Form Stuff .
Creo un campione qui , basta cambiare ImageView in ClickableImageView dal tuo layout. Spero che aiuti.
Penso che ImageButton sia una soluzione migliore
<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" />
Ho una soluzione più bella se usi immagini di sfondo :)
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;
}
});
}
O:
Puoi usare questo modulo, con il pulsante immagine.
Crea file 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>
E 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"
/>
La tua immagine cambia con un clic e puoi regolarla con un layout lineare:
<?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>
Ecco la mia soluzione, che, utilizzando la libreria " nineOldAndroids ", supporta anche le vecchie 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;
}
});
Presume che rootView sia la cella stessa (il layout) e che abbia una singola imageView che desideri sia influenzata dal colore che desideri applicare all'intera cella.
EDIT: se lo desideri, puoi anche estendere ImageView per gestire il primo piano e impostarlo su "? Android: attr / selectableItemBackground". C'è una libreria per questo qui e un tutorial su come farlo per qualsiasi visualizzazione desideri, qui .
Grazie per l'aiuto su questo thread. Tuttavia, ti sei perso una cosa ... devi gestire anche ACTION_CANCEL. Se non lo fai, potresti non ripristinare correttamente il valore alfa di ImageView nel caso in cui una vista principale nella gerarchia della vista intercetti un evento di tocco (pensa a ScrollView che avvolge ImageView).
Ecco una classe completa che si basa sulla classe precedente ma si occupa anche di ACTION_CANCEL. Utilizza una classe helper ImageViewCompat per astrarre le differenze nell'API JellyBean pre-post.
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();
}
}
Ecco il mio codice. L'idea è che ImageView ottenga il filtro del colore quando l'utente lo tocca e il filtro del colore viene rimosso quando l'utente smette di toccarlo.
Martin Booka Weser, András, Ah Lam, altosh, la soluzione non funziona quando ImageView ha anche onClickEvent. La soluzione worawee.s e kcoppock (con ImageButton) richiede uno sfondo, che non ha senso quando ImageView non è trasparente.
Questa è l'estensione dell'idea AZ_ sul filtro colore.
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;
}
}
utilizzo:
Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));
Ho provato con:
<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" />
e questo ha funzionato. Si prega di notare sulla linea:style="?android:borderlessButtonStyle"
Penso che il modo più semplice sia creare un nuovo file XML. In questo caso, chiamiamolo "example.xml" nella cartella drawable e inseriamo il seguente codice:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blue"
android:state_pressed="true" />
</selector>
Ma prima devi impostare i colori nel file colors.xml, nella cartella dei valori, in questo modo:
<resources>
<color name="blue">#0000FF</color>
</resources>
Ciò fatto, è sufficiente impostare il pulsante / pulsante immagine per utilizzare il nuovo layout, in questo modo:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/example"
/>
Quindi, quando fai clic su quell'immagine, cambierà nel colore impostato in
<item android:drawable="@color/blue"
android:state_pressed="true" />
dando il feedback che desideri ...
Questa è la migliore soluzione che abbia mai visto. È più generico.
<?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>
Ho fatto quanto segue in XML, con 0 riempimento intorno all'immagine e increspatura sopra l'immagine:
<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" />
Per ora, dovremmo sviluppare la pratica del Material Design . In questo caso potresti aggiungere un effetto a catena su un ImageView.
Basta aggiungere l'attributo XML, android: clickable = "true" ...