Bir görünümün mutlak konumunu ayarlama


180

Android'de bir görünümün mutlak konumunu ayarlamak mümkün mü? (Bir olduğunu biliyorum AbsoluteLayout, ama kullanımdan kaldırıldı ...)

Örneğin, 240x320 piksel ekranım varsa ImageView, merkezi (100,100) konumunda olacak şekilde nasıl 20x20 piksel olan bir ekran ekleyebilirim ?


3
ayrıca bkz view.setTranslationX()veyaview.offsetLeftAndRight()
Drew Lesueur

Buraya ilgi duyabilecek bir kütüphane yayınladım. github.com/ManuelPeinado/ImageLayout
Manuel

1
Bu çok zordur çünkü zamanın% 99,9'u mutlak konumlandırma android için kötü bir fikirdir. SADECE tek bir fiziksel cihazda çalıştırılacak bir uygulama yazıyorsanız , bu işe yarayabilir, ancak bu genellikle güvenli bir varsayım değildir. Örneğin, bunu google play'e yüklemeyin. İOS'ta iyi çalışıyor çünkü sadece bir avuç donanım cihazı var ve her biri için özel bir film şeridi oluşturabilirsiniz.
edthethird

2
@ edthethird, Çapraz platform uygulamamda ekran boyutunu alıyorum ve her şeyi buna bağlıyorum. Ben sadece "eskimiş" AbsoluteLayout geçti ve iyi çalışıyor.
William Jockusch

Yeterince adil, ancak göreli bir Düzen veya LinearLayout sizin için otomatik olarak yapacak.
edthethird

Yanıtlar:


271

RelativeLayout'u kullanabilirsiniz. Diyelim ki düzeninizin içinde (50,60) 30x40 ImageView istediniz. Faaliyetinizin bir yerinde:

// Some existing RelativeLayout from your layout xml
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);

ImageView iv = new ImageView(this);

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

Daha fazla örnek:

Sırasıyla (50,60) ve (80,90) değerlerine iki 30x40 ImageView (bir sarı, bir kırmızı) yerleştirir:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;

iv = new ImageView(this);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;
rl.addView(iv, params);

Rehber (50,60) az bir 30x40 sarı ImageView ve başka 30x40 kırmızı ImageView <80,90> göreli sarı ImageView:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;

int yellow_iv_id = 123; // Some arbitrary ID value.

iv = new ImageView(this);
iv.setId(yellow_iv_id);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;

// This line defines how params.leftMargin and params.topMargin are interpreted.
// In this case, "<80,90>" means <80,90> to the right of the yellow ImageView.
params.addRule(RelativeLayout.RIGHT_OF, yellow_iv_id);

rl.addView(iv, params);

1
Bu gece bir göz atacağım, bu çok hoş bir fikir, neden böyle düşünmediğimi bilmiyorum. Ben ImageViewkoymak için birkaç var , bir kullanmak daha iyi olmaz mıydı FrameLayout?
Sephy

Aslında bu işe yarıyor gibi görünüyor, ancak, sadece bu şekilde bir resim eklediğinizde işe yarıyor. Eğer
ikincisini

1
İki görüntü üst üste geliyor. Açıklamak için yukarıdaki çözümüme bazı kod ekleyeceğim.
Andy Zhang

2
Evet, dün bunu çözümünüzü kendi başıma kazarak da buldum. Ayrıca FrameLayout ile bir şeyler deniyorum. Benim asıl sorunum her biri rastgele (x, y) konum ile 5 görüntü var, bu yüzden RelativeLayout.RIGHT_OF ya da bunun gibi bir şey kullanamıyorum. Garip bir şey düzgün yerleştirilmesi için 3 görüntü alabilirsiniz ama 2 çalışmıyor ... Anlayamıyorum ... Ben bu gece bazı ekran görüntüleri ve bazı kod ile yazı güncelleyeceğim.
Sephy

9
Neden bu yöntemi kullanmak AbsoluteLayout kullanmaktan daha iyi olur? AbsoluteLayout'un kullanımdan kaldırılması nedeniyle mi?
Nathan

66

Genel olarak, olarak, leftMargin ve topMargin niteliklerini belirterek, FrameLayout öğesini kap olarak kullanarak belirli bir konuma bir Görünüm ekleyebilirsiniz .

Aşağıdaki örnek, tam ekran kapsayıcısı olarak bir FrameLayout kullanarak (100,200) konumuna bir 20x20 piksel ImageView yerleştirecektir:

XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:background="#33AAFF"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>

Etkinlik / Parça / Özel görünüm

//...
FrameLayout root = (FrameLayout)findViewById(R.id.root);
ImageView img = new ImageView(this);
img.setBackgroundColor(Color.RED);
//..load something inside the ImageView, we just set the background color

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(20, 20);
params.leftMargin = 100;
params.topMargin  = 200;
root.addView(img, params);
//...

Kenar boşlukları RelativeLayout olmadan mutlak (X, Y) koordinatları olarak kullanılabileceğinden bu işe yarayacaktır:

resim açıklamasını buraya girin


2
Parlak! 500 değerinde! +1
Lisa Anne

16

Yukarıdaki Andy Zhang'ın cevabına eklemek için, isterseniz, rl.addView'a param verebilir, sonra daha sonra değişiklik yapabilirsiniz, bu yüzden:

params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

Aynı şekilde şu şekilde de yazılabilir:

params = new RelativeLayout.LayoutParams(30, 40);
rl.addView(iv, params);
params.leftMargin = 50;
params.topMargin = 60;

Eğer params değişkenini koruyorsanız, iv'in yerleşimini rl'ye ekledikten sonra istediğiniz zaman değiştirebilirsiniz.


bu örneği çok sevdik. . İ x set can y ı xml düzeni görüntüyü yaşıyorum zaman ekseni beni nasıl önermek, (i görüntüyü yeniden boyutlandırmak için çalışıyorum ve bazı pozisyonda görüntüyü ayarlamak gerekir) Can
G_S

Korkarım ne istediğini tam olarak anlamadım. XML mizanpajı kullanılarak konumlandırılmış bir nesneyle ilişkili LayoutParams nesnesine erişmeye mi çalışıyorsunuz? Bunun nasıl yapıldığından emin değilim. Cevabı başka bir yerde bulamazsanız, bunun cevaplanması için yeni bir soru oluşturmaya değer olabilir.
Tükenmiş

lütfen bu soruya bir göz atın stackoverflow.com/questions/12028404/…
G_S

5

Koddaki piksel değerlerini kodlamadan daha temiz ve dinamik bir yol.

Tıklanan bir düğmenin tam altına bir iletişim kutusu (anında şişirdiğim) yerleştirmek istedim.

ve şu şekilde çözdü:

    // get the yoffset of the position where your View has to be placed 
    final int yoffset = < calculate the position of the view >

    // position using top margin
    if(myView.getLayoutParams() instanceof MarginLayoutParams) {
        ((MarginLayoutParams) myView.getLayoutParams()).topMargin = yOffset;
    }

Ancak, üst düzeninin myViewaşağıdakilerin bir örneği olduğundan emin olmalısınız :RelativeLayout .

daha eksiksiz kod:

    // identify the button
    final Button clickedButton = <... code to find the button here ...>

    // inflate the dialog - the following style preserves xml layout params
    final View floatingDialog = 
        this.getLayoutInflater().inflate(R.layout.floating_dialog,
            this.floatingDialogContainer, false);

    this.floatingDialogContainer.addView(floatingDialog);

    // get the buttons position
    final int[] buttonPos = new int[2];
    clickedButton.getLocationOnScreen(buttonPos);        
    final int yOffset =  buttonPos[1] + clickedButton.getHeight();

    // position using top margin
    if(floatingDialog.getLayoutParams() instanceof MarginLayoutParams) {
        ((MarginLayoutParams) floatingDialog.getLayoutParams()).topMargin = yOffset;
    }

Bu şekilde, hedef görünümün, Java kodunuzdaki bu pikselleri / dpsleri kodlamak yerine, düzen XML dosyalarını kullanarak ayarlanan düzen parametrelerine ayarlanmasını bekleyebilirsiniz.


1

Ekran görüntüsünü kontrol et

İstediğiniz görünümü X & Y'ye yerleştirin noktanıza

düzen dosyası

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.test.MainActivity" >

    <AbsoluteLayout
        android:id="@+id/absolute"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <RelativeLayout
            android:id="@+id/rlParent"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <ImageView
                android:id="@+id/img"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/btn_blue_matte" />
        </RelativeLayout>
    </AbsoluteLayout>

</RelativeLayout>

Java Sınıfı

public class MainActivity extends Activity {

    private RelativeLayout rlParent;
    private int width = 100, height = 150, x = 20, y= 50; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        AbsoluteLayout.LayoutParams param = new AbsoluteLayout.LayoutParams(width, height, x, y);
        rlParent = (RelativeLayout)findViewById(R.id.rlParent);
        rlParent.setLayoutParams(param);
    }
}

Bitti


0

Birine yardımcı olması durumunda, bu animatör ViewPropertyAnimator'u aşağıdaki gibi de deneyebilirsiniz

myView.animate().x(50f).y(100f);

myView.animate().translateX(pixelInScreen) 

Not: Bu piksel görünüme bağlı değildir. Bu piksel, ekrandaki piksel konumudur.

bpr10 cevabına kredi


-1

Belirli bir konumdaki görünümü ayarlamak için aşağıdaki kodu deneyin: -

            TextView textView = new TextView(getActivity());
            textView.setId(R.id.overflowCount);
            textView.setText(count + "");
            textView.setGravity(Gravity.CENTER);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
            textView.setTextColor(getActivity().getResources().getColor(R.color.white));
            textView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // to handle click 
                }
            });
            // set background 
            textView.setBackgroundResource(R.drawable.overflow_menu_badge_bg);

            // set apear

            textView.animate()
                    .scaleXBy(.15f)
                    .scaleYBy(.15f)
                    .setDuration(700)
                    .alpha(1)
                    .setInterpolator(new BounceInterpolator()).start();
            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.topMargin = 100; // margin in pixels, not dps
            layoutParams.leftMargin = 100; // margin in pixels, not dps
            textView.setLayoutParams(layoutParams);

            // add into my parent view
            mainFrameLaout.addView(textView);

-1

Xamarin için kodum , bu amaçla FrameLayout kullanıyorum ve aşağıdaki benim kod:

               List<object> content = new List<object>();

        object aWebView = new {ContentType="web",Width="300", Height = "300",X="10",Y="30",ContentUrl="http://www.google.com" };
        content.Add(aWebView);
        object aWebView2 = new { ContentType = "image", Width = "300", Height = "300", X = "20", Y = "40", ContentUrl = "https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4" };
        content.Add(aWebView2);
        FrameLayout myLayout = (FrameLayout)FindViewById(Resource.Id.frameLayout1);
        foreach (object item in content)
        {

            string contentType = item.GetType().GetProperty("ContentType").GetValue(item, null).ToString();
            FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(Convert.ToInt32(item.GetType().GetProperty("Width").GetValue(item, null).ToString()), Convert.ToInt32(item.GetType().GetProperty("Height").GetValue(item, null).ToString()));
            param.LeftMargin = Convert.ToInt32(item.GetType().GetProperty("X").GetValue(item, null).ToString());
            param.TopMargin = Convert.ToInt32(item.GetType().GetProperty("Y").GetValue(item, null).ToString());

            switch (contentType) {
                case "web":{
                        WebView webview = new WebView(this);

                        //webview.hei;
                        myLayout.AddView(webview, param);
                        webview.SetWebViewClient(new WebViewClient());
                        webview.LoadUrl(item.GetType().GetProperty("ContentUrl").GetValue(item, null).ToString());

                        break;
                    }
                case "image":
                    {
                        ImageView imageview = new ImageView(this);

                        //webview.hei;
                        myLayout.AddView(imageview, param);
                        var imageBitmap =  GetImageBitmapFromUrl("https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4");
                        imageview.SetImageBitmap(imageBitmap);


                        break;
                    }

            }

        }

Benim için yararlı oldu çünkü ben görünüm özelliklerine kendi görünümleri temelinde üst üste binmek için gerekli, örneğin görüşlerini üst üste yığılmış .

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.