Почему это не работает иногда?
TL; DR У меня много кнопок, и я обмениваю их изображения. По какой-то причине мой код работает только на некоторых телефонах, а не на других.
Мое приложение использует следующий код для сравнения изображений на кнопках с изображениями:
onCreate
:
redsquare = getResources().getDrawable(R.drawable.redsquare);
bitred = ((BitmapDrawable) redsquare).getBitmap();
onClick
(v
нажата кнопка)
ClickGround = v.getBackground(); //Get the background of button clicked
//the bitmap background of the button clicked
BitClick = ((BitmapDrawable) ClickGround).getBitmap();
Затем, позже в onClick, я проверю, нажал ли пользователь на redSquare, выполнив следующее:
if (BitClick == bitred) { //Make sure it is the red square that user clicked
}
Я тестировал его на своем эмуляторе и телефоне HUAWEI, и он отлично работает. Когда я тестировал его на другом телефоне (lg g3), оператор if не проходит. Почему результаты разные? Является ли изображение каким-то образом испорченным в моем телефоне?
Ответы
Ответ 1
Вы можете, я делаю небольшое изменение в вашем коде сравнения, чтобы он работал со всеми устройствами.
Bitmap BitRed = ((BitmapDrawable)getResources().getDrawable(R.drawable.redsquare)).getBitmap();
Bitmap BitClick = ((BitmapDrawable) v.getBackground()).getBitmap();
if (BitClick.sameAs(BitRed))
{
//Your Button with Red Square Clicked
}
Подробнее см. SameAs.
Надеюсь, это поможет вам.
Ответ 2
Прежде всего, Resources.getDrawable(int)
устарел. Вероятно, это не связано с вашей проблемой, но вы должны это исправить.
Если вы сравниваете растровые изображения с помощью ==
, вы сравниваете идентификаторы объектов. Если тест ==
дает вам false
, это означает, что вы сравниваете разные объекты. В этом нет никаких сомнений.
Ваши фрагменты не дают достаточного контекста, чтобы убедиться, но вот некоторые возможности:
-
Что-то в вашем коде вызывает присвоение другого значения bitred
.
-
Идентификаторы bitred
в двух фрагментах кода не обозначают одну и ту же переменную Java.
-
Ваше предположение, что "красное" растровое изображение, которое используется в качестве красного фона, всегда будет одним и тем же объектом.
Предположим, что вы уже устранили 1. и 2. выше и сосредоточьтесь на 3. Как это могло произойти? Ну, мы не можем видеть соответствующий код (где вы случайно меняете изображения кнопок), но я могу представить несколько возможностей:
- Вы можете многократно извлекать растровое изображение из
Resources
.
- Метод, который вы вызываете для переключения растровых изображений, может создавать/устанавливать копию.
- Метод, который вы вызываете для получения растрового изображения с нажатой кнопкой, может возвращать копию.
И поскольку каждая из вышеперечисленных операций может зависеть от реализаций API, которые могут вести себя по-другому (поскольку javadoc позволяет это) поведение вашего приложения может быть зависимым от платформы.
Итак, каково решение?
Гипотетически, если вы можете понять, что вызывает различные объекты растровых изображений, вы можете потенциально обойти его. Однако, хотя ваш код по-прежнему зависит от неуказанного поведения, существует риск того, что он сломается на других телефонах...
Лучшим решением является изменение вашего приложения, чтобы он не полагался на использование ==
для сравнения объектов Bitmap
. Например:
-
Свяжите тег с каждой кнопкой.
button1.setTag("one");
button2.setTag("two");
-
Создайте HashMap
, который отображает от тега кнопки текущий цвет для этой кнопки. HashMap является частью состояния модели приложения.
Map colors = new HashMap();
...
colors.put("one", "red");
colors.put("two", "blue");
-
При изменении растровых изображений изображений для кнопок сделайте соответствующее обновление на карте.
// After swap the images of button1 and button2 ...
String c1 = colors.get("one");
String c2 = colors.get("two");
colors.put("one", c2);
colors.put("two", c1);
-
В методе onClick используйте карту, чтобы найти текущий цвет кнопки, а не пытаться понять ее, сравнив объекты Bitmap
.
if (colors.get(v.getTag()).equals("red")) {
// it is red!
}
(Обратите внимание, что это близко к тому, что предлагает Биджу Парвати, но он не сказал явно, как обращаться с цветами кнопок/изображениями.)
Ответ 3
Прежде всего Resources.getDrawable(int)
устарел, поэтому вы наверняка получите такие проблемы на некоторых более новых устройствах. Лучше всего использовать теги для вашей кнопки для каждой выталкиваемой вами комбинации для этой конкретной кнопки. Например, рассмотрим, что у вас есть 4 кнопки, то есть кнопка1, кнопка2, кнопка3 и кнопка4. Теперь предположим, что инициалы у всех есть некоторый фон defualt.
Допустим,
button1.setBackgroundResource(R.drawable.default1);
button1.setTag(R.drawable.default1); // set the tag for button same as the drawable id
Сделайте то же самое для всех ваших 4 кнопок
button4.setBackgroundResource(R.drawable.default4);
button4.setTag(R.drawable.default4); // set the tag for button same as the drawable id
Теперь каждый раз, когда вы меняете фон/изображения для своих кнопок, вам нужно также обновить тег, что-то вроде этого
button1.setBackgroundResource(R.drawable.redimage);
button1.setTag(R.drawable.redimage); // set the tag for button same as the drawable id
и на ваших кнопках onClick()
вам нужно просто использовать случай переключения, чтобы различать разные теги
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button1:
switch(button1.getTag()){
case R.drawable.default1:
// do whatever action you want to perform
break;
case R.drawable.redimage:
// do whatever action you want to perform
break;
}
break;
// similarly you can do the same for rest of the buttons.
}
}
Надеюсь, что это поможет.