UITextView yang diperluas ke teks menggunakan tata letak otomatis


163

Saya memiliki pandangan yang ditata sepenuhnya menggunakan tata letak otomatis secara terprogram. Saya memiliki UITextView di tengah tampilan dengan item di atas dan di bawahnya. Semuanya berfungsi dengan baik, tetapi saya ingin dapat memperluas UITextView saat teks ditambahkan. Ini harus mendorong semua yang ada di bawahnya saat mengembang.

Saya tahu bagaimana melakukan ini dengan cara "pegas dan struts", tetapi apakah ada cara tata letak otomatis untuk melakukan ini? Satu-satunya cara yang dapat saya pikirkan adalah dengan menghapus dan menambahkan kembali kendala setiap kali perlu tumbuh.


5
Anda dapat membuat IBOutlet ke batasan ketinggian untuk tampilan teks, dan hanya memodifikasi konstanta ketika Anda ingin itu tumbuh, tidak perlu menghapus dan menambahkan.
rdelmar

4
2017, tip besar yang sering membuat Anda kesal : HANYA ITU BEKERJA JIKA ANDA SETELAH DILIHAT VIEWDID> MUNCUL < sangat frustasi jika Anda mengatur teks di ViewDidLoad - itu tidak akan berhasil!
Fattie

2
tip No2: jika Anda memanggil [someView.superView layoutIfNeeded] MAKA mungkin bekerja di viewWillAppear ();)
Yaro

Jawaban:


30

Tampilan yang mengandung UITextView akan ditetapkan ukurannya setBoundsoleh AutoLayout. Jadi, inilah yang saya lakukan. Superview pada awalnya mengatur semua kendala lain sebagaimana mestinya, dan pada akhirnya saya menempatkan satu kendala khusus untuk ketinggian UITextView, dan saya menyimpannya dalam variabel instan.

_descriptionHeightConstraint = [NSLayoutConstraint constraintWithItem:_descriptionTextView
                                 attribute:NSLayoutAttributeHeight 
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:nil 
                                 attribute:NSLayoutAttributeNotAnAttribute 
                                multiplier:0.f 
                                 constant:100];

[self addConstraint:_descriptionHeightConstraint];

Dalam setBoundsmetode ini, saya kemudian mengubah nilai konstanta.

-(void) setBounds:(CGRect)bounds
{
    [super setBounds:bounds];

    _descriptionTextView.frame = bounds;
    CGSize descriptionSize = _descriptionTextView.contentSize;

    [_descriptionHeightConstraint setConstant:descriptionSize.height];

    [self layoutIfNeeded];
}

4
Anda juga dapat memperbarui batasan di 'textViewDidChange:' dari UITextViewDelegate
LK__

2
Solusi bagus Perhatikan bahwa Anda juga bisa membuat kendala di Interface Builder, dan sambungkan menggunakan outlet. Dikombinasikan dengan menggunakan textViewDidChangeini akan menghemat kode subclassing dan menulis kerumitan ...
Bob Vork

3
Ingatlah bahwa textViewDidChange:tidak akan dipanggil saat menambahkan teks ke UITextView secara terprogram.
Mengembara

Saran @BobVork bekerja dengan baik XCODE 11 / iOS13, tetapkan batasan konstan ketika nilai tampilan teks diatur dalam viewWillAppear dan perbarui di textViewDidChange.
ptc

549

Ringkasan: Nonaktifkan pengguliran tampilan teks Anda, dan jangan membatasi ketinggiannya.

Untuk melakukan ini secara pemrograman, masukkan kode berikut viewDidLoad:

let textView = UITextView(frame: .zero, textContainer: nil)
textView.backgroundColor = .yellow // visual debugging
textView.isScrollEnabled = false   // causes expanding height
view.addSubview(textView)

// Auto Layout
textView.translatesAutoresizingMaskIntoConstraints = false
let safeArea = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
    textView.topAnchor.constraint(equalTo: safeArea.topAnchor),
    textView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor),
    textView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor)
])

Untuk melakukan ini di Interface Builder, pilih tampilan teks, hapus centang Scrolling Diaktifkan di Attributes Inspector, dan tambahkan kendala secara manual.

Catatan: Jika Anda memiliki tampilan lain di atas / di bawah tampilan teks Anda, pertimbangkan untuk menggunakan a UIStackViewuntuk mengatur semuanya.


12
Bekerja untuk saya (iOS 7 @ xcode 5). Peringatannya adalah bahwa hanya menghapus centang "bergulir diaktifkan" di IB tidak akan membantu. Anda harus secara terprogram melakukannya.
Kenneth Jiang

10
Bagaimana cara menetapkan ketinggian maksimal pada tampilan teks dan kemudian membuat tampilan teks untuk menggulir setelah kontennya telah melampaui ketinggian tampilan teks?
ma11hew28

3
@iOSGeek cukup buat subclass UITextView dan timpa intrinsicContentSizeseperti ini - (CGSize)intrinsicContentSize { CGSize size = [super intrinsicContentSize]; if (self.text.length == 0) { size.height = UIViewNoIntrinsicMetric; } return size; }. Katakan padaku apakah itu berhasil untukmu. Tidak mengujinya sendiri.
manuelwaldner

1
Setel properti ini dan masukkan UITextView di UIStackView. Voilla - self-resize textView!)
Nik Kov

3
Jawaban ini adalah emas. Dengan Xcode 9 juga berfungsi jika Anda menonaktifkan kotak centang di IB.
bio

48

Inilah solusi untuk orang yang lebih suka melakukan semuanya dengan tata letak otomatis:

Inspektur Ukuran:

  1. Atur prioritas ketahanan kompresi konten menjadi 1000.

  2. Turunkan prioritas ketinggian kendala dengan mengklik "Edit" di Kendala. Buat kurang dari 1000.

masukkan deskripsi gambar di sini

Inspektur Atribut:

  1. Hapus centang "Menggulir Diaktifkan"

Ini bekerja dengan sempurna. Saya tidak mengatur ketinggian. Meningkatkan prioritas resistensi kompresi vertikal UItextview ke 1000 hanya diperlukan. UItextView memiliki beberapa inset, itu sebabnya autolayout memberikan kesalahan karena UItextview akan membutuhkan sedikitnya 32 tinggi, bahkan jika tidak ada konten di dalamnya, ketika scrolling dinonaktifkan.
nr5

Pembaruan: Batasan ketinggian diperlukan jika Anda ingin ketinggian minimum 20 atau apa pun. Bijaksana lain 32 akan dianggap sebagai min tinggi.
nr5

@Nil Senang mendengarnya membantu.
Michael Revlis

@MichaelRevlis, Ini sangat bagus. tetapi ketika ada teks besar maka teks tidak ditampilkan. Anda dapat memilih teks melakukan pemrosesan lain tetapi tidak terlihat. bisakah Anda membantu saya dengan itu? ? itu terjadi ketika saya hapus centang opsi yang diaktifkan bergulir. ketika saya mengaktifkan textview scrolling maka itu akan ditampilkan dengan sempurna tetapi saya ingin tampilan teks tidak untuk menggulir.
Bhautik Ziniya

@ BhautikZiniya, sudahkah Anda mencoba membangun aplikasi di perangkat nyata? Saya pikir itu mungkin bug yang menampilkan simulator. Saya memiliki UITextView dengan ukuran font teks 100. Ini ditampilkan dengan baik pada perangkat nyata tetapi teks tidak terlihat pada simulator.
Michael Revlis

38

UITextView tidak menyediakan intrinsicContentSize, jadi Anda perlu mensubklasifikasikan dan menyediakannya. Untuk membuatnya tumbuh secara otomatis, batalkan intrinsicContentSize di layoutSubviews. Jika Anda menggunakan selain dari contentInset default (yang saya tidak rekomendasikan), Anda mungkin perlu menyesuaikan perhitungan intrinsicContentSize.

@interface AutoTextView : UITextView

@end

#import "AutoTextView.h"

@implementation AutoTextView

- (void) layoutSubviews
{
    [super layoutSubviews];

    if (!CGSizeEqualToSize(self.bounds.size, [self intrinsicContentSize])) {
        [self invalidateIntrinsicContentSize];
    }
}

- (CGSize)intrinsicContentSize
{
    CGSize intrinsicContentSize = self.contentSize;

    // iOS 7.0+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) {
        intrinsicContentSize.width += (self.textContainerInset.left + self.textContainerInset.right ) / 2.0f;
        intrinsicContentSize.height += (self.textContainerInset.top + self.textContainerInset.bottom) / 2.0f;
    }

    return intrinsicContentSize;
}

@end

1
Ini bekerja dengan baik untuk saya. Selain itu, saya akan mengatur 'scrollEnabled' menjadi NO di Interface Builder untuk Text View ini, karena sudah menampilkan semua kontennya tanpa perlu menggulir. Lebih penting lagi, jika ia berada di dalam tampilan gulir yang sebenarnya, Anda dapat mengalami lompatan kursor di dekat bagian bawah tampilan teks, jika Anda tidak menonaktifkan pengguliran pada tampilan teks itu sendiri.
idStar

Ini bekerja dengan baik. Menariknya ketika mengganti setScrollEnabled:untuk selalu mengaturnya untuk NOAnda akan mendapatkan loop tak terbatas untuk ukuran konten intrinsik yang terus tumbuh.
Pascal

Pada iOS 7.0, saya juga diperlukan untuk memanggil [textView sizeToFit]di textViewDidChange:callback delegasi untuk Auto Layout untuk tumbuh atau menyusut textview (dan menghitung ulang setiap bergantung kendala) setelah setiap keystroke.
ikuti

6
Tampaknya ini tidak lagi diperlukan di iOS 7.1. Untuk memperbaiki dan memberikan kompatibilitas mundur, bungkus kondisi -(void)layoutSubviewsdan bungkus semua kode -(CGSize)intrinsicContentSizedengan version >= 7.0f && version < 7.1f+else return [super intrinsicContentSize];
David James

1
@ DavidJames ini masih diperlukan di ios 7.1.2, saya tidak tahu di mana Anda menguji.
Softlion

28

Anda dapat melakukannya melalui storyboard, cukup nonaktifkan "Scrolling Enabled" :)

StoryBoard


2
Jawaban terbaik untuk pertanyaan ini
Ivan Byelko

Ini adalah solusi terbaik ketika Anda bekerja dengan Tata Letak Otomatis.
JanApotheker

1
Pengaturan Tata Letak Otomatis (Leading, Trailing, Top, Bottom, NO Height / Width ) + Scrolling dinonaktifkan. dan itu dia. Terima kasih!
Farhan Arshad

15

Saya menemukan itu tidak sepenuhnya tidak umum dalam situasi di mana Anda mungkin masih perlu isScrollEnabled disetel ke true untuk memungkinkan interaksi UI yang masuk akal. Kasus sederhana untuk ini adalah ketika Anda ingin mengizinkan tampilan teks yang diperluas secara otomatis tetapi masih membatasi ketinggian maksimumnya untuk sesuatu yang masuk akal dalam UITableView.

Berikut adalah subkelas dari UITextView yang saya buat yang memungkinkan ekspansi otomatis dengan tata letak otomatis tetapi Anda masih dapat membatasi ketinggian maksimum dan yang akan mengatur apakah tampilan dapat digulir tergantung pada ketinggian. Secara default tampilan akan berkembang tanpa batas jika Anda memiliki pengaturan kendala seperti itu.

import UIKit

class FlexibleTextView: UITextView {
    // limit the height of expansion per intrinsicContentSize
    var maxHeight: CGFloat = 0.0
    private let placeholderTextView: UITextView = {
        let tv = UITextView()

        tv.translatesAutoresizingMaskIntoConstraints = false
        tv.backgroundColor = .clear
        tv.isScrollEnabled = false
        tv.textColor = .disabledTextColor
        tv.isUserInteractionEnabled = false
        return tv
    }()
    var placeholder: String? {
        get {
            return placeholderTextView.text
        }
        set {
            placeholderTextView.text = newValue
        }
    }

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        isScrollEnabled = false
        autoresizingMask = [.flexibleWidth, .flexibleHeight]
        NotificationCenter.default.addObserver(self, selector: #selector(UITextInputDelegate.textDidChange(_:)), name: Notification.Name.UITextViewTextDidChange, object: self)
        placeholderTextView.font = font
        addSubview(placeholderTextView)

        NSLayoutConstraint.activate([
            placeholderTextView.leadingAnchor.constraint(equalTo: leadingAnchor),
            placeholderTextView.trailingAnchor.constraint(equalTo: trailingAnchor),
            placeholderTextView.topAnchor.constraint(equalTo: topAnchor),
            placeholderTextView.bottomAnchor.constraint(equalTo: bottomAnchor),
        ])
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var text: String! {
        didSet {
            invalidateIntrinsicContentSize()
            placeholderTextView.isHidden = !text.isEmpty
        }
    }

    override var font: UIFont? {
        didSet {
            placeholderTextView.font = font
            invalidateIntrinsicContentSize()
        }
    }

    override var contentInset: UIEdgeInsets {
        didSet {
            placeholderTextView.contentInset = contentInset
        }
    }

    override var intrinsicContentSize: CGSize {
        var size = super.intrinsicContentSize

        if size.height == UIViewNoIntrinsicMetric {
            // force layout
            layoutManager.glyphRange(for: textContainer)
            size.height = layoutManager.usedRect(for: textContainer).height + textContainerInset.top + textContainerInset.bottom
        }

        if maxHeight > 0.0 && size.height > maxHeight {
            size.height = maxHeight

            if !isScrollEnabled {
                isScrollEnabled = true
            }
        } else if isScrollEnabled {
            isScrollEnabled = false
        }

        return size
    }

    @objc private func textDidChange(_ note: Notification) {
        // needed incase isScrollEnabled is set to true which stops automatically calling invalidateIntrinsicContentSize()
        invalidateIntrinsicContentSize()
        placeholderTextView.isHidden = !text.isEmpty
    }
}

Sebagai bonus ada dukungan untuk menyertakan teks placeholder mirip dengan UILabel.


7

Anda juga dapat melakukannya tanpa subklas UITextView. Lihat jawaban saya untuk Bagaimana saya mengukur ukuran UITextView untuk kontennya di iOS 7?

Gunakan nilai ekspresi ini:

[textView sizeThatFits:CGSizeMake(textView.frame.size.width, CGFLOAT_MAX)].height

untuk memperbarui constantdari textViewketinggian 's UILayoutConstraint.


3
Di mana Anda melakukan ini dan Anda melakukan hal lain untuk memastikan UITextView sudah diatur? Saya melakukan ini, dan teks melihat ukurannya sendiri, tetapi teks itu sendiri akan terpotong setengah jalan ke bawah ketinggian UITextView. Teks diatur secara terprogram tepat sebelum melakukan hal-hal Anda di atas.
chadbag

Saya menemukan ini umumnya lebih bermanfaat daripada scrollEnabled = TIDAK ada trik, jika Anda ingin mengatur lebar secara manual.
jchnxu

3

Suatu hal penting yang perlu diperhatikan:

Karena UITextView adalah subkelas dari UIScrollView, maka ia tunduk pada properti AdaptsScrollViewInsets dari UIViewController secara otomatis.

Jika Anda mengatur tata letak dan TextView adalah subview pertama dalam hierarki UIViewControllers, itu akan diubah isinyaInsets jika secara otomatisAdjustsScrollViewInsets benar kadang-kadang menyebabkan perilaku tak terduga dalam tata letak otomatis.

Jadi jika Anda mengalami masalah dengan tata letak otomatis dan tampilan teks, coba atur automaticallyAdjustsScrollViewInsets = falsepada view controller atau pindahkan textView ke depan dalam hierarki.


2

Ini komentar yang lebih penting

Kunci untuk memahami mengapa jawaban vitaminwater bekerja adalah tiga hal:

  1. Ketahuilah bahwa UITextView adalah subkelas dari kelas UIScrollView
  2. Memahami cara kerja ScrollView dan bagaimana contentSize-nya dihitung. Untuk lebih lanjut lihat ini di sini jawaban dan berbagai solusi dan komentarnya.
  3. Memahami apa itu contentSize dan bagaimana menghitungnya. Lihat di sini dan di sini . Mungkin juga membantu bahwa pengaturan kemungkinan tidak lain contentOffsetadalah :

func setContentOffset(offset: CGPoint)
{
    CGRect bounds = self.bounds
    bounds.origin = offset
    self.bounds = bounds
}

Untuk lebih lanjut lihat objc scrollview dan memahami scrollview


Menggabungkan ketiga bersama-sama Anda akan dengan mudah memahami bahwa Anda perlu mengizinkan contentSize intrinsik textView untuk bekerja bersama kendala AutoLayout dari textView untuk mendorong logika. Ini hampir seolah-olah Anda textView berfungsi seperti UILabel

Untuk mewujudkannya, Anda perlu menonaktifkan pengguliran yang pada dasarnya berarti ukuran scrollView, ukuran contentSize dan dalam hal menambahkan containerView, maka ukuran containerView akan sama. Ketika semuanya sama, Anda TIDAK perlu menggulir. Dan Anda akan melakukannya . Memiliki berarti Anda belum menggulir ke bawah. Bahkan 1 poin pun turun! Hasilnya, textView akan terbentang semua.0 contentOffset0 contentOffSet

Ini juga tidak bernilai apa pun yang berarti bahwa batas dan bingkai scrollView adalah sama. Jika Anda gulir ke bawah 5 poin maka contentOffset Anda akan menjadi , sedangkan Anda akan sama dengan0 contentOffset5scrollView.bounds.origin.y - scrollView.frame.origin.y5


1

Solusi Plug and Play - Xcode 9

AutoLayout seperti UILabel, dengan deteksi link yang , pemilihan teks , mengedit dan bergulir dariUITextView .

Secara otomatis menangani

  • Area aman
  • Insets konten
  • Padding baris fragmen
  • Insets wadah teks
  • Kendala
  • Tampilan tumpukan
  • String yang dikaitkan
  • Masa bodo.

Banyak jawaban ini yang membuat saya 90% di sana, tetapi tidak ada yang terbukti bodoh.

Masukkan UITextViewsubclass ini dan Anda baik-baik saja.


#pragma mark - Init

- (instancetype)initWithFrame:(CGRect)frame textContainer:(nullable NSTextContainer *)textContainer
{
    self = [super initWithFrame:frame textContainer:textContainer];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (void)commonInit
{
    // Try to use max width, like UILabel
    [self setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    
    // Optional -- Enable / disable scroll & edit ability
    self.editable = YES;
    self.scrollEnabled = YES;
    
    // Optional -- match padding of UILabel
    self.textContainer.lineFragmentPadding = 0.0;
    self.textContainerInset = UIEdgeInsetsZero;
    
    // Optional -- for selecting text and links
    self.selectable = YES;
    self.dataDetectorTypes = UIDataDetectorTypeLink | UIDataDetectorTypePhoneNumber | UIDataDetectorTypeAddress;
}

#pragma mark - Layout

- (CGFloat)widthPadding
{
    CGFloat extraWidth = self.textContainer.lineFragmentPadding * 2.0;
    extraWidth +=  self.textContainerInset.left + self.textContainerInset.right;
    if (@available(iOS 11.0, *)) {
        extraWidth += self.adjustedContentInset.left + self.adjustedContentInset.right;
    } else {
        extraWidth += self.contentInset.left + self.contentInset.right;
    }
    return extraWidth;
}

- (CGFloat)heightPadding
{
    CGFloat extraHeight = self.textContainerInset.top + self.textContainerInset.bottom;
    if (@available(iOS 11.0, *)) {
        extraHeight += self.adjustedContentInset.top + self.adjustedContentInset.bottom;
    } else {
        extraHeight += self.contentInset.top + self.contentInset.bottom;
    }
    return extraHeight;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    // Prevents flashing of frame change
    if (CGSizeEqualToSize(self.bounds.size, self.intrinsicContentSize) == NO) {
        [self invalidateIntrinsicContentSize];
    }
    
    // Fix offset error from insets & safe area
    
    CGFloat textWidth = self.bounds.size.width - [self widthPadding];
    CGFloat textHeight = self.bounds.size.height - [self heightPadding];
    if (self.contentSize.width <= textWidth && self.contentSize.height <= textHeight) {
        
        CGPoint offset = CGPointMake(-self.contentInset.left, -self.contentInset.top);
        if (@available(iOS 11.0, *)) {
            offset = CGPointMake(-self.adjustedContentInset.left, -self.adjustedContentInset.top);
        }
        if (CGPointEqualToPoint(self.contentOffset, offset) == NO) {
            self.contentOffset = offset;
        }
    }
}

- (CGSize)intrinsicContentSize
{
    if (self.attributedText.length == 0) {
        return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
    }
    
    CGRect rect = [self.attributedText boundingRectWithSize:CGSizeMake(self.bounds.size.width - [self widthPadding], CGFLOAT_MAX)
                                                    options:NSStringDrawingUsesLineFragmentOrigin
                                                    context:nil];
    
    return CGSizeMake(ceil(rect.size.width + [self widthPadding]),
                      ceil(rect.size.height + [self heightPadding]));
}

0

jawaban vitaminwater bekerja untuk saya.

Jika teks tampilan teks Anda memantul ke atas dan ke bawah selama pengeditan, setelah pengaturan [textView setScrollEnabled:NO];, atur Size Inspector > Scroll View > Content Insets > Never.

Semoga ini bisa membantu.


0

Tempatkan UILabel tersembunyi di bawah tampilan teks Anda. Label baris = 0. Atur batasan UITextView menjadi sama dengan label UIL (centerX, centerY, lebar, tinggi). Bekerja bahkan jika Anda meninggalkan perilaku gulir dari textView.


-1

BTW, saya membangun UITextView yang diperluas menggunakan subkelas dan mengesampingkan ukuran konten intrinsik. Saya menemukan bug di UITextView yang mungkin ingin Anda selidiki dalam implementasi Anda sendiri. Inilah masalahnya:

Tampilan teks yang meluas akan tumbuh turun untuk mengakomodasi teks yang tumbuh jika Anda mengetikkan satu huruf sekaligus. Tetapi jika Anda menempelkan banyak teks ke dalamnya, itu tidak akan tumbuh turun tetapi teks akan menggulir ke atas dan teks di atas tidak terlihat.

Solusinya: Override setBounds: di subclass Anda. Untuk beberapa alasan yang tidak diketahui, pasting menyebabkan nilai bounds.origin.y menjadi non-zee (33 dalam setiap kasus yang saya lihat). Jadi saya mengesampingkan setBounds: untuk selalu mengatur bounds.origin.y ke nol. Memperbaiki masalah.


-1

Inilah solusi cepat:

Masalah ini dapat terjadi jika Anda menyetel properti clipsToBounds menjadi false dari tampilan teks Anda. Jika Anda hanya menghapusnya, masalahnya hilang.

myTextView.clipsToBounds = false //delete this line

-3
Obj C:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic) UITextView *textView;
@end



#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize textView;

- (void)viewDidLoad{
    [super viewDidLoad];
    [self.view setBackgroundColor:[UIColor grayColor]];
    self.textView = [[UITextView alloc] initWithFrame:CGRectMake(30,10,250,20)];
    self.textView.delegate = self;
    [self.view addSubview:self.textView];
}

- (void)didReceiveMemoryWarning{
    [super didReceiveMemoryWarning];
}

- (void)textViewDidChange:(UITextView *)txtView{
    float height = txtView.contentSize.height;
    [UITextView beginAnimations:nil context:nil];
    [UITextView setAnimationDuration:0.5];

    CGRect frame = txtView.frame;
    frame.size.height = height + 10.0; //Give it some padding
    txtView.frame = frame;
    [UITextView commitAnimations];
}

@end
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.