Bagaimana cara menggunakan tata-letak otomatis untuk memindahkan tampilan lain saat suatu tampilan disembunyikan?

334

Saya telah mendesain Sel khusus saya di IB, mensubklasifikasikan dan menghubungkan outlet saya ke kelas khusus saya. Saya memiliki tiga subview dalam konten sel yaitu: UIView (cdView) dan dua label (titleLabel dan emailLabel). Bergantung pada data yang tersedia untuk setiap baris, kadang-kadang saya ingin UIView dan dua label ditampilkan di sel saya dan kadang-kadang hanya dua label. Apa yang saya coba lakukan adalah menetapkan batasan seperti itu jika saya mengatur properti UIView menjadi tersembunyi atau saya akan menghapusnya dari superview dua label akan pindah ke kiri. Saya mencoba mengatur batasan utama UIView menjadi Superview (konten sel) untuk 10px dan batasan utama UILabel untuk 10 px ke tampilan berikutnya (UIView). Kemudian dalam kode saya

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];

if ([record.imageURL is equalToString:@""]) {
     cell.cdView.hidden = YES;
}

Saya menyembunyikan cell.cdView saya dan saya ingin label untuk pindah ke kiri namun mereka tetap berada di posisi yang sama di Cell. Saya mencoba menghapus cell.cdView dari superview tetapi tidak berhasil juga. Saya telah melampirkan gambar untuk menjelaskan tentang saya.

sel

Saya tahu bagaimana melakukan ini secara terprogram dan saya tidak mencari solusi itu. Yang saya inginkan adalah menetapkan batasan dalam IB dan saya berharap bahwa subview saya akan bergerak secara dinamis jika tampilan lain dihapus atau disembunyikan. Apakah mungkin untuk melakukan ini di IB dengan tata letak otomatis?

.....
Guferos
sumber
Ubah runtime nilai kendala - periksa jawaban
Kampai
Untuk kasus khusus ini, Anda juga dapat menggunakan UIStackView. ketika Anda menyembunyikan cd, label akan menempati ruang mereka
Marco Pappalardo

Jawaban:

373

Itu mungkin, tetapi Anda harus melakukan sedikit pekerjaan ekstra. Ada beberapa hal konseptual untuk keluar dari jalan pertama:

  • Tampilan tersembunyi, meskipun tidak menggambar, tetap berpartisipasi dalam Tata Letak Otomatis dan biasanya mempertahankan bingkai mereka , meninggalkan tampilan terkait lainnya di tempat mereka.
  • Saat menghapus tampilan dari superview-nya, semua kendala terkait juga dihapus dari hierarki tampilan itu.

Dalam kasus Anda, ini kemungkinan berarti:

  • Jika Anda mengatur tampilan kiri Anda untuk disembunyikan, label tetap di tempatnya, karena tampilan kiri itu masih memakan tempat (meskipun itu tidak terlihat).
  • Jika Anda menghapus tampilan kiri Anda, label Anda mungkin akan dibiarkan ambigu terbatas, karena Anda tidak lagi memiliki batasan untuk tepi kiri label Anda.

Yang perlu Anda lakukan adalah membatasi label Anda dengan bijaksana . Biarkan kendala Anda saat ini (ruang 10pts ke tampilan lain), tetapi tambahkan kendala lain: jadikan tepi kiri label Anda 10pts dari tepi kiri superview mereka dengan prioritas yang tidak diperlukan (prioritas tinggi default mungkin akan bekerja dengan baik).

Kemudian, ketika Anda ingin mereka bergerak ke kiri, hapus tampilan kiri sama sekali. Batasan 10pt wajib untuk tampilan kiri akan menghilang bersama dengan tampilan yang terkait dengannya, dan Anda akan dibiarkan hanya dengan kendala prioritas tinggi yang labelnya berjarak 10 poin dari superview mereka. Pada pass tata letak berikutnya, ini akan menyebabkan mereka melebar ke kiri sampai mereka memenuhi lebar superview tetapi untuk jarak Anda di sekitar tepi.

Satu peringatan penting: jika Anda ingin tampilan kiri Anda kembali dalam gambar, Anda tidak hanya harus menambahkannya kembali ke hierarki tampilan, tetapi Anda juga harus membangun kembali semua kendala pada saat yang sama. Ini berarti Anda memerlukan cara untuk mengembalikan batasan spasi 10pt antara tampilan dan labelnya setiap kali tampilan itu ditampilkan lagi.

Tim
sumber
8
Meskipun jawaban ini pasti akan berfungsi, IMO, terlalu membatasi untuk menangani berbagai kasus penggunaan tampaknya menjadi bau kode - terutama karena Anda harus membangun kembali semua kendala untuk setiap tampilan yang dihapus yang ingin Anda tampilkan lagi.
memmons
Menurut saya, ini bukan jalan yang harus ditempuh. Anda sebaiknya menggunakan batasan lebar / tinggi untuk tampilan yang ingin Anda sembunyikan.
ullstrm
26
Dengan hormat saya tidak setuju. Jika Anda (misalnya) mengatur lebar tampilan menjadi 0, Anda akan mengalami dua masalah. Pertama, Anda sekarang memiliki spasi ganda antara superview dan tampilan yang terlihat: |-(space)-[hidden(0)]-(space)-[visible]efektif |-(2*space)-[visible]. Kedua, tampilan itu mungkin mulai melempar pelanggaran batasan tergantung pada subtree dan kendala tampilan sendiri - Anda tidak dapat menjamin bahwa Anda dapat secara sewenang-wenang membatasi tampilan pada lebar 0 dan membuatnya tetap berfungsi.
Tim
1
Jika Anda menggunakan tampilan dengan ukuran konten intrinsik, jawaban Tim sepertinya adalah cara unik untuk melakukannya.
balkoth
Terima kasih, Tim. Saya menetapkan batasan 0 dengan prioritas lebih tinggi untuk menghindari ketidakcocokan kendala, tetapi sekarang saya menyadari ada masalah dengan spasi ganda. Saya tidak memiliki masalah itu karena saya tidak pernah menunjukkan dua pandangan bersama (kasus saya :) |-[otherViews]-[eitherThis][orThis]-|, tetapi saya akhirnya akan mengalami masalah itu.
Ferran Maylinch
207

Menambah atau menghapus kendala selama runtime adalah operasi kelas berat yang dapat memengaruhi kinerja. Namun, ada alternatif yang lebih sederhana.

Untuk tampilan yang ingin Anda sembunyikan, atur batasan lebar. Batasi tampilan lain dengan celah horizontal mengarah ke tampilan itu.

Untuk menyembunyikan, perbarui .constantbatasan lebar ke 0.f. Tampilan lain akan secara otomatis bergerak ke kiri untuk mengambil posisi.

Lihat jawaban saya yang lain di sini untuk perincian lebih lanjut:

Bagaimana cara mengubah batasan label selama runtime?

Max MacLeod
sumber
29
Satu-satunya masalah dengan solusi ini adalah bahwa margin ke kiri akan menjadi dua kali lipat dari apa yang Anda inginkan, jadi saya akan memperbarui salah satu kendala itu juga, tetapi bahkan kemudian saya pikir ini kurang bekerja daripada menghapus subview.
José Manuel Sánchez
2
@ skinsfan00atg Jika Anda menggunakan tampilan dengan ukuran konten intrinsik, Anda tidak dapat menggunakan solusi ini.
balkoth
@ Balkoth kenapa tidak? Anda bisa mengurangi prioritas pelukan konten
Max MacLeod
2
@MaxMacLeod Jika Anda mengurangi prioritas memeluk konten maka Anda tidak menggunakan ukuran konten intrinsik, Anda menggunakan ukuran yang ditunjukkan oleh kendala.
balkoth
2
@ MaxmacLeod Ok, saya mengerti maksud Anda. Anda perlu mengatur prioritas ketahanan kompresi ke 0 (bukan konten yang dipeluk) dalam kode ketika Anda ingin menyembunyikan tampilan, dan ketika Anda ingin menampilkan kembali mengembalikan nilai itu. Selain itu, Anda perlu menambahkan kendala dalam pembuat antarmuka untuk mengatur ukuran tampilan menjadi 0. Tidak perlu menyentuh kendala ini dalam kode.
balkoth
87

Bagi mereka yang hanya mendukung iOS 8+ , ada properti boolean baru yang aktif . Ini akan membantu untuk mengaktifkan hanya kendala yang diperlukan secara dinamis

Stopkontak PS Constraint harus kuat , tidak lemah.

Contoh:

@IBOutlet weak var optionalView: UIView!
@IBOutlet var viewIsVisibleConstraint: NSLayoutConstraint!
@IBOutlet var viewIsHiddenConstraint: NSLayoutConstraint!

func showView() {
    optionalView.isHidden = false
    viewIsVisibleConstraint.isActive = true
    viewIsHiddenConstraint.isActive = false
}

func hideView() {
    optionalView.isHidden = true
    viewIsVisibleConstraint.isActive = false
    viewIsHiddenConstraint.isActive = true
}

Juga untuk memperbaiki kesalahan di storyboard Anda harus menghapus Installedcentang pada kotak centang untuk salah satu kendala ini.

UIStackView (iOS 9+)
Satu opsi lagi adalah membungkus pandangan AndaUIStackView. Setelah tampilan disembunyikanUIStackViewakan memperbarui tata letak secara otomatis

Silmaril
sumber
sebagian aktif bekerja. Tetapi jika saya menggunakannya di dalam sel yang dapat digunakan kembali, dari aktif ke nonaktif, berfungsi, tetapi tidak untuk nonaktif aktif. Ada ide? Atau bisakah Anda memberikan contoh mungkin?
Aoke Li
10
Ini terjadi karena kendala yang dinonaktifkan tidak dimuat atau tidak dialokasikan. Outlet kendala Anda harus kuat, bukan lemah
Silmaril
Di mana kita dapat menemukan properti "aktif" itu?
Lakshmi Reddy
Tampaknya over-constrain + set constraint activity dapat menjadi jawaban yang paling masuk akal.
Ting Yi Shih
68

UIStackViewreposisi pandangannya secara otomatis ketika hiddenproperti diubah pada salah satu dari subview-nya (iOS 9+)

UIView.animateWithDuration(1.0) { () -> Void in
   self.mySubview.hidden = !self.mySubview.hidden
}

Lompat ke 11:48 dalam video WWDC ini untuk demo:

Misteri Tata Letak Otomatis, Bagian 1

5 bar
sumber
Saya menyembunyikan tampilan tumpukan bersarang dan seluruh tampilan tumpukan yang berisi menghilang.
Ian Warburton
5
Ini harus menjadi jawaban yang diterima. Mengikuti rekomendasi apel dari wwdc 2015 tentang desain pembangun antarmuka.
thibaut noah
@ thibautnoah Lalu bagaimana dengan dukungan iOS 8-?
bagage
5
@bagage Kecuali Anda Facebook atau Google, Anda bisa menjatuhkannya. Dengan cakupan di antara iOS 9 Anda akan mendukung lebih dari 90% perangkat, lebih dari cukup. Dukungan di bawah ini akan melumpuhkan proses pengembangan Anda dan mencegah Anda menggunakan fitur terbaru imo
thibaut noah
16

Proyek saya menggunakan @IBDesignablesubkelas khusus UILabel(untuk memastikan konsistensi dalam warna, font, inset, dll.) Dan saya telah menerapkan sesuatu seperti berikut:

override func intrinsicContentSize() -> CGSize {
    if hidden {
        return CGSizeZero
    } else {
        return super.intrinsicContentSize()
    }
}

Ini memungkinkan subclass label untuk mengambil bagian dalam Tata Letak Otomatis, tetapi tidak mengambil ruang ketika disembunyikan.

Robert Atkins
sumber
13

Untuk Googler: membangun jawaban Max, untuk menyelesaikan masalah padding yang banyak orang perhatikan, saya hanya menambah tinggi label dan menggunakan tinggi itu sebagai pemisah alih-alih padding aktual. Gagasan ini dapat diperluas untuk skenario apa pun yang berisi tampilan.

Berikut ini contoh sederhana:

Tangkapan Layar IB

Dalam hal ini, saya memetakan ketinggian label Penulis ke yang sesuai IBOutlet:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

dan ketika saya mengatur ketinggian batasan untuk 0.0f, kami mempertahankan "padding", karena ketinggian tombol Play memungkinkan untuk itu.

jterry
sumber
Bagi mereka yang baru NSLayoutConstraintmengenal saya percaya bahwa Anda ingin memperbarui constantproperti Anda authorLabelHeight.
Kyle
8

hubungkan batasan antara uiview dan label sebagai IBOutlet dan atur anggota prioritas ke nilai yang lebih rendah saat disembunyikan = YES

n0c
sumber
3
Anda tidak dapat menyesuaikan prioritas NSLayoutConstraint setelah itu ditetapkan; Anda harus menghapus dan membaca batasan baru dengan prioritas berbeda.
Tim
7
Saya menggunakan metode ini. Saya memiliki kasing yang menggunakan label dan tombol, di mana saya perlu menyembunyikan tombol dan memperluas label. Saya memiliki dua kendala, satu awalnya dengan prioritas 751 dan yang lainnya dengan 750. Kemudian ketika saya menyembunyikan tombol, saya membalik prioritas, dan panjang label bertambah. Perlu dicatat bahwa jika Anda mencoba untuk membuat prioritas yang lebih tinggi 1000 Anda mendapatkan kesalahan "Mutasi prioritas dari yang diperlukan untuk tidak pada kendala yang diinstal (atau sebaliknya) tidak didukung.". Jadi jangan dan Anda tampaknya baik-baik saja. Xcode 5.1 / viewDidLoad.
John Bushnell
8

Apa yang akhirnya saya lakukan adalah membuat 2 xibs. Satu dengan tampilan kiri dan satu tanpa itu. Saya mendaftarkan keduanya di controller dan kemudian memutuskan mana yang akan digunakan selama cellForRowAtIndexPath.

Mereka menggunakan kelas UITableViewCell yang sama. Kelemahannya adalah bahwa ada beberapa duplikasi konten antara xibs, tetapi sel-sel ini cukup mendasar. Sisi baiknya adalah saya tidak memiliki banyak kode untuk mengelola penghapusan tampilan secara manual, memperbarui kendala, dll.

Secara umum, ini mungkin solusi yang lebih baik karena tata letak mereka berbeda secara teknis dan karenanya harus memiliki xib yang berbeda.

[self.table registerNib:[UINib nibWithNibName:@"TrackCell" bundle:nil] forCellReuseIdentifier:@"TrackCell"];
[self.table registerNib:[UINib nibWithNibName:@"TrackCellNoImage" bundle:nil] forCellReuseIdentifier:@"TrackCellNoImage"];

TrackCell *cell = [tableView dequeueReusableCellWithIdentifier:(appDelegate.showImages ? @"TrackCell" : @"TrackCellNoImage") forIndexPath:indexPath];
Michael Peterson
sumber
7

Dalam hal ini, saya memetakan ketinggian label Penulis ke IBOutlet yang sesuai:

@property (retain, nonatomic) IBOutlet NSLayoutConstraint* authorLabelHeight;

dan ketika saya mengatur ketinggian batasan menjadi 0,0f, kami mempertahankan "padding", karena ketinggian tombol Play memungkinkan untuk itu.

cell.authorLabelHeight.constant = 0;

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Mitul Marsoniya
sumber
6

Gunakan dua UIStackView Horizontal dan Vertical, ketika beberapa tampilan subview dalam stack disembunyikan, subview stack lainnya akan dipindahkan, gunakan Distribution -> Fill Proportionally for Vertical stack dengan dua UILabels dan perlu tetapkan lebar dan tinggi konstan untuk UIView pertamamasukkan deskripsi gambar di sini

Roman Solodyashkin
sumber
2

Coba ini, saya telah menerapkan kode di bawah ini,

Saya punya satu View di ViewController yang menambahkan tiga tampilan lainnya, Ketika ada tampilan yang disembunyikan dua tampilan lainnya akan bergerak, Ikuti langkah-langkah di bawah ini. ,

File 1.ViewController.h

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIView *viewOne;
@property (strong, nonatomic) IBOutlet UIView *viewTwo;
@property (strong, nonatomic) IBOutlet UIView *viewThree;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewOneWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewTwoWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewThreeWidth;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *viewBottomWidth;
@end

2.ViewController.m

 #import "ViewController.h"
 @interface ViewController ()
{
  CGFloat viewOneWidthConstant;
  CGFloat viewTwoWidthConstant;
  CGFloat viewThreeWidthConstant;
  CGFloat viewBottomWidthConstant;
}
@end

@implementation ViewController
@synthesize viewOne, viewTwo, viewThree;

- (void)viewDidLoad {
  [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a 
  nib.

  /*
   0  0   0
   0  0   1
   0  1   0
   0  1   1
   1  0   0
   1  0   1
   1  1   0
   1  1   1
   */

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:NO];
  //    [viewTwo setHidden:YES];
  //    [viewThree setHidden:YES];


  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:NO];

  //    [viewOne setHidden:YES];
  //    [viewTwo setHidden:NO];
  //    [viewThree setHidden:YES];

 //    [viewOne setHidden:YES];
 //    [viewTwo setHidden:YES];
 //    [viewThree setHidden:NO];

//    [viewOne setHidden:YES];
//    [viewTwo setHidden:YES];
//    [viewThree setHidden:YES];

 [self hideShowBottomBar];
  }

- (void)hideShowBottomBar
{
  BOOL isOne = !viewOne.isHidden;
  BOOL isTwo = !viewTwo.isHidden;
  BOOL isThree = !viewThree.isHidden;

  viewOneWidthConstant = _viewOneWidth.constant;
  viewTwoWidthConstant = _viewTwoWidth.constant;
  viewThreeWidthConstant = _viewThreeWidth.constant;
  viewBottomWidthConstant = _viewBottomWidth.constant;

   if (isOne && isTwo && isThree) {
    // 0    0   0
    _viewOneWidth.constant = viewBottomWidthConstant / 3;
    _viewTwoWidth.constant = viewBottomWidthConstant / 3;
    _viewThreeWidth.constant = viewBottomWidthConstant / 3;
    }
    else if (isOne && isTwo && !isThree) {
     // 0    0   1
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = 0;
    }
   else if (isOne && !isTwo && isThree) {
    // 0    1   0
    _viewOneWidth.constant = viewBottomWidthConstant / 2;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
    }
    else if (isOne && !isTwo && !isThree) {
    // 0    1   1
    _viewOneWidth.constant = viewBottomWidthConstant;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && isTwo && isThree) {
    // 1    0   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant / 2;
    _viewThreeWidth.constant = viewBottomWidthConstant / 2;
   }
   else if (!isOne && isTwo && !isThree) {
    // 1    0   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = viewBottomWidthConstant;
    _viewThreeWidth.constant = 0;
   }
   else if (!isOne && !isTwo && isThree) {
    // 1    1   0
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = viewBottomWidthConstant;
   }
   else if (isOne && isTwo && isThree) {
    // 1    1   1
    _viewOneWidth.constant = 0;
    _viewTwoWidth.constant = 0;
    _viewThreeWidth.constant = 0;
   }
  }

 - (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
 }
 @end

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Semoga Jadi logika ini akan membantu seseorang.

Jaywant Khedkar
sumber
1

Dalam kasus saya saya mengatur konstan dari ketinggian kendala untuk 0.0fdan juga mengatur hiddenproperti untuk YES.

Untuk menunjukkan tampilan (dengan subview) lagi saya melakukan yang sebaliknya: Saya mengatur tinggi konstan ke nilai non-nol dan mengatur hiddenproperti NO.

pengujian
sumber
1

Saya akan menggunakan stackview horizontal. Itu dapat menghapus bingkai ketika subview disembunyikan.

Pada gambar di bawah, tampilan merah adalah wadah aktual untuk konten Anda dan memiliki ruang trailing 10pt ke superview oranye (ShowHideView), lalu sambungkan ShowHideView ke IBOutlet dan tampilkan / sembunyikan / hapus secara programatik.

  1. Ini adalah ketika tampilan terlihat / diinstal.

tampilan terlihat

  1. Ini adalah saat tampilan disembunyikan / tidak diinstal.

tampilan disembunyikan / dihapus

mnemonic23
sumber
1

Ini solusi saya yang lain menggunakan kendala prioritas. Idenya adalah mengatur lebar ke 0.

  1. buat tampilan kontainer (oranye) dan atur lebar. masukkan deskripsi gambar di sini

  2. buat tampilan konten (merah) dan atur spasi 10pt ke superview (oranye). Perhatikan trailing space constraint, ada 2 trailing constraint dengan prioritas berbeda. Rendah (= 10) dan Tinggi (<= 10). Ini penting untuk menghindari ambiguitas. masukkan deskripsi gambar di sini

  3. Atur lebar tampilan oranye ke 0 untuk menyembunyikan tampilan. masukkan deskripsi gambar di sini

mnemonic23
sumber
0

Seperti yang disarankan no_scene, Anda pasti dapat melakukan ini dengan mengubah prioritas kendala saat runtime. Ini jauh lebih mudah bagi saya karena saya memiliki lebih dari satu pandangan yang menghalangi yang harus dihapus.

Berikut cuplikan menggunakan ReactiveCocoa:

RACSignal* isViewOneHiddenSignal = RACObserve(self.viewModel, isViewOneHidden);
RACSignal* isViewTwoHiddenSignal = RACObserve(self.viewModel, isViewTwoHidden);
RACSignal* isViewThreeHiddenSignal = RACObserve(self.viewModel, isViewThreeHidden);
RAC(self.viewOne, hidden) = isViewOneHiddenSignal;
RAC(self.viewTwo, hidden) = isViewTwoHiddenSignal;
RAC(self.viewThree, hidden) = isViewThreeHiddenSignal;

RAC(self.viewFourBottomConstraint, priority) = [[[[RACSignal
    combineLatest:@[isViewOneHiddenSignal,
                    isViewTwoHiddenSignal,
                    isViewThreeHiddenSignal]]
    and]
    distinctUntilChanged]
    map:^id(NSNumber* allAreHidden) {
        return [allAreHidden boolValue] ? @(780) : @(UILayoutPriorityDefaultHigh);
    }];

RACSignal* updateFramesSignal = [RACObserve(self.viewFourBottomConstraint, priority) distinctUntilChanged];
[updateFramesSignal
    subscribeNext:^(id x) {
        @strongify(self);
        [self.view setNeedsUpdateConstraints];
        [UIView animateWithDuration:0.3 animations:^{
            [self.view layoutIfNeeded];
        }];
    }];
Skensell
sumber
0

Dalam hal ini membantu seseorang, saya membangun kelas pembantu untuk menggunakan format visual batasan . Saya menggunakannya di aplikasi saya saat ini.

AutolayoutHelper

Mungkin sedikit disesuaikan dengan kebutuhan saya, tetapi Anda mungkin menemukan itu berguna atau Anda mungkin ingin mengubahnya dan membuat pembantu Anda sendiri.

Saya harus berterima kasih kepada Tim atas jawabannya di atas , jawaban ini tentang UIScrollView dan juga tutorial ini .

Ferran Maylinch
sumber
0

Inilah cara saya akan menyelaraskan uiviews saya untuk mendapatkan solusi Anda:

  1. Seret jatuhkan satu UIImageView dan letakkan di sebelah kiri.
  2. Seret jatuhkan satu UIView dan letakkan di sebelah kanan UIImageView.
  3. Seret drop dua UILabel di dalam UIView yang kendala memimpin dan trailingnya nol.
  4. Setel batasan utama UIView yang berisi 2 label ke superview, bukan UIImagView.
  5. JIKA UIImageView disembunyikan, tetapkan konstan kendala utama ke 10 px ke superview. ELSE, tetapkan konstan kendala utama ke 10 px + UIImageView.width + 10 px.

Saya membuat aturan praktis saya sendiri. Setiap kali Anda harus menyembunyikan / menampilkan uiview apa pun yang batasannya mungkin terpengaruh, tambahkan semua subview yang terpengaruh / tergantung di dalam uiview dan perbarui konstanta kendala terkemuka / trailing / atas / bawah secara terprogram.

Deepak Thakur
sumber
0

Ini adalah pertanyaan lama tapi tetap saya harap ini akan membantu. Datang dari Android, di platform ini Anda memiliki metode praktisisVisible untuk menyembunyikannya dari tampilan tetapi juga tidak memiliki bingkai yang dipertimbangkan saat autolayout menggambar tampilan.

menggunakan ekstensi dan "extended" uiview Anda bisa melakukan fungsi serupa di ios (tidak yakin mengapa itu tidak ada di UIKit) di sini implementasi di swift 3:

    func isVisible(_ isVisible: Bool) {
        self.isHidden = !isVisible
        self.translatesAutoresizingMaskIntoConstraints = isVisible
        if isVisible { //if visible we remove the hight constraint 
            if let constraint = (self.constraints.filter{$0.firstAttribute == .height}.first){
                self.removeConstraint(constraint)
            }
        } else { //if not visible we add a constraint to force the view to have a hight set to 0
            let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal , toItem: nil, attribute: .notAnAttribute, multiplier: 0, constant: 0)
            self.addConstraint(height)
        }
        self.layoutIfNeeded()
    }
Vincent Choubard
sumber
0

cara yang tepat untuk melakukannya adalah menonaktifkan batasan dengan isActive = false. namun perhatikan bahwa menonaktifkan batasan menghilangkan dan melepaskannya, jadi Anda harus memiliki outlet yang kuat untuk itu.

Hogdotmac
sumber
0

Solusi termudah adalah dengan menggunakan UIStackView (horizontal). Tambahkan ke tumpukan tampilan: tampilan pertama dan tampilan kedua dengan label. Kemudian atur properti isHidden dari tampilan pertama ke false. Semua kendala akan dihitung dan diperbarui secara otomatis.

Oleh Kudinov
sumber
0

Saya pikir ini adalah jawaban yang paling sederhana. Harap verifikasi bahwa itu berfungsi:

        StackFullView.layer.isHidden = true
        Task_TopSpaceSections.constant = 0.   //your constraint of top view

periksa di sini https://www.youtube.com/watch?v=EBulMWMoFuw

Gowthaman M
sumber