2013-07-19 1 views
10

() У меня есть простой макет:Странное поведение View.getHitRect

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

<Button 
    android:id="@+id/button1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Button" /> 

<Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:onClick="animate" 
    android:text="animate" /> 

</LinearLayout> 

и в моей деятельности я печать хит прямоугольник на кнопку после изменения y местоположение:

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 ударил прямоугольник: 0 50 116 122

фактический выход

Button1 ударил прямоугольник: 0 0 116 72

button1 удар Прямоугольник: -58 14 58 86

Может кто-то объяснить этот вывод, я делаю что-то неправильно, или это ошибка? В основном я использую этот getHitRect() в своем обычном ViewGroup, чтобы определить, к какому дочернему пользователю прикоснулся. Есть ли лучший способ получить ребенка в определенной точке, может быть функция вроде 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(); 
} 

ответ

8

getHitRect() была ошибка и не будет применяться прообразы должным образом. Мы исправили эту ошибку внутренне, и исправление будет доступно в следующей публичной версии Android.

+8

Поскольку этот ответ был сделан 19 июля 2013 года, я предполагаю, что вы имели в виду Android 4.3 как «следующий выпуск». Означает ли это, что метод, getHitRect() ненадежен в версиях до этого? – Saket

+0

@Saket Я бы сказал, что это справедливое предположение, поскольку у меня есть телефон, который застрял на 4.1.2 (Xperia S) и координаты y, которые я получаю, не имеют большого смысла, то есть нижний и верхний обломки, потому что эта функция rect я бы сэкономил много боли ... – AgentKnopf

+0

@ Zainodis См. обновление OP. Этот метод должен хорошо работать :) – Saket

2

Вы можете получить удар Прямоугольник по этому пути:

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() возвращает неправильное значение, решение, которое задавал автор вопроса, используя работы с девятидюймодами – 2cupsOfTech

1

Вот решение, которое не зависит от 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; 'как при использовании более широкого разделителя между элементами в списке, было много пропущенных обнаружений касаний. – LadyWoodi

Смежные вопросы