내용에 맞게 UITableView 크기 조정
에 질문이 UILabel
있고에 객관식 답변이 표시 되는 앱을 만들고 있는데 UITableView
각 행 에는 객관식 선택이 표시됩니다 . 질문과 답변은 다양하므로 UITableView
동적으로 높이 가 필요합니다 .
sizeToFit
테이블에 대한 해결 방법 을 찾고 싶습니다 . 표의 프레임이 모든 내용의 높이로 설정되는 경우.
아무도 내가 이것을 달성 할 수있는 방법에 대해 조언 할 수 있습니까?
실제로 나는 스스로 답을 찾았습니다.
난 그냥 새를 만들 CGRect
에 대한 tableView.frame
와 height
의table.contentSize.height
즉,의 높이를 설정 UITableView
받는 height
내용의. 코드가 UI를 수정하므로 기본 스레드에서 UI를 실행하는 것을 잊지 마십시오.
dispatch_async(dispatch_get_main_queue(), ^{
//This code will run in the main thread:
CGRect frame = self.tableView.frame;
frame.size.height = self.tableView.contentSize.height;
self.tableView.frame = frame;
});
KVO, DispatchQueue 또는 제약 조건 설정이없는 Swift 5 및 4.2 솔루션.
이 솔루션은 Gulz의 답변을 기반으로 합니다.
1)의 서브 클래스를 생성합니다 UITableView
:
import UIKit
final class ContentSizedTableView: UITableView {
override var contentSize:CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
2) UITableView
레이아웃에 a 를 추가하고 모든면에 제약 조건을 설정하십시오. 클래스를로 설정하십시오 ContentSizedTableView
.
3) 스토리 보드는 하위 클래스 intrinsicContentSize
를 고려 하지 않기 때문에 약간의 오류가 표시 됩니다. 크기 관리자를 열고 intrinsicContentSize를 자리 표시 자 값으로 재정 의하여이 문제를 해결하십시오. 이것은 디자인 타임에 대한 재정의입니다. 런타임에 ContentSizedTableView
클래스 에서 재정의를 사용합니다.
업데이트 : Swift 4.2 코드가 변경되었습니다. 이전 버전을 사용 UIViewNoIntrinsicMetric
하는 경우 대신UIView.noIntrinsicMetric
스위프트 솔루션
이 단계를 따르세요:
1- 스토리 보드에서 테이블의 높이 제한을 설정하십시오.
2- 스토리 보드에서 높이 구속 조건을 끌어 뷰 컨트롤러 파일에서 @IBOutlet을 만듭니다.
@IBOutlet weak var tableHeight: NSLayoutConstraint!
3- 그런 다음이 코드를 사용하여 테이블 동적 분석의 높이를 변경할 수 있습니다.
override func viewWillLayoutSubviews() {
super.updateViewConstraints()
self.tableHeight?.constant = self.table.contentSize.height
}
최신 정보
마지막 행이 잘린 경우 willDisplay 셀 함수에서 viewWillLayoutSubviews ()를 호출하십시오.
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
self.viewWillLayoutSubviews()
}
나는 iOS 7에서 이것을 시도했고 그것은 나를 위해 일했다.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView sizeToFit];
}
테이블보기에서 contentSize 속성에 대한 관찰자를 추가하고 그에 따라 프레임 크기를 조정하십시오.
[your_tableview addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];
콜백에서 :
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
CGRect frame = your_tableview.frame;
frame.size = your_tableview.contentSize;
your_tableview.frame = frame;
}
이것이 도움이되기를 바랍니다.
테이블 뷰의 컨텐츠 크기 변경을 직접 추적하지 않으려는 경우이 서브 클래스가 유용 할 수 있습니다.
protocol ContentFittingTableViewDelegate: UITableViewDelegate {
func tableViewDidUpdateContentSize(_ tableView: UITableView)
}
class ContentFittingTableView: UITableView {
override var contentSize: CGSize {
didSet {
if !constraints.isEmpty {
invalidateIntrinsicContentSize()
} else {
sizeToFit()
}
if contentSize != oldValue {
if let delegate = delegate as? ContentFittingTableViewDelegate {
delegate.tableViewDidUpdateContentSize(self)
}
}
}
}
override var intrinsicContentSize: CGSize {
return contentSize
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
return contentSize
}
}
스크롤보기 안에 테이블보기가 있었고 tableView의 높이를 계산하고 그에 따라 크기를 조정해야했습니다. 내가 취한 단계는 다음과 같습니다.
0) scrollView에 UIView를 추가하십시오 (아마도이 단계없이 작동하지만 가능한 충돌을 피하기 위해 시도했습니다)-이것은 테이블 뷰의 컨테이너 뷰입니다. 이 단계를 수행하면 뷰 경계를 테이블 뷰의 경계로 바로 설정하십시오.
1) UITableView의 하위 클래스를 만듭니다.
class IntrinsicTableView: UITableView {
override var contentSize:CGSize {
didSet {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
self.layoutIfNeeded()
return CGSize(width: UIViewNoIntrinsicMetric, height: contentSize.height)
}
}
2) 스토리 보드의 테이블 뷰 클래스를 IntrinsicTableView로 설정하십시오. 스크린 샷 : http://joxi.ru/a2XEENpsyBWq0A
3) heightConstraint를 테이블 뷰로 설정하십시오.
4) 테이블의 IBoutlet을 ViewController로 드래그하십시오.
5) 테이블 높이 제약 조건의 IBoutlet을 ViewController로 드래그하십시오.
6)이 메소드를 ViewController에 추가하십시오.
override func viewWillLayoutSubviews() {
super.updateViewConstraints()
self.yourTableViewsHeightConstraint?.constant = self.yourTableView.intrinsicContentSize.height
}
도움이 되었기를 바랍니다
스위프트 3, iOS 10.3
해결 방법 1 : 그냥 넣어self.tableview.sizeToFit()
에서cellForRowAt indexPath
기능. 테이블 뷰 높이를 필요한 높이보다 높게 설정하십시오. tableview 아래에 뷰가없는 경우 좋은 솔루션입니다. 그러나 가지고 있다면 하단 테이블 뷰 제약 조건이 업데이트되지 않습니다 (솔루션 2를 생각해 냈으므로 수정하지 않았습니다)
예:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as? TestCell {
cell.configureCell(data: testArray[indexPath.row])
self.postsTableView.sizeToFit()
return cell
}
return UITableViewCell()
}
해결 방법 2 : 스토리 보드에서 테이블 뷰 높이 제약 조건을 설정하고 ViewController로 끕니다. 셀의 평균 높이를 알고 배열에 포함 된 요소 수를 알고 있으면 다음과 같이 할 수 있습니다.
tableViewHeightConstraint.constant = CGFloat(testArray.count) * 90.0 // Let's say 90 is the average cell height
*편집하다:
모든 솔루션을 한 후 나는 시도하고 그들의 모든 뭔가를 해결했다,하지만 완전히 이 이 문제를 완전히 설명하고 수정 대답이다.
contentSize가 올바르지 않은 경우 추정 된 RowHeight (자동)를 기반으로하기 때문에이 값을 사용하십시오.
tableView.estimatedRowHeight = 0;
출처 : https://forums.developer.apple.com/thread/81895
Mimo의 대답 과 Anooj VM의 대답은 모두 훌륭하지만 목록이 큰 경우 작은 문제가 있습니다. 프레임 높이가 일부 셀을 차단 할 수 있습니다.
그래서. 나는 대답을 약간 수정했다.
dispatch_async(dispatch_get_main_queue()) {
//This code will run in the main thread:
CGFloat newHeight=self.tableView.contentSize.height;
CGFloat screenHeightPermissible=(self.view.bounds.size.height-self.tableView.frame.origin.y);
if (newHeight>screenHeightPermissible)
{
//so that table view remains scrollable when 'newHeight' exceeds the screen bounds
newHeight=screenHeightPermissible;
}
CGRect frame = self.tableView.frame;
frame.size.height = newHeight;
self.tableView.frame = frame;
}
AutoLayout을 사용하는 경우 훨씬 더 좋은 방법이 있습니다. 높이를 결정하는 구속 조건을 변경하십시오. 테이블 내용의 높이를 계산 한 다음 구속 조건을 찾아 변경하십시오. 다음은 예입니다 (테이블 높이를 결정하는 구속 조건이 실제로 "같음"관계의 높이 구속 조건이라고 가정).
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
for constraint in tableView.constraints {
if constraint.firstItem as? UITableView == tableView {
if constraint.firstAttribute == .height {
constraint.constant = tableView.contentSize.height
}
}
}
}
Anooj VM의 답변의 확장으로 콘텐츠 크기가 변경 될 때만 콘텐츠 크기 를 새로 고치는 것이 좋습니다 .
이 방법은 스크롤을 제대로 비활성화 하고 더 큰 목록 과 회전을 지원합니다 . contentSize 변경 내용이 기본 스레드에서 전달되므로 dispatch_async가 필요하지 않습니다.
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:NULL];
}
- (void)resizeTableAccordingToContentSize:(CGSize)newContentSize {
CGRect superviewTableFrame = self.tableView.superview.bounds;
CGRect tableFrame = self.tableView.frame;
BOOL shouldScroll = newContentSize.height > superviewTableFrame.size.height;
tableFrame.size = shouldScroll ? superviewTableFrame.size : newContentSize;
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.tableView.frame = tableFrame;
} completion: nil];
self.tableView.scrollEnabled = shouldScroll;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([change[NSKeyValueChangeKindKey] unsignedIntValue] == NSKeyValueChangeSetting &&
[keyPath isEqualToString:@"contentSize"] &&
!CGSizeEqualToSize([change[NSKeyValueChangeOldKey] CGSizeValue], [change[NSKeyValueChangeNewKey] CGSizeValue])) {
[self resizeTableAccordingToContentSize:[change[NSKeyValueChangeNewKey] CGSizeValue]];
}
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self resizeTableAccordingToContentSize:self.tableView.contentSize]; }
- (void)dealloc {
[self.tableView removeObserver:self forKeyPath:@"contentSize"];
}
Musa almatri의 objc 버전
(void)viewWillLayoutSubviews
{
[super updateViewConstraints];
CGFloat desiredHeight = self.tableView.contentSize.height;
// clamp desired height, if needed, and, in that case, leave scroll Enabled
self.tableHeight.constant = desiredHeight;
self.tableView.scrollEnabled = NO;
}
이 사용자 정의를 시도해 볼 수 있습니다 AGTableView
To Set a TableView Height Constraint Using storyboard or programmatically. (This class automatically fetch a height constraint and set content view height to yourtableview height).
class AGTableView: UITableView {
fileprivate var heightConstraint: NSLayoutConstraint!
override init(frame: CGRect, style: UITableViewStyle) {
super.init(frame: frame, style: style)
self.associateConstraints()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.associateConstraints()
}
override open func layoutSubviews() {
super.layoutSubviews()
if self.heightConstraint != nil {
self.heightConstraint.constant = self.contentSize.height
}
else{
self.sizeToFit()
print("Set a heightConstraint to Resizing UITableView to fit content")
}
}
func associateConstraints() {
// iterate through height constraints and identify
for constraint: NSLayoutConstraint in constraints {
if constraint.firstAttribute == .height {
if constraint.relation == .equal {
heightConstraint = constraint
}
}
}
}
}
Note If any problem to set a Height then yourTableView.layoutSubviews()
.
Based on answer of fl034. But for Xamarin.iOS users:
[Register("ContentSizedTableView")]
public class ContentSizedTableView : UITableView
{
public ContentSizedTableView(IntPtr handle) : base(handle)
{
}
public override CGSize ContentSize { get => base.ContentSize; set { base.ContentSize = value; InvalidateIntrinsicContentSize(); } }
public override CGSize IntrinsicContentSize
{
get
{
this.LayoutIfNeeded();
return new CGSize(width: NoIntrinsicMetric, height: ContentSize.Height);
}
}
}
If you want your table to be dynamic, you will need to use a solution based on the table contents as detailed above. If you simply want to display a smaller table, you can use a container view and embed a UITableViewController in it - the UITableView will be resized according to the container size.
This avoids a lot of calculations and calls to layout.
Mu solution for this in swift 3: Call this method in viewDidAppear
func UITableView_Auto_Height(_ t : UITableView)
{
var frame: CGRect = t.frame;
frame.size.height = t.contentSize.height;
t.frame = frame;
}
참고URL : https://stackoverflow.com/questions/2595118/resizing-uitableview-to-fit-content
'development' 카테고리의 다른 글
Android : BOTTOM의 탭 (0) | 2020.06.13 |
---|---|
액세스가 허용되지 않은 데이터베이스를 숨기는 방법 (0) | 2020.06.13 |
새 Rails 앱을 만들 때 Rails에게 테스트 단위 대신 RSpec을 사용하도록 지시하려면 어떻게해야합니까? (0) | 2020.06.13 |
Convert.ToString ()과 .ToString ()의 차이점 (0) | 2020.06.13 |
많은 UI 구성 요소가이를 필요로하기 때문에 호출 스레드는 STA이어야합니다. (0) | 2020.06.13 |