Görünümün kök düzenine göre koordinatlarını alma


Yanıtlar:


138

Bu bir çözümdür, ancak API'lar zaman içinde değiştiğinden ve bunu yapmanın başka yolları olabileceğinden, diğer yanıtları kontrol ettiğinizden emin olun. Biri daha hızlı, diğeri daha kolay olduğunu iddia ediyor.

private int getRelativeLeft(View myView) {
    if (myView.getParent() == myView.getRootView())
        return myView.getLeft();
    else
        return myView.getLeft() + getRelativeLeft((View) myView.getParent());
}

private int getRelativeTop(View myView) {
    if (myView.getParent() == myView.getRootView())
        return myView.getTop();
    else
        return myView.getTop() + getRelativeTop((View) myView.getParent());
}

Bunun işe yarayıp yaramadığını bana bildirin.

Her bir üst konteynerin üst ve sol konumlarını tekrar tekrar eklemelidir. İsterseniz bir ile de uygulayabilirsiniz Point.


getRelativeLeft () bu döküm eklemek gerekir, ancak (Görünüm) veya (düğme) ((Nesne) myView.getParent ()). getRelativeTop () eklediğimde, doğru değil
pengwang

Çok benzer bir şey yaptım ama getId == R.id.myRootView tarafından kök görünümü için kontrol etti.
fhucho

1
Log.i ("RelativeLeft", "" + getRelativeLeft (findViewById (R.id.tv))); Log.i ("RelativeTop", "" + getRelativeTop (findViewById (R.id.tv))); her şeyi 0 alırım; Yerleşimdeki textView aşağıdaki gibidir <TextView android: layout_width = "fill_parent" android: layout_height = "wrap_content" android: text = "@ string / merhaba" android: id = "@ + id / tv" android: layout_marginBottom = "69dip" android: layout_marginLeft = "69dip" />
pengwang

Bunun gibi smiliar yaklaşım (manuel olarak hesaplanıyor) benim için çalıştı, bu yüzden bu cevabı kabul ettim.
fhucho

3
android api zaten kök için göreceli koordinat sağlar. buraya bak stackoverflow.com/a/36740277/2008214
carlo.marinangeli

155

Android API bunu başarmak için zaten bir yöntem sunuyor. Bunu dene:

Rect offsetViewBounds = new Rect();
//returns the visible bounds
childView.getDrawingRect(offsetViewBounds);
// calculates the relative coordinates to the parent
parentViewGroup.offsetDescendantRectToMyCoords(childView, offsetViewBounds); 

int relativeTop = offsetViewBounds.top;
int relativeLeft = offsetViewBounds.left;

İşte doktor


16
Bu kabul edilen cevap olmalı. Yığın taşması olasılığı ve matematik hatası olasılığı yoktur. Teşekkürler!
GLee

Kabul ediyorum, bu kabul edilen cevap olmalı - sadece 92 oy kaldı.
şaşkın

Araç çubuğunda bir görünümün koordinatlarını bulmak istedim. Bu, android için sürekli olarak çalışan bir yöntemdir: fitsSystemWindows ve 19 ila 27 arasındaki çeşitli API sürümleri. Bu doğru cevap.
David Ferrand

Kusursuz çalıştı
Rawa

Çok iyi çalıştı, sadece parentViewGroupgörünüm hiyerarşisinde herhangi bir ebeveyn olabileceğini belirtmek istiyorum , bu yüzden ScrollView için de mükemmel çalışıyor.
Sira Lam

93

Lütfen kullanın view.getLocationOnScreen(int[] location);( Javadoc'lara bakınız ). Cevap tamsayı dizisidir (x = location[0]ve y = location[1]).


13
Bu, Faaliyetin kök düzenine değil, ekrana bağlı konumu döndürür.
fhucho

10
Ayrıca görünümün pencereye göre konumunu döndüren View.getLocationInWindow (int []) vardır.
Rubicon

Lütfen bana bu yöntemin nasıl çalıştığını söyler misiniz? Ekranda bir görünümün çıktısını veya x, y değerlerini nasıl alacağımızı gösteren bir boşluk döndürür
user1106888

6
Kök düzenine göre konumu almak için, kök düzen ve öğe için getLocationInWindow'u çağırmanız ve çıkarma gücünü kullanmanız yeterlidir. Kabul edilen cevaptan çok daha basit ve daha hızlı.
Blake Miller

1
bu sadece ekranla ilgili konumdur. kök değil. köke göre için burayı okuyun: stackoverflow.com/a/36740277/2008214
carlo.marinangeli

36
View rootLayout = view.getRootView().findViewById(android.R.id.content);

int[] viewLocation = new int[2]; 
view.getLocationInWindow(viewLocation);

int[] rootLocation = new int[2];
rootLayout.getLocationInWindow(rootLocation);

int relativeLeft = viewLocation[0] - rootLocation[0];
int relativeTop  = viewLocation[1] - rootLocation[1];

Önce kök düzenini alıp görünümle koordinat farkını hesaplıyorum.
Bunun getLocationOnScreen()yerine de kullanabilirsiniz getLocationInWindow().


3
görünüm ne ölçeklendirilir ve döndürülür?
DKV

Benim için çalışan tek cevap bu. Bu cevap kabul edilmelidir
neoexpert

36

Manuel olarak hesaplamaya gerek yok.

Bunun için getGlobalVisibleRect kullanın :

Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;

Ayrıca, merkez koordinatlar için aşağıdakine benzer bir şey yerine şunları unutmayın:

...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;

Sadece şunları yapabilirsiniz:

float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();

Tüm android kaynağında baktığımızda getGlobalVisibleRectyapmasıdır globalOffset.set(-mScrollX, -mScrollY);sadece ile bu değerleri alabilir bu yüzden getScollX/Ysadece göreli koordinatları gerekiyorsa.
Xander

2
Bu cevap kabul edilmelidir. getLocationOnScreen, getGlobalVisibleRect'in yanı sıra çalışır. Ancak getGlobalVisibleRect biraz daha fazla bilgi sağlar ve ham dizilerle çalışmaya gerek yoktur. Bu nedenle getGlobalVisibleRect ile giderdim. Kullanımı basit. Rect positionRect = yeni Rect (); view.getGlobablVisibleRect (positionRect); // x = positionRect.left // y = positionRect.top. şerefe
JacksOnF1re

Çocuğun bir kısmı dışarıda ise, bu durumda dikkate alınmayacaksa. böyle bir dava nasıl çözülür?
DKV

Mükemmel cevap! Çok teşekkür ederim!
Rohit Kumar

8

`

view.getLocationOnScreen (int [] konum)

; `` görünümünüzün konumunu doğru şekilde almak için.

Ama bir var yakalamak düzeni yanlış pozisyon alacak şişirilmiş edilmeden önce bunu kullanırsanız.

Bu sorunun çözümü şöyle ekliyor ViewTreeObserver: -

Görünümünüzün xy konumunu depolamak için diziyi global olarak bildirin

 int[] img_coordinates = new int[2];

ve daha sonra ViewTreeObservermizanpaj enflasyonu için geri arama almak için üst mizanpajınızı ekleyin ve yalnızca görüş pozisyonunu getirin, aksi takdirde yanlış xy koordinatları elde edersiniz

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

                            // measure your views here
                            fab.getLocationOnScreen(img_coordinates);
                        }
                    }
            );

ve sonra böyle kullan

xposition = img_coordinates[0];
yposition =  img_coordinates[1];

3

Kendime çoğu koşulda işe yarayan iki yarar yöntemi yazdım, kaydırma, çeviri ve ölçeklendirme işledim, ancak döndürme değil. Bu tutarsız doğruluk vardı çerçevede offsetDescendantRectToMyCoords () kullanmaya çalıştıktan sonra yaptım. Bazı durumlarda işe yaradı, ancak diğerlerinde yanlış sonuçlar verdi.

"nokta" iki elemanlı bir kayan dizidir (x & y koordinatları), "ata", ağaç hiyerarşisinde "alt öğenin" üstünde bir yerde bir görünüm grubudur.

İlk olarak, soy koordinatlarından ataya giden bir yöntem:

public static void transformToAncestor(float[] point, final View ancestor, final View descendant) {
    final float scrollX = descendant.getScrollX();
    final float scrollY = descendant.getScrollY();
    final float left = descendant.getLeft();
    final float top = descendant.getTop();
    final float px = descendant.getPivotX();
    final float py = descendant.getPivotY();
    final float tx = descendant.getTranslationX();
    final float ty = descendant.getTranslationY();
    final float sx = descendant.getScaleX();
    final float sy = descendant.getScaleY();

    point[0] = left + px + (point[0] - px) * sx + tx - scrollX;
    point[1] = top + py + (point[1] - py) * sy + ty - scrollY;

    ViewParent parent = descendant.getParent();
    if (descendant != ancestor && parent != ancestor && parent instanceof View) {
        transformToAncestor(point, ancestor, (View) parent);
    }
}

Daha sonra, atadan soydan nesile:

public static void transformToDescendant(float[] point, final View ancestor, final View descendant) {
    ViewParent parent = descendant.getParent();
    if (descendant != ancestor && parent != ancestor && parent instanceof View) {
        transformToDescendant(point, ancestor, (View) parent);
    }

    final float scrollX = descendant.getScrollX();
    final float scrollY = descendant.getScrollY();
    final float left = descendant.getLeft();
    final float top = descendant.getTop();
    final float px = descendant.getPivotX();
    final float py = descendant.getPivotY();
    final float tx = descendant.getTranslationX();
    final float ty = descendant.getTranslationY();
    final float sx = descendant.getScaleX();
    final float sy = descendant.getScaleY();

    point[0] = px + (point[0] + scrollX - left - tx - px) / sx;
    point[1] = py + (point[1] + scrollY - top - ty - py) / sy;
}

2

Birisi hala bunu anlamaya çalışıyorsa. Merkezinin X ve Y merkezlerini bu şekilde elde edersiniz view.

    int pos[] = new int[2];
    view.getLocationOnScreen(pos);
    int centerX = pos[0] + view.getMeasuredWidth() / 2;
    int centerY = pos[1] + view.getMeasuredHeight() / 2;

1

Cevabı burada buldum

Diyor ki: getLeft () ve getTop () yöntemlerini çağırarak bir görünümün konumunu almak mümkündür. Birincisi, görünümü temsil eden dikdörtgenin sol veya X koordinatını döndürür. İkincisi, görünümü temsil eden dikdörtgenin üst veya Y koordinatını döndürür. Bu yöntemlerin her ikisi de görünümün üst öğeye göre konumunu döndürür. Örneğin, getLeft () 20 döndürdüğünde, görünüm doğrudan üst öğesinin sol kenarının 20 piksel sağında bulunur.

bu yüzden kullanın:

view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left

1
Bu, ebeveynin ebeveyni vb.
Olabilecek

görünüm ne ölçeklendirilir ve döndürülür?
DKV
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.