Atur posisi absolut tampilan

180

Apakah mungkin untuk mengatur posisi absolut tampilan di Android? (Aku tahu ada AbsoluteLayout, tapi sudah usang ...)

Misalnya, jika saya memiliki layar 240x320px, bagaimana saya bisa menambahkan ImageViewyang 20x20px sehingga pusatnya berada di posisi (100.100)?

Sephy
sumber
3
juga melihat view.setTranslationX()atauview.offsetLeftAndRight()
Drew LeSueur
Saya baru saja merilis perpustakaan yang mungkin menarik di sini. github.com/ManuelPeinado/ImageLayout
Manuel
1
Ini sangat sulit karena 99,9% dari waktu penentuan posisi absolut adalah ide yang buruk di android. Jika Anda menulis aplikasi yang HANYA akan dijalankan pada satu perangkat fisik, maka ini mungkin berhasil, tetapi itu umumnya bukan asumsi yang aman untuk dibuat. Misalnya, jangan unggah ini ke google play. Ini berfungsi dengan baik di iOS karena hanya ada beberapa perangkat perangkat keras, dan Anda dapat membuat storyboard khusus untuk masing-masing perangkat.
edthethird
2
@edthethird, Di aplikasi lintas-platform saya, saya mendapatkan ukuran layar dan mendasarkan semuanya pada itu. Saya baru saja beralih ke AbsoluteLayout "usang", dan berfungsi dengan baik.
William Jockusch
cukup adil, tapi itulah yang Layout Relatif atau LinearLayout akan lakukan untuk Anda secara otomatis.
edthethird

Jawaban:

271

Anda dapat menggunakan RelativeLayout. Katakanlah Anda menginginkan ImageView 30x40 pada posisi (50,60) di dalam tata letak Anda. Di suatu tempat dalam aktivitas Anda:

// 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);

Lebih banyak contoh:

Tempat dua 30x40 ImageViews (satu kuning, satu merah) masing-masing di (50,60) dan (80,90):

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

Tempatkan satu ImageView 30x40 kuning di (50,60) dan satu lagi ImageView merah 30x40 <80,90> relatif terhadap ImageView kuning:

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);
Andy Zhang
sumber
1
Saya akan mencobanya malam ini, itu ide yang sangat bagus, tidak tahu mengapa saya tidak memikirkan hal itu. Karena saya memiliki beberapa ImageViewuntuk dimasukkan, bukankah lebih baik menggunakan FrameLayout?
Sephy
Memang ini tampaknya berhasil, namun, itu hanya berfungsi ketika menambahkan satu gambar dengan cara ini. jika saya mencoba menambahkan yang ke-2, yang pertama hilang begitu saja ...
Sephy
1
Kedua gambar hanya saling bertumpukan. Saya akan menambahkan beberapa kode ke solusi saya di atas untuk menjelaskan.
Andy Zhang
2
Ya memang, saya menemukan itu kemarin juga dengan menggali solusi Anda sendiri. Saya juga mencoba berbagai hal dengan FrameLayout. Masalah aktual saya adalah bahwa saya memiliki 5 gambar dengan masing-masing posisi acak (x, y), jadi saya tidak dapat menggunakan RelativeLayout.RIGHT_OF atau sesuatu seperti itu. Yang aneh adalah bahwa saya bisa mendapatkan 3 gambar untuk ditempatkan dengan benar tetapi 2 dari mereka tidak berfungsi ... Saya tidak mengerti ... Saya akan memperbarui posting saya dengan beberapa screenshot malam ini dan beberapa kode.
Sephy
9
Mengapa menggunakan metode ini lebih baik daripada menggunakan AbsoluteLayout? Hanya karena AbsoluteLayout sudah usang?
Nathan
66

Secara umum, Anda dapat menambahkan tampilan di posisi tertentu menggunakan FrameLayout sebagai wadah dengan menentukan atribut leftMargin dan topMargin .

Contoh berikut akan menempatkan ImageView 20x20px pada posisi (100.200) menggunakan FrameLayout sebagai wadah layar penuh:

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>

Tampilan Aktivitas / Fragmen / Kustom

//...
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);
//...

Ini akan melakukan trik karena margin dapat digunakan sebagai koordinat absolut (X, Y) tanpa RelativeLayout:

masukkan deskripsi gambar di sini

bonnyz
sumber
2
Cemerlang! Senilai 500! +1
Lisa Anne
16

Hanya dengan menambahkan jawaban Andy Zhang di atas, jika Anda mau, Anda bisa memberikan param ke rl.addView, lalu buat perubahan di kemudian hari, jadi:

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

Bisa juga ditulis sebagai:

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

Jadi, jika Anda mempertahankan variabel params, Anda dapat mengubah tata letak iv kapan saja setelah menambahkannya ke rl.

Luar Biasa
sumber
menyukai sampel ini. Bisakah Anda menyarankan saya bagaimana saya bisa mengatur sumbu x, y ketika saya memiliki gambar dalam tata letak xml. (Saya mencoba untuk mengubah ukuran gambar dan saya perlu mengatur gambar di beberapa posisi)
G_S
Sayangnya saya tidak begitu mengerti apa yang Anda tanyakan. Apakah Anda mencoba mengakses objek LayoutParams yang dikaitkan dengan objek yang telah diposisikan menggunakan tata letak XML? Saya tidak yakin bagaimana itu dilakukan. Mungkin ada baiknya menyiapkan pertanyaan baru untuk dijawab, jika Anda tidak dapat menemukan jawabannya di tempat lain.
Luar Biasa
silakan lihat pertanyaan ini stackoverflow.com/questions/12028404/…
G_S
5

Cara yang lebih bersih dan dinamis tanpa hardcoding nilai piksel apa pun dalam kode.

Saya ingin memposisikan dialog (yang saya mengembang dengan cepat) tepat di bawah tombol yang diklik.

dan menyelesaikannya dengan cara ini:

    // 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;
    }

Namun Anda harus memastikan tata letak induk myViewadalah turunan dariRelativeLayout .

kode lebih lengkap:

    // 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;
    }

Dengan cara ini Anda masih dapat mengharapkan tampilan target untuk menyesuaikan ke setiap parameter tata letak yang diatur menggunakan tata letak file XML, alih-alih hardcoding piksel / dps dalam kode Java Anda.

Hari Krishna Ganji
sumber
1

Periksa tangkapan layar

Tempatkan pandangan apa pun pada titik X & Y keinginan Anda

file tata letak

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

Kelas Jawa

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);
    }
}

Selesai

Hiren Patel
sumber
0

Kalau-kalau itu dapat membantu seseorang, Anda juga dapat mencoba animator ini ViewPropertyAnimator seperti di bawah ini

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

myView.animate().translateX(pixelInScreen) 

Catatan: Pixel ini tidak relatif terhadap tampilan. Pixel ini adalah posisi pixel di layar.

kredit untuk jawaban bpr10

Praveenb
sumber
-1

Coba kode di bawah ini untuk mengatur tampilan di lokasi tertentu: -

            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);
Duggu
sumber
-1

Kode saya untuk Xamarin , saya menggunakan FrameLayout untuk tujuan ini dan berikut ini adalah kode saya:

               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;
                    }

            }

        }

Itu berguna bagi saya karena saya membutuhkan properti pandangan untuk saling tumpang tindih berdasarkan penampilan mereka, misalnya pandangan ditumpuk satu sama lain .

Technacron
sumber