奇怪View.getHitRect()行为

问题描述:

我有一个简单的布局:奇怪View.getHitRect()行为

​​3210

,并在我的活动,我改变了y位置后打印按钮的命中RECT:

public class MainActivity extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
} 

public void animate(View view) { 
    printHitRect(); 
    findViewById(R.id.button1).setY(50); 
    printHitRect(); 
} 
private void printHitRect() { 
    Rect rect = new Rect(); 
    findViewById(R.id.button1).getHitRect(rect); 
    Log.d(">>button1 hit rect", rect.flattenToString()); 
} 
} 

预期的输出

button1的命中RECT:0 0 116 72

button1的击中RECT:0 50 116 122

实际输出

button1的击中RECT: 0 0 116 72

Button1的命中RECT:-58 14 58 86

有人能解释这个输出,我是不是做错了什么或者是一个错误吗?基本上我在我的自定义ViewGroup中使用这个getHitRect()来检测哪个孩子用户已经触摸。有没有更好的方法让孩子在某个特定点上,可能是getChildAt(x, y)这样的功能?

而不是setY(),我试过setTranslateY()。我也使用NineOldAndroid库以及内置的动画框架。如果我使用findViewById(R.id.button1).animate().y(50)而不是setY(),则可以看到相同的行为。

UPDATE:

最后我用的是现在工作nineoldandroid库写入工具方法:

private static void getHitRect(View v, Rect rect) { 
    rect.left = (int) com.nineoldandroids.view.ViewHelper.getX(v); 
    rect.top = (int) com.nineoldandroids.view.ViewHelper.getY(v); 
    rect.right = rect.left + v.getWidth(); 
    rect.bottom = rect.top + v.getHeight(); 
} 

getHitRect()有一个bug,并且不会正确地应用转换。我们在内部修复了这个错误,并且修复程序将在下一个公开发布的Android中提供。

+8

因为这个答案在2013年7月19日提出,我假设你指到Android 4.3作为“下一个版本”。这是否意味着方法,getHitRect()在它之前的版本上不可靠? – Saket

+0

@Saket我会说这是一个公平的假设,因为我在这里有一个电话卡在4.1.2(Xperia S)上,并且我得到的y坐标没有太大意义,即底部和顶部 - 无赖因为该矩形函数会为我节省很多痛苦... – AgentKnopf

+0

@Zainodis查看OP的更新。该方法应该工作得很好:) – Saket

可以得到击中RECT通过这种方式:

public Rect getHitRect(View child){ 
    Rect frame = new Rect(); 
    frame.left = child.getLeft(); 
    frame.right = child.getRight(); 
    frame.top = child.getTop(); 
    frame.bottom = child.getBottom(); 
    return frame; 
} 
+0

这不起作用child.getLeft()返回错误的值,提问者使用nineoldandroid写的解决方案的工作 – 2cupsOfTech

这里是一个不依赖于NineOldAndroids的解决方案。

如果按照NineOldAndroids代码路径的代码路径你最终在这里交的蜂窝设备:Github

private static void getHitRect(View v, Rect rect) { 
    rect.left = (int) (v.getLeft() + v.getTranslationX()); 
    rect.top = (int) (v.getTop() + v.getTranslationY()); 
    rect.right = rect.left + v.getWidth(); 
    rect.bottom = rect.top + v.getHeight(); 
} 
+0

好的解决方案,我只需要添加小的校准'rect.top - = dividerValue/2; rect.bottom + = dividerValue/2;'当在listview中的项目之间使用更宽的分隔符时,有很多错过的触摸检测。 – LadyWoodi