Saya memiliki bagian UIImageView
dalam UIScrollView
yang saya gunakan untuk memperbesar dan menggulir. Jika gambar / konten tampilan gulir lebih besar dari tampilan gulir, semuanya berfungsi dengan baik. Namun, ketika gambar menjadi lebih kecil dari tampilan gulir, itu menempel ke sudut kiri atas tampilan gulir. Saya ingin membuatnya tetap terpusat, seperti aplikasi Foto.
Adakah ide atau contoh tentang menjaga konten yang UIScrollView
terpusat saat lebih kecil?
Saya bekerja dengan iPhone 3.0.
Kode berikut hampir berfungsi. Gambar kembali ke sudut kiri atas jika saya menjepitnya setelah mencapai tingkat zoom minimum.
- (void)loadView {
[super loadView];
// set up main scroll view
imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
[imageScrollView setBackgroundColor:[UIColor blackColor]];
[imageScrollView setDelegate:self];
[imageScrollView setBouncesZoom:YES];
[[self view] addSubview:imageScrollView];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"WeCanDoIt.png"]];
[imageView setTag:ZOOM_VIEW_TAG];
[imageScrollView setContentSize:[imageView frame].size];
[imageScrollView addSubview:imageView];
CGSize imageSize = imageView.image.size;
[imageView release];
CGSize maxSize = imageScrollView.frame.size;
CGFloat widthRatio = maxSize.width / imageSize.width;
CGFloat heightRatio = maxSize.height / imageSize.height;
CGFloat initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
[imageScrollView setMinimumZoomScale:initialZoom];
[imageScrollView setZoomScale:1];
float topInset = (maxSize.height - imageSize.height) / 2.0;
float sideInset = (maxSize.width - imageSize.width) / 2.0;
if (topInset < 0.0) topInset = 0.0;
if (sideInset < 0.0) sideInset = 0.0;
[imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}
/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
// END Bug workaround
CGSize maxSize = imageScrollView.frame.size;
CGSize viewSize = view.frame.size;
float topInset = (maxSize.height - viewSize.height) / 2.0;
float sideInset = (maxSize.width - viewSize.width) / 2.0;
if (topInset < 0.0) topInset = 0.0;
if (sideInset < 0.0) sideInset = 0.0;
[imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}
Jawaban:
Saya punya solusi yang sangat sederhana! Yang Anda butuhkan adalah memperbarui pusat subview Anda (imageview) saat memperbesar di ScrollViewDelegate. Jika gambar yang diperbesar lebih kecil dari scrollview maka sesuaikan pusat subview.center else adalah (0,0).
sumber
CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentInset.left - scrollView.contentInset.right - scrollView.contentSize.width) * 0.5, 0.0); CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentInset.top - scrollView.contentInset.bottom - scrollView.contentSize.height) * 0.5, 0.0);
zoomToRect:
. MenggunakancontentInset
pendekatan berfungsi lebih baik, jika Anda membutuhkan fungsi itu. Lihat petersteinberger.com/blog/2013/how-to-center-uiscrollview untuk detail lebih lanjut.@ EvelynCordner jawaban adalah yang paling berhasil di aplikasi saya. Kode jauh lebih sedikit daripada opsi lain juga.
Inilah versi Swift jika ada yang membutuhkannya:
sumber
Oke, saya telah memperjuangkan ini selama dua hari terakhir dan akhirnya dan akhirnya menemukan solusi yang cukup andal (sejauh ini ...) saya pikir saya harus membagikannya dan menyelamatkan orang lain dari rasa sakit. :) Jika Anda menemukan masalah dengan solusi ini, silakan berteriak!
Saya pada dasarnya telah melalui apa yang dimiliki orang lain: mencari StackOverflow, Forum Pengembang Apple, melihat kode untuk three20, ScrollingMadness, ScrollTestSuite, dll. Saya sudah mencoba memperbesar bingkai UIImageView, bermain dengan offset dan / atau insets UIScrollView. dari ViewController, dll. tetapi tidak ada yang berhasil (karena semua orang juga tahu).
Setelah tidur di atasnya, saya mencoba beberapa sudut alternatif:
Dengan metode UIScrollView subkelas ini, saya mengganti mutator contentOffset sehingga tidak menetapkan {0,0} ketika gambar diskalakan lebih kecil dari viewport - alih-alih pengaturan offset sehingga gambar akan tetap dipusatkan di viewport. Sejauh ini, sepertinya selalu berhasil. Saya telah memeriksanya dengan gambar yang lebar, tinggi, kecil & besar dan tidak memiliki masalah "berfungsi tapi jepit pada zoom minimum yang merusaknya".
Saya telah mengunggah contoh proyek ke github yang menggunakan solusi ini, Anda dapat menemukannya di sini: http://github.com/nyoron/NYOBetterZoom
sumber
anOffset.y = -(scrollViewSize.height - zoomViewSize.height) / 2.0
keanOffset.y = (-(scrollViewSize.height - zoomViewSize.height) / 2.0) + 10;
Kode ini harus bekerja pada sebagian besar versi iOS (dan telah diuji untuk bekerja pada 3.1 ke atas).
Ini didasarkan pada kode Apple WWDC untuk photoscoller.
Tambahkan di bawah ini ke subclass Anda dari UIScrollView, dan ganti tileContainerView dengan tampilan yang mengandung gambar atau ubin Anda:
sumber
UIScrollView
pendekatan subclass tampaknya lebih disukai: itu dipanggil ketika tampilan pertama kali ditampilkan + terus menerus saat zooming sedang berlangsung (sedangkanscrollViewDidZoom
hanya dipanggil sekali per gulir dan setelah fakta)Untuk solusi yang lebih cocok untuk tampilan gulir yang menggunakan autolayout, gunakan inset konten tampilan gulir daripada memperbarui bingkai subview tampilan gulir Anda.
sumber
UIView
yang ada di dalamUIScrollview
ke pusat yang sama (view.center = scrollview.center;
) dan kemudian discrollViewDidZoom
setview.frame.origin
x
dany
ke0
lagi.dispatch_async
ke antrian utama diviewWillAppear
mana saya memanggilscrollViewDidZoom:
tampilan gulir utama saya. Ini membuat tampilan muncul dengan gambar tengah.viewDidLayoutSubviews
untuk memastikan sudah diatur dengan benar ketika tampilan menunjukkan pertama kali.Saat ini saya sedang subclassing
UIScrollView
dan overridingsetContentOffset:
untuk menyesuaikan offset berdasarkancontentSize
. Ini berfungsi baik dengan pinch dan zooming terprogram.Selain pendek dan manis, kode ini menghasilkan zoom yang jauh lebih mulus daripada solusi @Erdemus. Anda dapat melihatnya beraksi di demo RMGallery .
sumber
Saya menghabiskan satu hari berjuang dengan masalah ini, dan akhirnya menerapkan scrollViewDidEndZooming: withView: atScale: sebagai berikut:
Ini memastikan bahwa ketika gambar lebih kecil dari layar, masih ada ruang yang cukup di sekitarnya sehingga Anda dapat memposisikannya ke tempat yang Anda inginkan.
(dengan asumsi bahwa UIScrollView Anda berisi UIImageView untuk menampung gambar)
Pada dasarnya, apa yang dilakukan adalah memeriksa apakah lebar / tinggi tampilan gambar Anda lebih kecil dari lebar / tinggi layar, dan jika demikian, buat inset setengah lebar / tinggi layar (Anda mungkin bisa membuat ini lebih besar jika Anda ingin gambar tersebut keluar dari batas layar).
Perhatikan bahwa karena ini adalah metode UIScrollViewDelegate , jangan lupa untuk menambahkannya ke deklarasi pengontrol tampilan Anda, jadi untuk menghindari masalah build.
sumber
Apple telah merilis video sesi WWDC 2010 untuk semua anggota program pengembang iphone. Salah satu topik yang dibahas adalah bagaimana mereka membuat aplikasi foto !!! Mereka membangun aplikasi langkah demi langkah yang sangat mirip dan telah membuat semua kode tersedia secara gratis.
Itu tidak menggunakan api pribadi juga. Saya tidak dapat memasukkan kode apa pun di sini karena perjanjian non-pengungkapan, tetapi di sini ada tautan ke unduhan kode sampel. Anda mungkin harus masuk untuk mendapatkan akses.
http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?code=y&source=x&bundleID=20645
Dan, berikut ini tautan ke halaman iTunes WWDC:
http://insideapple.apple.com/redir/cbx-cgi.do?v=2&la=en&lc=&a=kGSol9sgPHP%2BtlWtLp%2BEP%2FnxnZarjWJglPBZRHd3oDbACudP51JNGS8KlsFgxZto9X%2BTsnqSbeUSWX0doe%2Fzv%2FN5XV55%2FomsyfRgFBysOnIVggO%2Fn2p%2BiweDK%2F%2FmsIXj
sumber
Ok, solusi ini bekerja untuk saya. Saya memiliki subkelas
UIScrollView
dengan referensi untukUIImageView
itu ditampilkan. Setiap kaliUIScrollView
zoom, properti contentSize disesuaikan. Di setter itulah saya mengatur skala denganUIImageView
tepat dan juga menyesuaikan posisi tengahnya.Lembur saya mengatur gambar pada
UIScrollView
saya mengubah ukurannya. TheUIScrollView
dalam scrollview juga merupakan kelas khusus yang saya buat.Dengan dua metode ini saya dapat memiliki tampilan yang berperilaku seperti aplikasi foto.
sumber
Cara saya melakukan ini adalah dengan menambahkan tampilan ekstra ke dalam hierarki:
Berikan
UIView
rasio aspek yang sama dengan AndaUIScrollView
, dan pusatkanUIImageView
ke dalam itu.sumber
Saya tahu beberapa jawaban di atas benar, tetapi saya hanya ingin memberikan jawaban saya dengan beberapa penjelasan, komentarnya akan membuat Anda mengerti mengapa kami menyukai ini.
Ketika saya memuat scrollView untuk pertama kalinya, saya menulis kode berikut untuk membuatnya menjadi pusat, perhatikan kami mengatur
contentOffset
terlebih dahulu, kemudiancontentInset
Lalu, ketika saya mencubit vContent, saya menulis kode berikut untuk membuatnya menjadi pusat.
sumber
Jika
contentInset
tidak diperlukan untuk hal lain, itu dapat digunakan untuk memusatkan konten scrollview.Keuntungan jika pendekatan ini adalah Anda masih dapat menggunakan
contentLayoutGuide
untuk menempatkan konten di dalam scrollviewatau cukup seret dan jatuhkan konten dalam Xcode's Interface Builder.
sumber
Anda bisa menonton
contentSize
properti UIScrollView (menggunakan mengamati kunci-nilai atau serupa), dan secara otomatis menyesuaikancontentInset
setiap kalicontentSize
perubahan menjadi kurang dari ukuran tampilan gulir.sumber
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
(dijelaskan di developer.apple.com/iphone/library/documentation/UIKit/... ), tetapi saya lebih suka mengamaticontentSize
karena jika tidak, Anda akhirnya membuang skala zoom baru dan tetap menemukannya dari tampilan. (Kecuali jika Anda dapat melakukan beberapa matematika luar biasa berdasarkan ukuran relatif dari pandangan Anda.)Salah satu cara elegan untuk memusatkan konten
UISCrollView
adalah ini.Tambahkan satu pengamat ke contentSize Anda
UIScrollView
, sehingga metode ini akan dipanggil setiap kali konten berubah ...Sekarang pada metode pengamat Anda:
Anda harus mengubah
[pointer viewWithTag:100]
. Ganti dengan tampilan konten AndaUIView
.imageGallery
menunjuk ke ukuran jendela Anda.Ini akan memperbaiki pusat konten setiap kali ukurannya berubah.
CATATAN: Satu-satunya cara konten ini tidak berfungsi dengan baik adalah dengan fungsionalitas zoom standar
UIScrollView
.sumber
Ini adalah solusi saya untuk masalah itu yang berfungsi cukup baik untuk segala jenis tampilan di dalam scrollview.
sumber
Ada banyak solusi di sini, tetapi saya berisiko mengambilnya di sini sendiri. Ini bagus karena dua alasan: ini tidak mengacaukan pengalaman pembesaran, seperti halnya memperbarui bingkai tampilan gambar yang sedang berlangsung, dan juga menghormati insets tampilan gulir asli (katakanlah, didefinisikan dalam xib atau storyboard untuk penanganan yang anggun dari toolbar semi-transparan dll) .
Pertama, tentukan pembantu kecil:
Untuk mempertahankan inset asli, bidang yang ditentukan:
Dan di suatu tempat di viewDidLoad, isi:
Untuk menempatkan UIImageView ke dalam UIScrollView (dengan asumsi UIImage itu sendiri ada di loadImage var):
scrollViewDidZoom: dari UIScrollViewDelegate untuk tampilan gulir itu:
Akhirnya, berpusat pada dirinya sendiri:
Saya belum menguji perubahan orientasi (yaitu reaksi yang tepat untuk mengubah ukuran UIScrollView sendiri), tetapi memperbaikinya harus relatif mudah.
sumber
Anda akan menemukan bahwa solusi yang diposting oleh Erdemus berfungsi, tetapi ... Ada beberapa kasus di mana metode scrollViewDidZoom tidak dipanggil & gambar Anda macet di sudut kiri atas. Solusi sederhana adalah dengan secara eksplisit memanggil metode ketika Anda awalnya menampilkan gambar, seperti ini:
Dalam banyak kasus, Anda mungkin menggunakan metode ini dua kali, tetapi ini adalah solusi yang lebih bersih daripada beberapa jawaban lain dalam topik ini.
sumber
Contoh Penggulung Foto Apple melakukan persis seperti yang Anda cari. Letakkan ini di Subclass UIScrollView Anda dan ubah _zoomView menjadi UIImageView Anda.
Contoh Kode Penggulung Foto Apple
sumber
Untuk membuat animasi mengalir dengan baik, atur
dan gunakan fungsi ini (menemukan pusat menggunakan metode pada jawaban ini )
Ini menciptakan efek memantul tetapi tidak melibatkan gerakan mendadak sebelumnya.
sumber
Hanya jawaban yang disetujui dalam cepat, tetapi tanpa subklas menggunakan delegasi
sumber
Dalam hal imageView batin Anda memiliki lebar spesifik awal (mis. 300) dan Anda hanya ingin memusatkan lebarnya hanya pada zoom yang lebih kecil dari lebar awalnya, ini mungkin membantu Anda juga.
sumber
Inilah cara saya saat ini membuat karya ini. Lebih baik tapi masih belum sempurna. Coba atur:
untuk memperbaiki masalah dengan tampilan yang tidak terpusat saat di
minZoomScale
.Juga, saya melakukan hal berikut untuk mencegah gambar menempel pada sisi setelah memperkecil.
sumber
Oke, saya pikir saya sudah menemukan solusi yang cukup bagus untuk masalah ini. Caranya adalah dengan terus-menerus menyesuaikan
imageView's
frame. Saya menemukan ini bekerja lebih baik daripada terus-menerus menyesuaikancontentInsets
ataucontentOffSets
. Saya harus menambahkan sedikit kode tambahan untuk mengakomodasi gambar potret dan lanskap.Berikut kodenya:
sumber
Cukup nonaktifkan pagination, sehingga berfungsi dengan baik:
sumber
Saya memiliki masalah yang sama persis. Inilah cara saya menyelesaikannya
Kode ini harus dipanggil sebagai hasil dari
scrollView:DidScroll:
sumber
Meskipun pertanyaannya agak lama namun masalahnya masih ada. Saya memecahkannya dalam Xcode 7 dengan membuat batasan ruang vertikal dari item paling atas (dalam hal ini
topLabel
) ke superViews (thescrollView
) atasIBOutlet
dan kemudian menghitung ulang konstanta setiap kali konten berubah tergantung pada ketinggian subview scrollView (topLabel
danbottomLabel
).sumber