programing

뷰의 절대 좌표를 가져오는 방법

newstyles 2023. 6. 3. 08:19

뷰의 절대 좌표를 가져오는 방법

뷰의 왼쪽 상단 모서리에 있는 절대 화면 픽셀 좌표를 가져오려고 합니다.하지만, 내가 찾을 수 있는 모든 방법은 다음과 같습니다.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]);

이 코드는 모든 초기화가 완료된 후 추가되었습니다.는 이미가다셀이보의기미포지배함분(지[]배열다)되었습니다.TableLayout은 왼쪽 의 "[0]"입니다.ImageView그리고 저는 세포[4]를 선택했습니다. 가운데 어딘가에 있기 때문입니다. 그리고 분명히 좌표가 (0,0)이면 안 됩니다.

위에 표시된 코드는 여전히 로그에 있는 모든 0을 제공하는데, 다양한 퍼즐 조각이 올바르게 표시되어 있어서 정말 이해할 수 없습니다.(테이블 레이아웃 코너와 기본 가시성에 대해 public int를 시도했는데 둘 다 같은 결과를 얻었습니다.)

의미가 게중건모르만지겠지는저는, 이요한▁i는,저.ImageViews는 원래 크기가 주어지지 않습니다.ImageViews는 초기화 중에 표시할 이미지를 제공할 때 보기에 의해 자동으로 결정됩니다.로깅 코드가 이미지가 제공되고 자동으로 크기가 조정된 후에도 이 값이 0이 되도록 할 수 있습니까?잠재적으로 그것에 대응하기 위해 코드를 추가했습니다.tableLayout.requestLayout()위에 표시된 것처럼, 그러나 그것은 도움이 되지 않았습니다.

사용 및/또는.

수락된 답변은 실제로 위치를 얻는 방법을 알려주지 않았기 때문에 여기에 조금 더 자세히 설명합니다.당신은 통과합니다.int길이 2의 배열과 값이 뷰의 (x, y) 좌표(위쪽 왼쪽 모서리)로 바뀝니다.

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

메모들

  • 로 대체하면 대부분의 경우 동일한 결과를 얻을 수 있습니다( 답변 참조).그러나 대화 상자 또는 사용자 지정 키보드와 같은 작은 창에 있는 경우 사용자의 필요에 더 적합한 창을 선택해야 합니다.
  • 얻게 될 것입니다.(0,0)을 이방을 호면하출법에서 ,onCreate아직 시야가 확보되지 않았기 때문입니다.를 사용할 수 있습니다.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);
 }

첫 번째 방법:

Kotlin에서는 보기를 위한 간단한 확장을 만들 수 있습니다.

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()

Romain Guy의 말에 따라, 제가 고친 방법은 다음과 같습니다.이 문제를 가진 다른 사람들에게도 도움이 되기를 바랍니다.

저는 실제로 화면에 보기가 배치되기 전에 보기의 위치를 파악하려고 했지만, 그것이 일어나고 있는지 전혀 분명하지 않았습니다.그 선들은 초기화 코드가 실행된 후에 배치되었기 때문에 저는 모든 것이 준비되었다고 생각했습니다.그러나 이 코드는 스레드로 실험하여 Create()에 남아 있었습니다.sleep() Create() 이후부터 onResume()까지의 모든 과정이 실행을 마칠 때까지 레이아웃이 실제로 완료되지 않는다는 것을 발견했습니다.그래서 실제로 코드는 레이아웃이 화면에 배치되기 전에 실행하려고 했습니다.코드를 OnClickListener(또는 다른 Listener)에 추가하면 레이아웃이 완료된 후에만 실행될 수 있으므로 올바른 값을 얻을 수 있습니다.


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

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

또는 를 사용하여 보기의 좌표를 얻을 수 있습니다.

후에, 후에그,▁after그.x그리고.y보기의 왼쪽 상단 모서리여야 합니다.), 레 이 아 웃 작 경 상 자 우 대 은 화 다 트 보 화getLocationInWindow전체 화면이 아니라 컨테이너에 상대적입니다.

자바 솔루션

int[] point = new int[2];
view.getLocationOnScreen(point); // or getLocationInWindow(point)
int x = point[0];
int y = point[1];

참고: 값이 항상 0이면 위치를 요청하기 직전에 보기를 변경할 수 있습니다.

수새후 보기를업있하보사새다계용레다후를 사용하여 위치 합니다.view.post:

view.post(() -> {
    // Values should no longer be 0
    int[] point = new int[2];
    view.getLocationOnScreen(point); // or getLocationInWindow(point)
    int x = point[0];
    int y = point[1];
});

~~

코틀린 솔루션

val point = IntArray(2)
view.getLocationOnScreen(point) // or getLocationInWindow(point)
val (x, y) = point

참고: 값이 항상 0이면 위치를 요청하기 직전에 보기를 변경할 수 있습니다.

수새후 보기를업있하보사새다계용레다후를 사용하여 위치 합니다.view.post:

view.post {
    // Values should no longer be 0
    val point = IntArray(2)
    view.getLocationOnScreen(point) // or getLocationInWindow(point)
    val (x, y) = point
}

이를 처리하기 위한 확장 기능을 만드는 것이 좋습니다.

// To use, call:
val (x, y) = view.screenLocation

val View.screenLocation get(): IntArray {
    val point = IntArray(2)
    getLocationOnScreen(point)
    return point
}

또한 안정성이 필요한 경우 다음을 추가합니다.

view.screenLocationSafe { x, y -> Log.d("", "Use $x and $y here") }

fun View.screenLocationSafe(callback: (Int, Int) -> Unit) {
    post {
        val (x, y) = screenLocation
        callback(x, y)
    }
}

어디에 언제 전화를 해야 하는지에 답변 에도, 하는지에 대한 입니다.getLocationOnScreen?

다과관모정경우의보든련음된에 된 모든 .view보기가 화면에 배치(생성)된 후에만 사용할 수 있습니다.를 위를확려면코입다니합력드를치 에 넣어주세요.view.post(Runnable)은 이딴을름의 에 불립니다.view다음과 같이 배치되었습니다.

view.post(new Runnable() {
            @Override
            public void run() {

               // This code will run when view created and rendered on screen

               // So as the answer to this question, you can put the code here
               int[] location = new int[2];
               myView.getLocationOnScreen(location);
               int x = location[0];
               int y = location[1];
            }
        });  

은 utils를 합니다. utils는 utils를 합니다.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);

화면에서 보기 위치 및 치수 모두 가져오기

val viewTreeObserver: ViewTreeObserver = videoView.viewTreeObserver;

    if (viewTreeObserver.isAlive) {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                //Remove Listener
                videoView.viewTreeObserver.removeOnGlobalLayoutListener(this);
                
                //View Dimentions
                viewWidth = videoView.width;
                viewHeight = videoView.height;

                //View Location
                val point = IntArray(2)
                videoView.post {
                    videoView.getLocationOnScreen(point) // or getLocationInWindow(point)
                    viewPositionX = point[0]
                    viewPositionY = point[1]
                }

            }
        });
    }
binding.ivStory.setOnTouchListener(object : View.OnTouchListener{
        override fun onTouch(p0: View?, event: MotionEvent?): Boolean {
            val x = event?.x
            vak y = event?.y

            when (event!!.action) {
                MotionEvent.ACTION_UP ->

                if (x != null) {
                   //Do your stuff                    }

                MotionEvent.ACTION_DOWN  -> {

                }
            }
            return true
        }

    })

이것은 당신이 화면을 터치할 때 화면 뷰의 좌표를 얻는 코틀린 방식입니다.위쪽 및 아래쪽 작업을 모두 처리해야 합니다. 그렇지 않으면 여러 번의 클릭/터치가 발생할 수 있습니다.

언급URL : https://stackoverflow.com/questions/2224844/how-to-get-the-absolute-coordinates-of-a-view