Bagaimana cara mengatur posisi tampilan secara dinamis di Android?

102

Bagaimana cara mengubah posisi tampilan melalui kode? Seperti mengubah posisi X, Y nya. Apa itu mungkin?

Arun Badole
sumber

Jawaban:

117

Untuk apa pun di bawah Honeycomb (API Level 11), Anda harus menggunakan setLayoutParams(...).

Jika Anda dapat membatasi dukungan Anda untuk Honeycomb dan up Anda dapat menggunakan setX(...), setY(...), setLeft(...), setTop(...), dll

Dave yang mudah rusak
sumber
40
dari dokumen setTop () developer.android.com/reference/android/view/… : 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.- jadi mungkin itu bukan ide yang bagus;)
katzenhut
47

Ya, Anda dapat mengatur posisi tampilan secara dinamis di Android. Begitu juga anda memiliki ImageViewin LinearLayoutpada file xml anda, jadi anda bisa mengatur posisinya melalui LayoutParams.tapi pastikan untuk mengambil LayoutParamssesuai dengan layout yang diambil pada file xml anda, ada yang berbeda LayoutParamssesuai dengan layout yang diambil.

Berikut kode untuk disetel:

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

Saya harap ini akan membantu Anda untuk mengatur posisi.

AkashG
sumber
15
perhatikan juga bahwa Anda harus mengimpor android.widget.LinearLayout.LayoutParams; karena default-nya adalah LayoutParams ViewGroup
David T.
Sepertinya ini tidak berfungsi di Android 8+. apakah Anda pernah menghadapi masalah serupa?
MyFlashLab
Tahu mengapa para perancang Andriod bersusah payah untuk mencegah pembuat program menggunakan X, Y untuk memposisikan sesuatu. Akhirnya semuanya harus ditarik seperti itu. Ini menunjukkan bahwa Android dirancang oleh orang yang tidak bisa membuat kode.
Paul McCarthy
33

Sudah ada jawaban valid yang berbeda, tetapi tampaknya tidak ada yang menyarankan dengan tepat metode mana yang akan digunakan dalam hal ini, kecuali untuk batasan level API yang sesuai:

  • Jika Anda bisa menunggu siklus tata letak dan grup tampilan induk mendukung MarginLayoutParams(atau subclass), setel marginLeft/ marginTopsesuai.

  • Jika Anda perlu mengubah posisi segera dan terus-menerus (misalnya untuk jangkar PopupMenu), panggil tambahan layout(l, t, r, b)dengan koordinat yang sama. Ini mendahului apa yang akan dikonfirmasi oleh sistem tata letak nanti.

  • Untuk perubahan langsung (sementara) (seperti animasi), gunakan setX()/ setY()sebagai gantinya. Dalam kasus di mana ukuran induk tidak bergantung pada WRAP_CHILDREN, mungkin tidak masalah untuk menggunakan setX()/ setY()secara eksklusif.

  • Jangan pernah menggunakan setLeft()/ setRight()/ setBottom()/ setTop(), lihat di bawah.

Latar belakang : Kolom mLeft/ mTop/ mBottom/ mRightdiisi dari LayoutParams terkait di layout (). Tata letak dipanggil secara implisit dan asinkron oleh sistem tata letak tampilan Android. Dengan demikian, pengaturan MarginLayoutParamstampaknya menjadi cara yang paling aman dan terbersih untuk mengatur posisi secara permanen. Namun, kelambatan tata letak asynchronous mungkin menjadi masalah dalam beberapa kasus, misalnya saat menggunakan View untuk merender kursor, dan seharusnya diposisikan ulang dan berfungsi sebagai jangkar PopupMenu pada saat yang sama. Dalam hal ini, menelepon layout()bekerja dengan baik untuk saya.

Masalah dengan setLeft()dan setTop()adalah:

  • Memanggil mereka saja tidak cukup - Anda juga perlu menelepon setRight()dan setBottom()untuk menghindari meregangkan atau mengecilkan tampilan.

  • Implementasi metode ini terlihat relatif kompleks (= melakukan beberapa pekerjaan untuk memperhitungkan perubahan ukuran tampilan yang disebabkan oleh masing-masing metode)

  • Tampaknya menyebabkan masalah aneh dengan bidang masukan: Keyboard numerik lunak EditText terkadang tidak mengizinkan digit

setX()dan setY()bekerja di luar sistem tata letak, dan nilai terkait diperlakukan sebagai offset tambahan ke nilai kiri / atas / bawah / kanan yang ditentukan oleh sistem tata letak, yang menggeser tampilan sesuai kebutuhan. Mereka tampaknya telah ditambahkan untuk animasi (di mana efek langsung tanpa melalui siklus tata letak diperlukan).

Stefan Haustein
sumber
Halo Stefan. Bisakah Anda memberi saran beberapa buku atau artikel di mana saya dapat memahami cara kerja sistem tata letak android. Saya memahami bahwa urutan panggilan layout () onMeasure () onDraw (), tetapi ingin mengetahuinya lebih detail. Terima kasih sebelumnya
Sergey Brazhnik
Sayangnya saya tidak bisa - referensi terbaik dan paling pasti tampaknya adalah kode sumber Android yang sebenarnya O :)
Stefan Haustein
Saya menggunakan setY untuk mengubah tampilan, itu berubah di siklus tata letak berikutnya, tidak langsung?
sinyal
Bagaimana Anda menentukan ini?
Stefan Haustein
Itu worth menunjukkan bahwa marginLeftdapat diatur dengan menggunakan setLayoutParamsdengan new FrameLayout.LayoutParams(width, height)di mana Anda mengaturmarginLeft
lucidbrot
18

Ada pustaka yang disebut NineOldAndroids , yang memungkinkan Anda menggunakan pustaka animasi Honeycomb hingga versi satu.

Ini berarti Anda dapat menentukan kiri, kanan, terjemahanX / Y dengan antarmuka yang sedikit berbeda.

Berikut cara kerjanya:

ViewHelper.setTranslationX(view, 50f);

Anda cukup menggunakan metode statis dari kelas ViewHelper, meneruskan tampilan dan nilai mana pun yang ingin Anda setel.

Ben
sumber
16

Saya akan merekomendasikan penggunaan setTranslationXdan setTranslationY. Saya baru saja memulai ini sendiri, tetapi ini tampaknya cara yang paling aman dan disukai untuk memindahkan tampilan. Saya kira itu sangat tergantung pada apa yang sebenarnya Anda coba lakukan, tetapi ini bekerja dengan baik untuk saya untuk animasi 2D.

brianmearns
sumber
13

Anda dapat mencoba menggunakan metode berikut, jika Anda menggunakan HoneyComb Sdk (API Level 11).

view.setX(float x);

Parameter x adalah posisi x visual dari tampilan ini.

view.setY(float y);

Parameter y adalah posisi visual y dari tampilan ini.

Saya harap ini akan membantu Anda. :)

Nasi ayam
sumber
4
Saya sedang mengerjakan 2.2 Froyo dan metode ini tidak tersedia di dalamnya.
Arun Badole
7

Untuk dukungan untuk semua tingkat API Anda dapat menggunakan hal seperti ini:

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);
Orr
sumber
Karena dia ingin mengubah posisi dan solusi di atas lebih baik dan tidak perlu animasi
FireZenk
Selain itu, terjemahan dapat menyebabkan tampilan (sebagian) di luar layar
mewa
4

Setel posisi kiri tampilan ini relatif terhadap induknya:

view.setLeft(int leftPosition);

Setel posisi kanan tampilan ini relatif terhadap induknya:

view.setRight(int rightPosition);

Setel posisi teratas tampilan ini relatif terhadap induknya:

view.setTop(int topPosition);

Setel posisi bawah tampilan ini relatif terhadap induknya:

view.setBottom(int bottomPositon);

Metode di atas digunakan untuk mengatur posisi tampilan terkait dengan induknya.

Balaji.K
sumber
Maaf Metode ini tidak tersedia. Bisakah Anda mengirimkan saya kode?
Arun Badole
4
"Metode ini dimaksudkan untuk dipanggil oleh sistem tata letak dan umumnya tidak boleh dipanggil sebaliknya, karena properti dapat diubah kapan saja oleh tata letak."
GDanger
4

Gunakan LayoutParams. Jika Anda menggunakan LinearLayout Anda harus mengimpor android.widget.LinearLayout.LayoutParams, jika tidak impor versi LayoutParams yang tepat untuk tata letak yang Anda gunakan, atau itu akan menyebabkan ClassCastException , kemudian:

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

NB: Perhatikan bahwa Anda juga dapat menggunakan imageView.setLeft (int dim), TAPI INI TIDAK AKAN mengatur posisi komponen, ini hanya akan mengatur posisi batas kiri komponen, sisanya akan tetap pada posisi yang sama .

Alessandro Muzzi
sumber
jadi bagaimana kita bisa memindahkan tampilan ke posisi tertentu tanpa mempengaruhi tampilan asli?
James
Saya tidak yakin saya mengerti masalah Anda karena jika Anda ingin memindahkan tampilan, Anda akan mengubahnya dengan fakta Anda memindahkannya. Bagaimanapun, jika Anda ingin memindahkan tampilan ke yang lain secara independen darinya, Anda mungkin memerlukan tampilan FrameLayout untuk membersihkan tata letak utama Anda, lalu di dalamnya, Anda dapat menempatkan tampilan independen Anda (jelas jika Anda ingin itu bergerak di bawah tampilan utama Anda. harus menempatkan FrameLayout sebelum yang utama)
Alessandro Muzzi
3

Gunakan RelativeLayout, letakkan tampilan Anda di dalamnya, dapatkan RelativeLayout.LayoutParamsobjek dari tampilan Anda dan atur margin sesuai kebutuhan. Kemudian panggil requestLayout()pandangan Anda. Ini satu-satunya cara saya tahu.

glodos
sumber
1

Saya menemukan bahwa @Stefan Haustein sangat mirip dengan pengalaman saya, tetapi tidak yakin 100%. Saran saya adalah:

  • setLeft()/ setRight()/ setBottom()/ setTop()terkadang tidak berfungsi.
  • Jika Anda ingin mengatur posisi sementara (misalnya untuk melakukan animasi, tidak terpengaruh hierarki) saat tampilan ditambahkan dan ditampilkan , cukup gunakan setX()/setY() sebagai gantinya. (Anda mungkin ingin mencari lebih banyak perbedaan setLeft()dansetX() )
  • Dan perhatikan bahwa X, Y tampaknya absolut, dan didukung oleh AbsoluteLayout yang sekarang sudah tidak digunakan lagi. Jadi, Anda merasa X, Y sepertinya tidak didukung lagi. Dan ya, memang benar, tetapi hanya sebagian. Artinya jika view Anda ditambahkan, setX (), setY () akan bekerja dengan sempurna ; sebaliknya, saat Anda mencoba menambahkan tampilan ke tata letak grup tampilan (misalnya FrameLayout, LinearLayout, RelativeLayout), Anda harus menyetel LayoutParams dengan marginLeft, sebagai gantinya marginTop (setX (), setY () dalam hal ini terkadang tidak berfungsi).
  • Menetapkan posisi tampilan dengan marginLeft dan marginTop adalah proses yang tidak tersinkronisasi . Jadi perlu sedikit waktu untuk memperbarui hierarki . Jika Anda menggunakan tampilan langsung setelah mengatur margin untuk itu, Anda mungkin mendapatkan nilai yang salah .
Nguyen Tan Dat
sumber
0

Satu hal yang perlu diingat terkait pemosisian adalah bahwa setiap tampilan memiliki indeks yang relatif terhadap tampilan induknya. Jadi jika Anda memiliki layout linier dengan tiga subview, masing-masing subview akan memiliki indeks: 0, 1, 2 dalam kasus di atas.

Ini memungkinkan Anda menambahkan tampilan ke posisi terakhir (atau akhir) dalam tampilan induk dengan melakukan sesuatu seperti ini:

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

Atau Anda dapat mengganti tampilan menggunakan sesuatu seperti berikut:

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

parentView.addView(newView, childIndex);
Braden Holt
sumber