뷰의 절대 좌표를 얻는 방법 레이아웃의 왼쪽 상단 모서리에 대한 이러한 값을

뷰의 왼쪽 상단 모서리의 절대 화면 픽셀 좌표를 얻으려고합니다. 그러나 모든 방법은 내가 같은 찾을 수 있습니다 getLeft()getRight()따라서 저를주고, 그들은 모두 뷰의 부모를 기준으로 한 것 같다대로 작동하지 않습니다 0. 이를 수행하는 올바른 방법은 무엇입니까?

도움이된다면, 이것은 ‘사진을 순서대로 되돌려 놓기’게임입니다. 사용자가 상자를 그려 여러 조각을 선택할 수 있기를 바랍니다. 내 가정은 그렇게 할 수있는 가장 쉬운 방법가 있다는 것이다 getRawX()getRawY()로부터 MotionEvent다음 조각을 들고 레이아웃의 왼쪽 상단 모서리에 대한 이러한 값을 비교한다. 조각의 크기를 알면 선택한 조각 수를 결정할 수 있습니다. 내가 사용할 수있는 실현 getX()하고 getY()MotionEvent,하지만 반환 조각이 더 어려운 선택 된 결정하게 상대 위치로. (불가능하지는 않지만, 불필요하게 복잡해 보입니다).

편집 : 이것은 질문 중 하나에 따라 보유 컨테이너의 크기를 얻는 데 사용했던 코드입니다. TableLayout퍼즐 조각을 모두 담는 테이블입니다.

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());

편집 2 : 제안 된 답변 중 더 많은 것을 따라 시도한 코드가 있습니다.

public int[] tableLayoutCorners = new int[2];
(...)

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
            + ", " + corners.bottom);

cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);

이 코드는 모든 초기화가 완료된 후에 추가되었습니다. 이미지가에 포함 된 ImageView 배열 (cells [] 배열)로 분할되었습니다 TableLayout. Cells [0]은 왼쪽 상단 ImageView이며 중간에 어딘가에 있으므로 [4] 셀을 선택했으며 좌표는 (0,0)이 아니어야합니다.

위에 표시된 코드는 여전히 로그에 0을 모두 제공합니다. 여러 퍼즐 조각이 올바르게 표시되기 때문에 실제로 이해할 수 없습니다. (TableLayoutCorners 및 기본 가시성에 대해 public int를 시도했지만 동일한 결과를 얻었습니다.)

이것이 중요한지 모르겠지만 ImageView원래 크기는 주어지지 않았습니다. ImageViews 의 크기는 표시 할 이미지를 제공 할 때 View에 의해 자동으로 초기화하는 동안 결정됩니다. 로깅 코드에 이미지가 제공된 후 자동으로 크기가 조정 된 후에도 값이 0이 될 수 있습니까? 잠재적으로 그것을 반박하기 위해 tableLayout.requestLayout()위 의 코드 를 추가 했지만 도움이되지 않았습니다.



답변

View.getLocationOnScreen()및 / 또는을 사용하십시오 getLocationInWindow().


답변

수락 된 답변은 실제로 위치를 얻는 방법을 알려주지 않았으므로 여기에 좀 더 자세한 내용이 있습니다. int길이가 2 인 배열을 전달 하면 값이 뷰의 (x, y) 좌표 (왼쪽 위 모서리)로 바뀝니다.

int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];

노트

  • 로 교체 getLocationOnScreen하면 getLocationInWindow대부분의 경우 동일한 결과를 제공해야합니다 ( 이 답변 참조). ). 그러나 대화 상자 나 사용자 정의 키보드와 같은 더 작은 창에있는 경우 필요에 가장 적합한 것을 선택해야합니다.
  • 뷰가 아직 배치되지 않았기 때문에이 (0,0)메소드를 호출 하면 얻을 수 있습니다 onCreate. a ViewTreeObserver를 사용 하여 레이아웃이 완료되면 청취하고 측정 된 좌표를 얻을 수 있습니다. ( 이 답변을 참조하십시오 .)

답변

먼저보기의 localVisible 사각형을 가져와야합니다.

예를 들어 :

Rect rectf = new Rect();

//For coordinates location relative to the parent
anyView.getLocalVisibleRect(rectf);

//For coordinates location relative to the screen/display
anyView.getGlobalVisibleRect(rectf);

Log.d("WIDTH        :", String.valueOf(rectf.width()));
Log.d("HEIGHT       :", String.valueOf(rectf.height()));
Log.d("left         :", String.valueOf(rectf.left));
Log.d("right        :", String.valueOf(rectf.right));
Log.d("top          :", String.valueOf(rectf.top));
Log.d("bottom       :", String.valueOf(rectf.bottom));

이것이 도움이되기를 바랍니다.


답변

전역 레이아웃 리스너를 사용하면 항상 잘 작동했습니다. 레이아웃이 변경되면 (예 : 무언가가 View로 설정되어있는 경우) GONE 또는 하위 뷰가 추가 / 제거되는 경우 사물을 재 측정 할 수 있다는 이점이 있습니다.

public void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);

     // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
     LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null);

     // set a global layout listener which will be called when the layout pass is completed and the view is drawn
     mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
       new ViewTreeObserver.OnGlobalLayoutListener() {
          public void onGlobalLayout() {
               //Remove the listener before proceeding
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
               } else {
                    mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
               }

               // measure your views here
          }
       }
     );

     setContentView(mainLayout);
 }


답변

Romain Guy의 의견에 따라 수정 방법은 다음과 같습니다. 이 문제가있는 다른 사람에게 도움이 되길 바랍니다.

나는 그들이 화면에 배치되기 전에 실제로보기의 위치를 ​​얻으려고 노력했지만 전혀 일어나지 않았습니다. 이 코드는 초기화 코드가 실행 된 후에 배치되었으므로 모든 것이 준비되었다고 가정했습니다. 그러나이 코드는 여전히 onCreate ()에있었습니다. Thread.sleep ()을 실험하여 onResume ()까지 onCreate ()가 끝날 때까지 레이아웃이 실제로 마무리되지 않았다는 것을 알았습니다. 실제로 레이아웃이 화면에 배치되기 전에 코드를 실행하려고했습니다. 코드를 OnClickListener (또는 다른 리스너)에 추가하면 레이아웃이 완료된 후에 만 ​​실행될 수 있으므로 올바른 값을 얻습니다.


아래 줄은 커뮤니티 편집으로 제안되었습니다.

사용하시기 바랍니다 onWindowfocuschanged(boolean hasFocus)


답변

첫 번째 방법 :

에서 코 틀린 우리가보기에 대한 간단한 확장을 만들 수 있습니다 :

fun View.getLocationOnScreen(): Point
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return Point(location[0],location[1])
}

그리고 단순히 좌표를 얻으십시오.

val location = yourView.getLocationOnScreen()
val absX = location.x
val absY = location.y

두 번째 방법 :

두 번째 방법은 더 간단합니다.

fun View.absX(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[0]
}

fun View.absY(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[1]
}

간단하게 X를 view.absX(), Y를view.absY()


답변

내 유틸은 GET보기 위치 기능, 그것은 반환 Point을 가진 개체를 x value하고y value

public static Point getLocationOnScreen(View view){
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    return new Point(location[0], location[1]);
}

사용

Point viewALocation = getLocationOnScreen(viewA);