Saya membuat semua elemen dalam proyek android saya secara dinamis. Saya mencoba mendapatkan lebar dan tinggi tombol sehingga saya dapat memutar tombol itu. Saya hanya mencoba belajar bagaimana bekerja dengan bahasa android. Namun, mengembalikan 0.
Saya melakukan riset dan saya melihat bahwa itu perlu dilakukan di tempat lain selain di onCreate()
metode. Jika seseorang bisa memberi saya contoh bagaimana melakukannya, itu akan bagus.
Ini kode saya saat ini:
package com.animation;
import android.app.Activity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;
public class AnimateScreen extends Activity {
//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(30, 20, 30, 0);
Button bt = new Button(this);
bt.setText(String.valueOf(bt.getWidth()));
RotateAnimation ra = new RotateAnimation(0,360,bt.getWidth() / 2,bt.getHeight() / 2);
ra.setDuration(3000L);
ra.setRepeatMode(Animation.RESTART);
ra.setRepeatCount(Animation.INFINITE);
ra.setInterpolator(new LinearInterpolator());
bt.startAnimation(ra);
ll.addView(bt,layoutParams);
setContentView(ll);
}
Bantuan apa pun dihargai.
sumber
Masalah dasarnya adalah, Anda harus menunggu fase menggambar untuk pengukuran aktual (terutama dengan nilai dinamis seperti
wrap_content
ataumatch_parent
), tetapi biasanya fase ini belum selesaionResume()
. Jadi Anda perlu solusi untuk menunggu fase ini. Ada beberapa solusi yang mungkin untuk ini:1. Dengarkan Draw / Layout Events: ViewTreeObserver
ViewTreeObserver dipecat untuk berbagai peristiwa menggambar. Biasanya
OnGlobalLayoutListener
adalah apa yang Anda inginkan untuk mendapatkan pengukuran, sehingga kode di pendengar akan dipanggil setelah fase tata letak, sehingga pengukuran siap:Catatan: Pendengar akan segera dihapus karena jika tidak maka akan menyala pada setiap acara tata letak. Jika Anda harus mendukung aplikasi SDK Lvl <16 gunakan ini untuk membatalkan pendaftaran pendengar:
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. Tambahkan runnable ke antrian tata letak: View.post ()
Tidak terlalu terkenal dan solusi favorit saya. Pada dasarnya cukup gunakan metode posting View dengan runnable Anda sendiri. Ini pada dasarnya mengantri kode Anda setelah ukuran tampilan, tata letak, dll. Seperti yang dinyatakan oleh Romain Guy :
Contoh:
Keuntungan lebih dari
ViewTreeObserver
:Referensi:
3. Timpa Metode onLayout Views
Ini hanya praktis dalam situasi tertentu ketika logika dapat diringkas dalam pandangan itu sendiri, jika tidak, ini adalah sintaksis yang sangat verbose dan rumit.
Selain itu, onLayout akan dipanggil berkali-kali, jadi pertimbangkan apa yang Anda lakukan dalam metode ini, atau nonaktifkan kode Anda setelah pertama kali
4. Periksa apakah telah melalui fase tata letak
Jika Anda memiliki kode yang menjalankan beberapa kali saat membuat ui Anda bisa menggunakan metode lib dukungan v4 berikut:
Tambahan: Mendapatkan pengukuran yang ditentukan secara statis
Jika cukup untuk mendapatkan tinggi / lebar yang ditentukan secara statis, Anda bisa melakukan ini dengan:
View.getMeasuredWidth()
View.getMeasuredHeigth()
Tapi ingat, ini mungkin berbeda dengan lebar / tinggi sebenarnya setelah menggambar. Javadoc menjelaskan perbedaan dengan sempurna:
sumber
runOnUiThread(new Runnable() {...}
. Saat ini saya menggunakan variasi dari metode 1:addOnLayoutChangeListener
. Jangan lupa untuk menghapusnya lalu di dalam: removeOnLayoutChangeListener. Ini bekerja dari utas latar juga.android:visibility="gone"
, dan di proyek lain properti visibilitas adalahinvisible
. Jika visibilitas adalahgone
lebarnya akan selalu 0.Kita bisa menggunakan
sumber
Saya menggunakan solusi ini, yang menurut saya lebih baik daripada onWindowFocusChanged (). Jika Anda membuka DialogFragment, kemudian memutar telepon, onWindowFocusChanged akan dipanggil hanya ketika pengguna menutup dialog):
Sunting: karena removeGlobalOnLayoutListener sudah tidak digunakan lagi, sekarang Anda harus melakukan:
sumber
Seperti yang dinyatakan Ian dalam utas Pengembang Android ini :
sumber
Bottom line, if you call getWidth() etc. in a constructor, it will return zero.
itu bingo. Akar masalah saya.Jika Anda perlu mendapatkan lebar beberapa widget sebelum ditampilkan di layar, Anda dapat menggunakan getMeasuredWidth () atau getMeasuredHeight ().
sumber
Saya lebih suka menggunakan
OnPreDrawListener()
alih-alihaddOnGlobalLayoutListener()
, karena ini disebut sedikit lebih awal dari pendengar lainnya.sumber
return false
berarti untuk membatalkan izin menggambar saat ini . Untuk melanjutkan,return true
sebagai gantinya.Ekstensi Kotlin untuk mengamati tata letak global dan melakukan tugas yang diberikan ketika ketinggian siap secara dinamis.
Pemakaian:
Penerapan:
sumber
AndroidX memiliki beberapa fungsi ekstensi yang membantu Anda dengan pekerjaan semacam ini, di dalam
androidx.core.view
Anda perlu menggunakan Kotlin untuk ini.
Salah satu yang paling cocok di sini adalah
doOnLayout
:Dalam contoh Anda:
Ketergantungan:
androidx.core:core-ktx:1.0.0
sumber
Satu liner jika Anda menggunakan RxJava & RxBindings . Pendekatan serupa tanpa boilerplate. Ini juga memecahkan peretasan untuk menekan peringatan seperti dalam jawaban oleh Tim Autin .
Ini dia. Tidak perlu berhenti berlangganan, bahkan jika tidak pernah menelepon.
sumber
Itu terjadi karena pandangan perlu lebih banyak waktu untuk digembungkan. Jadi, alih-alih menelepon
view.width
danview.height
di utas utama, Anda harus menggunakanview.post { ... }
untuk memastikan bahwa Andaview
telah meningkat. Di Kotlin:Di Jawa, Anda juga dapat memanggil
getWidth()
dangetHeight()
metode dalamRunnable
dan meneruskan metodeRunnable
keview.post()
.sumber
.post
tidak menjamin tampilan ditata.Tinggi dan lebar adalah nol karena tampilan belum dibuat pada saat Anda meminta tinggi dan lebar. Salah satu solusi paling sederhana adalah
Metode ini baik dibandingkan dengan metode lain karena pendek dan garing.
sumber
Mungkin ini membantu seseorang:
Buat fungsi ekstensi untuk kelas Lihat
Ini kemudian dapat digunakan pada tampilan apa pun dengan:
sumber
Jawab dengan
post
salah, karena ukurannya mungkin tidak dihitung ulang.Hal penting lainnya adalah bahwa pandangan dan semua leluhurnya harus terlihat . Untuk itu saya menggunakan properti
View.isShown
.Inilah fungsi kotlin saya, yang dapat ditempatkan di suatu tempat di utils:
Dan penggunaannya adalah:
sumber
Jika Anda menggunakan Kotlin
sumber
Tampilan yang hilang mengembalikan 0 sebagai tinggi jika aplikasi di latar belakang. Ini kode saya (1oo% berfungsi)
sumber
Kita perlu menunggu tampilan akan ditarik. Untuk tujuan ini gunakan OnPreDrawListener. Contoh Kotlin:
sumber