У меня есть изображение в моем приложении для Android, которое я использую как кнопку с заданным событием onClick, но, как вы могли догадаться, при нажатии на изображение не появляется интерактивный эффект. Как я могу этого добиться?
У меня есть изображение в моем приложении для Android, которое я использую как кнопку с заданным событием onClick, но, как вы могли догадаться, при нажатии на изображение не появляется интерактивный эффект. Как я могу этого добиться?
Ответы:
Вы можете создавать разные изображения для состояний с щелчком / без щелчка и устанавливать их в 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 ...>
а затем установить ImageView интерактивным в XML, например<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) для упрощения повторного использования, но это должно позволить вам применить «выбранный» вид к просмотру изображения.
false
, иначе фактическое onClick()
событие представления не будет запущено
С помощью метода ColorFilter можно сделать только один файл изображения . Однако ColorFilter рассчитывает работать с ImageView, а не с кнопками, поэтому вам нужно преобразовать свои кнопки в ImageView. Это не проблема, если вы все равно используете изображения в качестве кнопок, но еще больше раздражает, если у вас есть текст ... В любом случае, если вы найдете способ обойти проблему с текстом, вот код, который нужно использовать:
ImageView button = (ImageView) findViewById(R.id.button);
button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
При этом к кнопке применяется красный оверлей (цветовой код - это шестнадцатеричный код для полностью непрозрачного красного цвета - первые две цифры обозначают прозрачность, затем RR GG BB.).
РЕДАКТИРОВАТЬ : Хотя исходный ответ ниже работает и его легко настроить, обратитесь к этому сообщению адвоката разработчика Android в Google, если вы хотите / нуждаетесь в более эффективной реализации. Также обратите внимание на то, что android:foreground
атрибут применяется ко всем представлениям , включая ImageView, по умолчанию в Android M.
Проблема с использованием селектора для 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!
Используйте style = "? Android: borderlessButtonStyle" в XML-файле. Он покажет эффект щелчка по умолчанию 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/…
style="?android:actionButtonStyle"
для интерактивного ImageView на ActionBar или ToolBar.
Просто используйте ImageButton .
Вот мой простой способ решить эту проблему:
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>
Если вы хотите, чтобы при касании появлялась рябь, ее можно задать с помощью этого кода:
<ImageView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</ImageView>
Точно так же вы можете реализовать эффект щелчка для TextView
<TextView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</TextView>
Вы можете попытаться 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: Как сказал Гунхан, с методом 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;
}
});
У меня есть onClickListener, установленный в imageView, но это может быть метод.
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();
}
}
Основываясь на ответе г-на Зорна , я использую статический метод в своем абстрактном классе 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-файлов и только одно изображение.
Используйте android.widget.Button
и установите для его background
свойства значение android.graphics.drawable.StateListDrawable
. Все это можно сделать в 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 в том случае, если родительское представление в иерархии представлений перехватит событие касания (подумайте, что ScrollView обертывает вас ImageView).
Вот полный класс, который основан на вышеупомянутом классе, но также заботится о ACTION_CANCEL. Он использует вспомогательный класс ImageViewCompat для абстрагирования различий в API JellyBean до публикации.
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 получает цветной фильтр, когда пользователь прикасается к нему, и цветной фильтр удаляется, когда пользователь перестает касаться его.
Martin Booka Weser, András, Ah Lam, altosh, решение не работает, если ImageView также имеет onClickEvent. Для решения worawee.s и kcoppock (с ImageButton) требуется фон, который не имеет смысла, когда ImageView не является прозрачным.
Это расширение идеи AZ_ о цветном фильтре.
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-файл. В этом случае назовем его "example.xml" в папке с возможностью переноса и вставим следующий код:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blue"
android:state_pressed="true" />
</selector>
Но перед этим вы должны установить цвета в файле colors.xml, в папке значений, например:
<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 я сделал следующее - с 0 отступом вокруг изображения и рябью поверх изображения:
<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" />
А пока нам нужно развивать практику Material Design . В этом случае вы можете добавить эффект ряби на ImageView.
Просто добавьте атрибут XML, android: clickable = "true" ...