Saya telah menyiapkan ViewPager sederhana yang memiliki ImageView dengan ketinggian 200dp pada setiap halaman.
Ini pager saya:
pager = new ViewPager(this);
pager.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
pager.setBackgroundColor(Color.WHITE);
pager.setOnPageChangeListener(listener);
layout.addView(pager);
Meskipun tingginya diatur sebagai wrap_content, pager selalu mengisi layar meskipun imageview hanya 200dp. Saya mencoba mengganti ketinggian pager dengan "200" tetapi itu memberi saya hasil yang berbeda dengan beberapa resolusi. Saya tidak dapat menambahkan "dp" ke nilai itu. Bagaimana cara menambahkan 200dp ke tata letak pager?
Jawaban:
Mengesampingkan Pengukuran Anda
ViewPager
sebagai berikut akan membuatnya mendapatkan ketinggian anak terbesar yang saat ini dimiliki.sumber
Solusi lain yang lebih umum adalah
wrap_content
untuk hanya bekerja.Saya telah memperluas
ViewPager
untuk menimpaonMeasure()
. Ketinggiannya melingkari pandangan anak pertama. Ini dapat menyebabkan hasil yang tidak terduga jika tampilan anak tidak persis sama tingginya. Untuk itu kelas dapat diperpanjang dengan mudah, katakanlah beranimasi dengan ukuran tampilan / halaman saat ini. Tapi aku tidak butuh itu.Anda dapat menggunakan ViewPager ini dalam tata letak XML Anda seperti halnya ViewPager asli:
Keuntungan: Pendekatan ini memungkinkan penggunaan ViewPager dalam tata letak apa pun termasuk RelativeLayout untuk melapisi elemen ui lainnya.
Satu kelemahan tetap: Jika Anda ingin menggunakan margin, Anda harus membuat dua tata letak bersarang dan memberikan margin dalam yang diinginkan.
Ini kodenya:
sumber
Saya mendasarkan jawaban saya pada Daniel López Lacalle dan posting ini http://www.henning.ms/2013/09/09/viewpager-that-simply-dont-measure-up/ . Masalah dengan jawaban Daniel adalah bahwa dalam beberapa kasus anak-anak saya memiliki tinggi nol. Solusinya adalah mengukur dua kali.
Ini juga memungkinkan Anda mengatur ketinggian pada ViewPager jika Anda mau atau hanya wrap_content.
sumber
scaleType
dan sama,layout_width=match_parent
sertalayout_height=wrap_content
? ada seperti 20dp yang hilang di sana.// super has to be called in the beginning so the child views can be initialized.
<----- ITULAH alasannya, harus menyebutnya di awal dan di akhir fungsi onMeasure. Yippiii, balita tinggi virtual pada saya hari ini!Saya baru saja menjawab pertanyaan yang sangat mirip tentang ini, dan kebetulan menemukan ini ketika mencari tautan untuk mendukung klaim saya, sangat beruntung Anda :)
Jawaban saya yang lain:
ViewPager tidak mendukung
wrap_content
karena (biasanya) tidak pernah memuat semua anak-anaknya secara bersamaan, dan karena itu tidak dapat memperoleh ukuran yang sesuai (pilihannya adalah memiliki pager yang mengubah ukuran setiap kali Anda beralih halaman).Namun Anda dapat mengatur dimensi yang tepat (misalnya 150dp) dan
match_parent
berfungsi juga.Anda juga dapat memodifikasi dimensi secara dinamis dari kode Anda dengan mengubah
height
-atribusi di dalamnyaLayoutParams
.Untuk kebutuhan Anda, Anda dapat membuat ViewPager dalam file xml-nya sendiri, dengan layout_height diatur ke 200dp, dan kemudian dalam kode Anda, daripada membuat ViewPager baru dari awal, Anda dapat mengembang file xml itu:
sumber
layout_height
set kewrap_content
, tetapi bahkan lebih buruk karena solusi sederhana untuk mengaturnya ke jumlah yang tetap tidak berfungsi.Menggunakan jawaban Daniel López Localle , saya membuat kelas ini di Kotlin. Semoga ini menghemat lebih banyak waktu
sumber
Saya telah menghadapi masalah ini di beberapa proyek dan tidak pernah memiliki solusi yang lengkap. Jadi saya membuat proyek github WrapContentViewPager sebagai pengganti di tempat untuk ViewPager.
https://github.com/rnevet/WCViewPager
Solusi ini terinspirasi oleh beberapa jawaban di sini, tetapi meningkatkan pada:
Diperbarui untuk dukungan perpustakaan versi 24 yang melanggar implementasi sebelumnya.
sumber
Saya baru saja bertemu dengan masalah yang sama. Saya punya ViewPager dan saya ingin menampilkan iklan di tombol itu. Solusi yang saya temukan adalah memasukkan pager ke dalam RelativeView dan mengatur layout_above ke id tampilan yang ingin saya lihat di bawahnya. itu berhasil untuk saya.
di sini adalah tata letak XML saya:
sumber
Saya juga mengalami masalah ini, tetapi dalam kasus saya saya punya
FragmentPagerAdapter
yang memasokViewPager
dengan halaman-halamannya. Masalah yang saya miliki adalah bahwaonMeasure()
dari yangViewPager
dipanggil sebelum salah satuFragments
telah dibuat (dan karena itu tidak dapat mengukur sendiri dengan benar).Setelah sedikit trial and error, saya menemukan bahwa
finishUpdate()
metode FragmentPagerAdapter dipanggil setelahFragments
diinisialisasi (dariinstantiateItem()
dalamFragmentPagerAdapter
), dan juga setelah / selama pengguliran halaman. Saya membuat antarmuka kecil:yang saya sampaikan ke
FragmentPagerAdapter
dan menelepon saya :yang pada gilirannya memungkinkan saya untuk memanggil implementasi
setVariableHeight()
sayaCustomViewPager
:Saya tidak yakin itu adalah pendekatan terbaik, akan suka komentar jika Anda pikir itu baik / buruk / jahat, tetapi tampaknya bekerja dengan sangat baik dalam implementasi saya :)
Semoga ini bisa membantu seseorang di luar sana!
Suntingan: Saya lupa menambahkan
requestLayout()
setelah meneleponsuper.measure()
(jika tidak mengubah tampilan).Saya juga lupa menambahkan padding orang tua ke ketinggian akhir.
Saya juga menjatuhkan menjaga lebar / tinggi asli MeasureSpecs demi menciptakan yang baru seperti yang diperlukan. Telah memperbarui kode yang sesuai.
Masalah lain yang saya miliki adalah bahwa ukurannya tidak benar dalam
ScrollView
dan menemukan pelakunya mengukur anak denganMeasureSpec.EXACTLY
bukannyaMeasureSpec.UNSPECIFIED
. Diperbarui untuk mencerminkan ini.Semua perubahan ini telah ditambahkan ke kode. Anda dapat memeriksa riwayat untuk melihat versi lama (salah) jika Anda mau.
sumber
Solusi lain adalah memperbarui
ViewPager
ketinggian sesuai dengan tinggi halaman saat ini diPagerAdapter
. Dengan asumsi bahwa Anda membuatViewPager
halaman Anda dengan cara ini:Di mana
mPages
daftar internalPageInfo
struktur ditambahkan secara dinamis kePagerAdapter
danCustomImageView
hanya biasaImageView
denganonMeasure()
metode overriden yang mengatur ketinggiannya sesuai dengan lebar yang ditentukan dan menjaga rasio aspek gambar.Anda dapat memaksa
ViewPager
ketinggian dengansetPrimaryItem()
metode:Perhatikan
Math.max(height, 1)
. Itu memperbaiki bug yang mengganggu yangViewPager
tidak memperbarui halaman yang ditampilkan (menunjukkannya kosong), ketika halaman sebelumnya memiliki tinggi nol (yaitu null dapat ditarik diCustomImageView
), masing-masing menggesek bolak-balik antara dua halaman.sumber
item.mImageView.measure(..)
untuk mendapatkan dimensi yang benar dalamgetMeasuredXXX()
metode.Saat menggunakan konten statis di dalam viewpager dan Anda tidak menginginkan animasi mewah, Anda dapat menggunakan pager tampilan berikut
sumber
sumber
Dari kode sumber aplikasi Android Popcorn time saya menemukan solusi ini yang secara dinamis menyesuaikan ukuran viewpager dengan animasi yang bagus tergantung pada ukuran anak saat ini.
https://git.popcorntime.io/popcorntime/android/blob/5934f8d0c8fed39af213af4512272d12d2efb6a6/mobile/src/main/java/pct/droid/widget/WrappingViewPager.java
sumber
Jika Anda membutuhkan ViewPager yang menyesuaikan ukurannya untuk setiap anak , bukan hanya yang terbesar, saya telah menulis sepotong kode yang melakukannya. Perhatikan bahwa tidak ada animasi pada perubahan itu (tidak perlu dalam kasus saya)
android: bendera minHeight juga didukung.
sumber
Jawaban Daniel López Lacalle yang ditingkatkan , ditulis ulang di Kotlin :
sumber
Saya bertemu dengan masalah yang sama, dan saya juga harus membuat ViewPager membungkus isinya ketika pengguna menggulir di antara halaman. Menggunakan jawaban cybergen di atas, saya mendefinisikan metode onMeasure sebagai berikut:
Dengan cara ini, metode onMeasure menetapkan ketinggian halaman saat ini yang ditampilkan oleh ViewPager.
sumber
Tidak ada yang disarankan di atas bekerja untuk saya. Kasing penggunaan saya memiliki 4 ViewPager khusus di
ScrollView
. Atas mereka diukur berdasarkan aspek rasio dan sisanya baru sajalayout_height=wrap_content
. Saya sudah mencoba solusi cybergen , Daniel López Lacalle . Tak satu pun dari mereka bekerja sepenuhnya untuk saya.Dugaan saya mengapa cybergen tidak berfungsi pada halaman> 1 adalah karena ia menghitung tinggi pager berdasarkan halaman 1, yang disembunyikan jika Anda menggulir lebih jauh.
Baik saran cybergen dan Daniel López Lacalle memiliki perilaku aneh dalam kasus saya: 2 dari 3 dimuat ok dan 1 tinggi acak adalah 0. Muncul yang
onMeasure
dipanggil sebelum anak-anak dihuni. Jadi saya datang dengan campuran 2 jawaban ini + perbaikan saya sendiri:Ide adalah membiarkan
ViewPager
menghitung dimensi anak-anak dan menyimpan tinggi halaman pertama yang dihitung dalam tata letak paramsViewPager
. Jangan lupa untuk mengatur ketinggian tata letak fragmen kewrap_content
sebaliknya Anda bisa mendapatkan tinggi = 0. Saya sudah menggunakan yang ini:Harap perhatikan bahwa solusi ini berfungsi baik jika semua halaman Anda memiliki ketinggian yang sama . Kalau tidak, Anda perlu menghitung ulang
ViewPager
tinggi berdasarkan anak aktif saat ini. Saya tidak membutuhkannya, tetapi jika Anda menyarankan solusinya, saya akan dengan senang hati memperbarui jawabannya.sumber
Untuk orang-orang yang memiliki masalah dan pengodean untuk Xamarin Android di C #, ini mungkin juga solusi cepat:
Ini terutama berguna jika pandangan anak Anda memiliki ketinggian yang sama. Kalau tidak, Anda akan diminta untuk menyimpan semacam nilai "minimumHeight" di atas semua anak yang Anda periksa, dan bahkan kemudian Anda mungkin tidak ingin memiliki ruang kosong terlihat di bawah tampilan anak kecil Anda.
Solusinya sendiri tidak cukup untuk saya, tetapi itu karena item anak saya listViews dan MeasuredHeight mereka tidak dihitung dengan benar, tampaknya.
sumber
Saya memiliki versi WrapContentHeightViewPager yang berfungsi dengan benar sebelum API 23 yang akan mengubah ukuran basis ketinggian tampilan induk pada tampilan anak saat ini yang dipilih.
Setelah memutakhirkan ke API 23, itu berhenti bekerja. Ternyata solusi lama itu digunakan
getChildAt(getCurrentItem())
untuk mendapatkan tampilan anak saat ini untuk mengukur yang tidak berfungsi. Lihat solusinya di sini: https://stackoverflow.com/a/16512217/1265583Di bawah ini berfungsi dengan API 23:
sumber
requestLayout()
begitu tingginya disesuaikan saat kita beralih dari satu tab ke tab lainnya. Apakah Anda ingat mengapasuper
perlu dipanggil dua kali? Saya perhatikan bahwa itu tidak akan berhasil sebaliknya.Kode di bawah ini adalah satu-satunya yang berfungsi untuk saya
1. Gunakan kelas ini untuk mendeklarasikan HeightWrappingViewPager:
2. Masukkan pager tampilan pembungkus tinggi ke file xml Anda:
3. Nyatakan pager tampilan Anda:
sumber
Saya mengedit jawaban cybergen untuk membuat viewpager untuk mengubah ketinggian, tergantung pada item yang dipilih. Kelasnya sama dengan cybergen, tapi saya menambahkan Vector bilangan bulat yang semua ketinggian viewpager anak-anak viewpager dan kita dapat mengaksesnya ketika halaman berubah untuk memperbarui ketinggian.
Ini kelasnya:
Kemudian dalam aktivitas Anda tambahkan OnPageChangeListener
Dan di sini adalah xml:
Harap perbaiki bahasa Inggris saya jika perlu
sumber
heights
Daftar dapat meningkatkan infinity.measure
akan dipanggil berkali-kali. Ini dapat meningkatkan daftar ketinggian. Situasi lain adalah pengguna dapat memanggilrequestLayout
(atausetLayoutParams
metode, seperti yang Anda lakukan) untuk viewPager ini secara manual, juga akan mengukur beberapa kali.Jika yang
ViewPager
Anda gunakan adalah anakScrollView
AND dan memilikiPagerTitleStrip
anak Anda harus menggunakan sedikit modifikasi dari jawaban-jawaban hebat yang telah disediakan. Untuk referensi XML saya terlihat seperti ini:Dalam Anda,
onMeasure
Anda harus MENAMBAH yang diukur dariPagerTitleStrip
jika ditemukan. Kalau tidak, tingginya tidak akan dianggap sebagai ketinggian terbesar dari semua anak meskipun membutuhkan ruang tambahan.Semoga ini bisa membantu orang lain. Maaf itu sedikit peretasan ...
sumber
Sebagian besar solusi yang saya lihat di sini tampaknya melakukan pengukuran ganda: pertama mengukur pandangan anak, dan kemudian memanggilnya
super.onMeasure()
Saya datang dengan kebiasaan
WrapContentViewPager
yang lebih efisien, bekerja dengan baik dengan RecyclerView dan FragmentAnda dapat memeriksa demo di sini:
github / ssynhtn / WrapContentViewPager
dan kode kelas di sini: WrapContentViewPager.java
sumber
Saya memiliki skenario yang serupa (tetapi lebih kompleks). Saya memiliki dialog, yang berisi ViewPager.
Salah satu halaman anak pendek, dengan tinggi statis.
Halaman anak lain harus selalu setinggi mungkin.
Halaman anak lain berisi ScrollView, dan halaman (dan dengan demikian seluruh dialog) harus WRAP_CONTENT jika konten ScrollView tidak memerlukan ketinggian penuh yang tersedia untuk dialog.
Tak satu pun dari jawaban yang ada bekerja sepenuhnya untuk skenario khusus ini. Tunggu - ini perjalanan yang bergelombang.
Terima kasih banyak kepada @Raanan untuk kode untuk mengukur tampilan dan mengukur tinggi dekorasi. Saya mengalami masalah dengan perpustakaannya - animasi tergagap, dan saya pikir ScrollView saya tidak akan bergulir ketika ketinggian dialog cukup pendek untuk membutuhkannya.
sumber
dalam kasus saya menambahkan
clipToPadding
memecahkan masalah.Bersulang!
sumber
Saya kasus saya menambahkan android: fillViewport = "true" menyelesaikan masalah
sumber
Dalam kasus saya, saya memerlukan viewpager dengan wrap_content untuk elemen dan animasi yang dipilih saat menerapkan ukuran. Di bawah ini Anda dapat melihat implementasi saya. Adakah yang bisa berguna.
Tambahkan attrs.xml dalam proyek:
Dan gunakan:
sumber
ViewPager ini hanya mengubah ukuran ke anak yang terlihat saat ini (bukan yang terbesar dari anak yang sebenarnya)
Ide dari https://stackoverflow.com/a/56325869/4718406
}
sumber
Ukur ketinggian ViewPager:
panggilan setPrimaryView (Lihat) :
sumber
Berikan tata letak induk ViewPager sebagai
NestedScrollView
Jangan lupa mengatur
android:fillViewport="true"
Ini akan memperluas scrollview dan konten anaknya untuk mengisi viewport.
https://developer.android.com/reference/android/widget/ScrollView.html#attr_android:fillViewport
sumber
Anda dapat beralih ke ViewPager2. Ini adalah versi terbaru dari ViewPager. Itu melakukan hal yang sama seperti ViewPager tetapi dengan cara yang lebih cerdas dan efisien. ViewPager2 hadir dengan beragam fitur baru. Tentu saja masalah Bungkus Konten telah diselesaikan oleh ViewPager2.
Dari Android docs: "ViewPager2 menggantikan ViewPager, menangani sebagian besar titik nyeri pendahulunya, termasuk dukungan tata letak kanan-ke-kiri, orientasi vertikal, koleksi Fragmen yang dapat dimodifikasi, dll."
Saya merekomendasikan artikel ini untuk pemula:
https://medium.com/google-developer-experts/exploring-the-view-pager-2-86dbce06ff71
sumber