Un bon exemple de cela est soit sur l'écran de lancement de Twitter (l'écran avec les grandes icônes qui est visible lorsque l'application est lancée pour la première fois) ou même simplement regarder le plateau d'application lorsque vous concentrez une icône d'application.
Fondamentalement, j'ai besoin de mettre en surbrillance une ImageView où la surbrillance contourne l'image dans ImageView et ressemble à une bordure de cette image. Je voudrais également personnaliser le surlignage pour qu'il soit d'une certaine couleur et pour qu'il disparaisse.
Merci,
groomy
Vous devez affecter l'attribut src
de ImageView
une liste d'états à dessiner. En d'autres termes, cette liste d'état aurait une image différente pour sélectionnée, pressée, non sélectionnée, etc. - c'est ainsi que l'application Twitter le fait.
Donc, si vous aviez une ImageView:
<ImageView style="@style/TitleBarLogo"
Android:contentDescription="@string/description_logo"
Android:src="@drawable/title_logo" />
Le src drawable (title_logo.xml) ressemblerait à ceci:
<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 en a un bon exemple.
Si vous n'avez pas d'autre dessinable pour l'état pressé, vous pouvez utiliser setColorFilter
pour obtenir un effet de teinte simple.
Il se comporte exactement comme le sélecteur d'état enfoncé, de sorte que lorsque vous appuyez sur l'image, l'arrière-plan devient gris clair.
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;
}
});
Il gère le déplacement du doigt en dehors des limites de la vue, donc s'il se produit, il restaure un arrière-plan par défaut.
Il est important de renvoyer false
à partir de la méthode onTouch
lorsque vous souhaitez également prendre en charge onClickListner
.
Il s'agit d'une extension de mklimek. Je ne pouvais pas le faire fonctionner correctement à partir de son extrait. J'ai un peu édité
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;
}
};
Pour afficher des images dynamiques, vous pouvez utiliser un LayerDrawable pour la source d'image.
LayerDrawable d = new LayerDrawable(new Drawable[]{new BitmapDrawable(myBmp), getResources().getDrawable(R.drawable.my_selector_list)});
imageView.setImageDrawable(d);
Seulement pour terminer la réponse de Josh Clemm. Vous pouvez également conserver la même image définie par src, mais modifier ou mettre en surbrillance uniquement l'arrière-plan. Cela ressemblerait plus ou moins à ceci:
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>
Et puis définir l'arrière-plan de votre bouton comme logo_box:
<ImageView
Android:contentDescription="@string/description_logo"
Android:src="@drawable/logo"
Android:background="@drawable/logo_box" />
Où background_normal et background_pressed peuvent être aussi complexes que vous le souhaitez, ou aussi simples qu'un @color :)
Ma solution, attribut personnalisé pour ImageView:
https://github.com/henrychuangtw/Android-ImageView-hover
Étape 1: déclarer-styleable
<declare-styleable name="MyImageViewAttr">
<attr name="hover_res" format="reference" />
</declare-styleable>
Étape 2: ImageView personnalisée
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;
}
};
}
Étape 3: déclarer myattr: xmlns: myattr = "http://schemas.Android.com/apk/res-auto" dans la mise en page 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">
Étape 4: définissez myattr: hover_res pour MyImageView
<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"/>
J'ai remarqué qu'un xml dessinable ne suffit pas:
<?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>
Une ImageView n'appuie pas. Vous devez également affecter un OnClickListener
pour une ImageView. Ensuite, il appuiera sur un bouton.
J'ai mis en place une petite bibliothèque qui devrait aider à cela: https://github.com/noveogroup/Highlightify
Fondamentalement, il crée un sélecteur lors de l'exécution et devrait être très facile à utiliser. Cependant, l'état concentré n'est pas encore pris en charge ...
J'utilise Android:state_selected="true"
Pour state of 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>
utilisez img_view.setSelected(true)
OU img_view.setSelected(false)
pour changer l'état de l'image dans Java/kotlin code .
Utilisez selectableItemBackground comme arrière-plan:
Android:background="?android:attr/selectableItemBackground"