Android'de görünüm konumunu dinamik olarak nasıl ayarlayabilirim?


102

Görünüm konumunu kod aracılığıyla nasıl değiştirebilirim? X, Y konumunu değiştirmek gibi. Mümkün mü?

Yanıtlar:


117

Honeycomb'un (API Seviye 11) altındaki her şey için kullanmanız gerekecek setLayoutParams(...).

Honeycomb'dan için desteğinizi sınırlamak ve eğer kullanabilirsiniz yukarı setX(...), setY(...), setLeft(...), setTop(...), vb


41
setTop () developer.android.com/reference/android/view/… dokümanlarından : sets the top position of this view relative to its parent. This method is meant to be called by the layout system and should not generally be called otherwise, because the property may be changed at any time by the layout.- belki bu o kadar da iyi bir fikir değil;)
katzenhut

47

Evet, görünümün konumunu Android'de dinamik olarak ayarlayabilirsiniz. Aynı şekilde bir var ImageViewiçinde LinearLayoutsenin xml aracılığıyla onun konumunu ayarlayabilirsiniz file.So LayoutParams.Ama almak için emin olun LayoutParamssizin xml file.There alınan düzenine göre farklıdır LayoutParamsalınan düzenine göre.

İşte ayarlanacak kod:

    LayoutParams layoutParams=new LayoutParams(int width, int height);
    layoutParams.setMargins(int left, int top, int right, int bottom);
    imageView.setLayoutParams(layoutParams);

Umarım pozisyon belirlemeniz size yardımcı olur.


15
ayrıca android.widget.LinearLayout.LayoutParams'ı içe aktarmanız gerektiğini unutmayın; çünkü varsayılan ViewGroup'un LayoutParams
David T.

Bu, Android 8+ üzerinde çalışmıyor gibi görünüyor. benzer bir sorunla karşılaştın mı?
MyFlashLab

Andriod tasarımcılarının programcıların bir şeyleri konumlandırmak için X, Y'yi kullanmasını engellemek için neden bu kadar zahmete girdiği hakkında herhangi bir fikriniz. Sonunda her şey bu şekilde çizilmelidir. Bu, Android'in kod yazamayan kişiler tarafından tasarlandığını gösteriyor.
Paul McCarthy

34

Halihazırda farklı geçerli yanıtlar var, ancak karşılık gelen API düzeyi kısıtlamaları dışında hiçbiri bu durumda hangi yöntemlerin kullanılacağını doğru bir şekilde önermiyor gibi görünüyor:

  • Bir düzen döngüsünü bekleyebilirseniz ve üst görünüm grubu MarginLayoutParams(veya bir alt sınıfı) destekliyorsa , buna göre marginLeft/ ayarlayın marginTop.

  • Konumu hemen ve ısrarla değiştirmeniz gerekirse (örneğin bir PopupMenu bağlantısı için), ek layout(l, t, r, b)olarak aynı koordinatlarla arayın . Bu, düzen sisteminin daha sonra onaylayacağı şeyi önceden belirler.

  • Anlık (geçici) değişiklikler için (animasyonlar gibi) bunun yerine setX()/ setY()kullanın. Ebeveyn boyutunun WRAP_CHILDREN'e bağlı olmadığı durumlarda, özel olarak setX()/ kullanmak iyi olabilir setY().

  • AslasetLeft() / setRight()/ setBottom()/ kullanmayın setTop(), aşağıya bakın.

Arka plan : mLeft/ mTop/ mBottom/ mRightalanları, layout () içindeki karşılık gelen LayoutParams'tan doldurulur. Düzen, Android görünüm düzeni sistemi tarafından örtülü ve eşzamansız olarak çağrılır. Bu nedenle, MarginLayoutParamskonumu kalıcı olarak ayarlamanın en güvenli ve en temiz yolu gibi görünüyor. Bununla birlikte, eşzamansız düzen gecikmesi bazı durumlarda bir sorun olabilir, örneğin bir imleci oluşturmak için bir Görünüm kullanıldığında ve yeniden konumlandırılması ve aynı zamanda bir PopupMenu bağlantısı olarak hizmet etmesi gerekir. Bu durumda aramalayout() benim için iyi çalıştı.

Sorunlar setLeft()ve setTop()şunlardır:

  • Onları tek başına aramak yeterli değildir - ayrıca aramanız setRight()ve setBottom()görünümü uzatmaktan veya küçültmekten kaçınmanız gerekir .

  • Bu yöntemlerin uygulanması nispeten karmaşık görünüyor (= her birinin neden olduğu görünüm boyutu değişikliklerini hesaba katmak için biraz çalışma yapmak)

  • Giriş alanlarında garip sorunlara neden oluyor gibi görünüyorlar: EditText yumuşak sayısal klavye bazen rakamlara izin vermiyor

setX()ve setY()yerleşim sisteminin dışında çalışır ve karşılık gelen değerler, görünümü buna göre kaydırarak, yerleşim sistemi tarafından belirlenen sol / üst / alt / sağ değerlere ek bir sapma olarak kabul edilir. Animasyonlar için eklenmiş gibi görünüyorlar (bir düzen döngüsünden geçmeden hemen bir efektin gerekli olduğu yerlerde).


Merhaba Stefan. Android düzen sisteminin nasıl çalıştığını anlayabileceğim birkaç kitap veya makale tavsiye edebilir misiniz? Layout () onMeasure () onDraw () çağrılarının sırasını anlıyorum, ancak daha fazla ayrıntı bilmek istiyorum. Şimdiden teşekkürler
Sergey Brazhnik

Maalesef yapamam - en iyi ve en kesin referans gerçek Android kaynak kodu gibi görünüyor O :)
Stefan Haustein

Görünümü değiştirmek için setY kullanıyorum, bir sonraki düzen döngüsünde değişiyor, hemen değil mi?
sinyal

Bunu nasıl belirlediniz?
Stefan Haustein

It değerinde olduğunu işaret marginLeftkullanılarak ayarlanabilir setLayoutParamsbir ile new FrameLayout.LayoutParams(width, height)hangi ayarladığınızmarginLeft
lucidbrot

18

Honeycomb animasyon kütüphanesini birinci versiyona kadar kullanmanıza izin veren NineOldAndroids adlı bir kütüphane var .

Bu, biraz farklı bir arayüzle sol, sağ, translationX / Y'yi tanımlayabileceğiniz anlamına gelir.

Şu şekilde çalışır:

ViewHelper.setTranslationX(view, 50f);

ViewHelper sınıfındaki statik yöntemleri kullanırsınız, görünümü iletirsiniz ve onu hangi değere ayarlamak isterseniz iletirsiniz.


16

Ben kullanarak öneriyoruz setTranslationXve setTranslationY. Buna kendim daha yeni başlıyorum, ancak bunlar bir manzarayı hareket ettirmenin en güvenli ve tercih edilen yolu gibi görünüyor. Sanırım bu, tam olarak ne yapmaya çalıştığınıza bağlı, ancak bu benim için 2D animasyon için iyi çalışıyor.


13

HoneyComb Sdk (API Seviye 11) kullanıyorsanız, aşağıdaki yöntemleri kullanmayı deneyebilirsiniz.

view.setX(float x);

Parametre x, bu görünümün görsel x konumudur.

view.setY(float y);

Parametre y, bu görünümün görsel y konumudur.

Umarım size yardımcı olur. :)


4
2.2 Froyo üzerinde çalışıyorum ve bu yöntemler içinde mevcut değil.
Arun Badole

7

Tüm API seviyelerine destek için kullanabileceğiniz bunu böyle:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);

Çünkü konumu değiştirmek istiyor ve üstü çözüm daha iyi ve animasyona ihtiyaç duymuyor
FireZenk

Ayrıca, çeviri, görünümün ekran dışına (kısmen) gitmesine neden olabilir
mewa

4

Bu görünümün sol konumunu üstüne göre ayarlayın:

view.setLeft(int leftPosition);

Üstüne göre bu görünümün doğru konumunu ayarlayın:

view.setRight(int rightPosition);

Üstüne göre bu görünümün en üst konumunu ayarlayın:

view.setTop(int topPosition);

Bu görünümün alt konumunu üstüne göre ayarlayın:

view.setBottom(int bottomPositon);

Yukarıdaki yöntemler, görünümü ebeveyniyle ilgili konumu ayarlamak için kullanılır.


Üzgünüm Bu yöntemler mevcut değil.Bana herhangi bir kod gönderebilir misin?
Arun Badole

4
"Bu yöntemin düzen sistemi tarafından çağrılması amaçlanmıştır ve genellikle başka türlü çağrılmamalıdır, çünkü özellik herhangi bir zamanda düzen tarafından değiştirilebilir."
GDanger

4

LayoutParams'ı kullanın. Bir LinearLayout kullanıyorsanız android.widget.LinearLayout.LayoutParams'ı içe aktarmanız gerekir, aksi takdirde kullandığınız düzen için LayoutParams'in uygun sürümünü içe aktarmanız gerekir, aksi takdirde bir ClassCastException'a neden olur , o zaman:

LayoutParams layoutParams = new LayoutParams(int width, int height);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);

Not: imageView.setLeft (int dim) 'i de kullanabileceğinizi unutmayın, ANCAK BU, bileşenin konumunu ayarlamaz, yalnızca bileşenin sol kenarının konumunu ayarlayacaktır, geri kalanı aynı konumda kalacaktır .


öyleyse görünümü orijinal görünümü etkilemeden belirli bir konuma nasıl taşıyabiliriz?
james

Sorununuzu anladığımdan emin değilim çünkü bir görünümü hareket ettirmek isterseniz, onu hareket ettirdiğiniz gerçeğiyle onu değiştireceksiniz. Her neyse, bir görünümü ondan bağımsız olarak başka birinin üzerine taşımak istiyorsanız, ana düzeninizi gösteren bir Çerçeve Düzeni görünümüne ihtiyacınız olabilir, ardından içine bağımsız görünümlerinizi yerleştirebilirsiniz (tabii ki ana görünümünüzün altına hareket etmesini istiyorsanız FrameLayout'u ana düzeninizin önüne yerleştirmelisiniz)
Alessandro Muzzi

3

Kullanın RelativeLayout, görünümünüzü içine yerleştirin, görünümünüzden RelativeLayout.LayoutParamsnesneyi alın ve ihtiyaç duyduğunuzda kenar boşluklarını ayarlayın. Sonra requestLayout()görüşünüzü arayın . Bunu bilmemin tek yolu bu.


1

@Stefan Haustein'ın deneyimime çok yaklaştığını, ancak% 100 emin olamadığını öğrendim. Benim önerim şu:

  • setLeft()/ setRight()/ setBottom()/ setTop()bazen çalışmaz.
  • Eğer isterseniz (örneğin animasyon yapmak için, bir hierachy etkilenmez) geçici bir pozisyon ayarlamak zaman görünümü eklendi ve gösterilen sadece kullanmak setX()/setY() yerine. (Daha fazla farklı arama yapmak isteyebilirsiniz vesetLeft()setX() )
  • Ve X, Y'nin mutlak göründüğüne ve artık kullanımdan kaldırılan AbsoluteLayout tarafından desteklendiğine dikkat edin. Dolayısıyla, X, Y'nin artık desteklenmediğini hissediyorsunuz. Ve evet, öyle, ama sadece kısmen. Bu, görünümünüz eklenirse setX (), setY () mükemmel çalışacaktır ; aksi halde, ne zaman sen deneyin görünüm grup düzeni içine bir görünüm eklemek (örn FrameLayout, LinearLayout, RelativeLayout) kullanarak, ayarlamalısınız ile LayoutParams marginLeft, marginTop yerine (setx (), bu durumda Sety () bazen çalışmaz).
  • Görünümün konumunu marginLeft'e göre ayarlayın ve marginTop , senkronize edilmemiş bir işlemdir. Bu yüzden hiyerarşiyi güncellemek için biraz zamana ihtiyacı var . Eğer varsa ayarlanan marjı sonra hemen görünümü kullanmak bunun için, size bir yanlış değerini alabilirsiniz .

0

Konumlandırmayla ilgili akılda tutulması gereken bir şey, her görünümün üst görünümüne göre bir dizine sahip olmasıdır. Dolayısıyla, üç alt görünüm içeren doğrusal bir düzene sahipseniz, alt görünümlerin her birinin bir indeksi olacaktır: yukarıdaki durumda 0, 1, 2.

Bu, aşağıdaki gibi bir şey yaparak bir üst öğe görünümündeki son konuma (veya sona) bir görünüm eklemenizi sağlar:

int childCount = parent.getChildCount();
parentView.addView(newView, childCount);

Alternatif olarak, aşağıdaki gibi bir şey kullanarak bir görünümü değiştirebilirsiniz:

int childIndex = parentView.indexOfChild(childView);
childView.setVisibility(View.GONE);

parentView.addView(newView, childIndex);
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.