为什么这有时不起作用?

时间:2016-01-06 04:39:14

标签: java android if-statement optimization bitmap

TL; DR我有很多按钮,我正在交换它们的图像。出于某种原因,我的代码仅适用于某些手机,而不适用于其他手机。

我的应用使用以下代码比较图像按钮上的图像:

onCreate

redsquare = getResources().getDrawable(R.drawable.redsquare);
bitred = ((BitmapDrawable) redsquare).getBitmap();

onClickv是单击的按钮)

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
}

我已经在我的模拟器和华为手机上测试过了,它运行正常。当我在另一部手机(LG g3)上测试时,if语句没有通过。为什么结果不同? 图片是否在某种程度上被搞砸了?

3 个答案:

答案 0 :(得分:11)

首先,Resources.getDrawable(int)deprecated。它可能与您的问题无关,但您应该修复它。

如果使用==比较位图,则表示您正在比较对象标识。如果==测试为您提供false,则表示您正在比较不同的对象。毫无疑问。

你的片段没有足够的背景来确定,但这里有一些可能性:

  1. 代码中的某些内容导致将不同的值分配给bitred

  2. 两段代码中的bitred标识符不表示相同的Java变量。

  3. 您认为用作红色背景的“红色”位图始终是相同的对象是无效的。

  4. 让我们假设您已经消除了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!
      }
      

    (请注意,这与Biju Parvathy所暗示的相近,但他没有明确如何处理按钮颜色/图像的变化。)

答案 1 :(得分:7)

你可以,我在比较代码中做了一些小改动,使其适用于所有设备。

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 :(得分:2)

首先,Resources.getDrawable(int)已被弃用,因此您肯定会在某些较新的设备中遇到此类问题。更好的方法是为每个可用于该特定按钮的drawable使用按钮的标签。例如,假设您有4个按钮,即button1,button2,button3和button4。现在假设首字母他们都有一些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.
    }
}

希望这有帮助。