AutoLayout 實現固定寬度動態高度的 ScrollView

2021-02-17 iOS開發

作為一個iOS 開發者,很多情況下會需要把一個和屏幕等寬的 contentview 添加到一個 scollrview 內部中。大多數的 app 需要有響應式布局,所以使用 Autolayout 可謂明智之選。第一次學習 scrollviews 時,你或許會覺得碉堡了。但它們奇怪的規則也會令人有點沮喪。

準備

你對 Xcode 和 interface builder 都足夠熟悉。

在 ScrollView 內的 Content View

這篇文章重點在 autolayout,所以我要用各種方式來告訴你如何處理它。第一個方式是 interface builder,因為這是最直觀的。

設置垂直滾動視圖的 interface builder

創建一個新的單視圖控制器應用程式,打開 storyboard,添加一個 scrollview 到 storyboard 上的ViewController 上。使 scrollview 填滿整個 viewcontroller 的 view。然後使用 storyborad 右下角的 pin 菜單,給 scrollview 添加上、左、右、下的約束。確保你沒有選中「constrain to margin」複選框。圖1 顯示了正確設置的 pin 菜單。這將添加 scrollview 和它的父視圖之間的約束。

圖1:給scrollview添加 上,左,右下的約束。

現在你想添加一個標準的 view 到 scrollview 上。就如你剛剛給 scrollview 添加上、左、右、下的約束那樣,給這個新 view 也添加這些約束,並確保這些約束的值都是0。

當你完成後,通過選中 view 面板中的 view ,查看在右側的 Size Inspector, 可以查看添加到 scrollview 和 Container view 的約束。圖2 顯示了內容視圖, 但 scroll view 應該看起來也是一樣的。

圖2:Size inspector 顯示在 scrollview 和 container view 上的約束。

ok,現在容器視圖裡已經有了一個 container view。有人會認為,因為我們給 scrollview 的邊緣添加了上、左、下、右的約束,所以這個 container view 將會一直在 scrollview 的上面,並且擁有和窗口一樣的寬度。但事實並非如此,因為 scrollviews 略有不同,這些約束定義了 scrollview 的 content size ,但因為我們的 view 沒有一個確切的 width 或 height ,所以這個 content size 的 wide 和 tall 都是0。

通常我們都想要一個 scrollview 只能垂直滾動,所以並不想讓 container view 比窗口寬,而高度我們通常是想要動態的,所以它會像其內部的 contents 一樣高,稍後再說動態高度,現在將解決固定寬度的問題。

設置垂直滾動

我們要確保 containner view 的寬度不會超過 window 的大小,為此我們將 container view 和 main view (包含 ScrollView 的視圖)設置成等寬,在 view inspector 中,按著 ctrl 拖拽 main view 到container view 並從彈出的菜單中選中 EqualWidths。圖3 顯示了被連接的2個視圖。

圖3 按著 Ctrl 拖拽 main view 向 container view

設置動態 Container view 高

最後一步,沒有那麼多的步驟指導。基本上,為了這項工作,container view 上所有的子視圖必須要有一個高度。一些子視圖可以使用它們固有的高度,通常是由它們的寬來決定的。一般地,你需要為任何沒有包含文本的視圖指定寬度和高度。這些包含文本的視圖至少有一個指定的寬或 margins。

第一個和最後一個視圖應該分別以 container view 的頂部和底部分別固定。例如 在圖4中,注意在圖4中所有的視圖都有左和右的約束,這將決定每個視圖的寬度。labels 不具有高度的約束,因為它將取決於其內容的大小。方形的視圖有確切的高度約束。還要注意所有的視圖頂部和底部之間有一個顯示的垂直約束。綜合這些就能決定 contanier view 的高,還有scrollview 的 content size。

在圖4中顯示如下約束。

圖4 添加子視圖到容器視圖示例

注意:如果要想 label 的 content 自動增長,就要先選中label並在屬性檢查器重設置 label 的行數為」0」。這樣 label 的行數就沒有限制了。

現在給底部的lable設置一段文字並運行這個例子,將會觸發垂直滾動的條件。圖5 顯示了堆疊視圖。從圖5中可以看出,在容器視圖頂部圖4所示的單個視圖,容器視圖堆放在 scrollview 上,然後是 main view,最後是 window。

圖5 模擬堆疊視圖

設置垂直滾動視圖編程

ok,這個部分將希望鞏固最後一節概念,創建一個single-view appliction的項目並打開ViewController.h文件。

注意:如果你熟練使用 Xcode 你也可以在原來的 storybord 上拖進一個新的 ViewController,創建一個類,設置這個ViewController的類為你新創建的那個類。你可以在右側的Identity Inspector裡設置.然後把這些類目放入一標題欄裡。

在ViewController.h裡,需要創建以下屬性:

當你完成你的代碼後,你的ViewController.h文件,應該和代碼1一樣。

代碼1 設置屬性

@interface ViewControllerTwo : UIViewController

@property (strong, nonatomic) UIView *contentView;

@property (strong, nonatomic) UIScrollView *scrollView;

@property (strong, nonatomic) UILabel *topLabel;

@property (strong, nonatomic) UILabel *bottomLabel;

@property (strong, nonatomic) UIView *boxView;

@end

在 ViewController.m 裡,第一步需要在 viewDidload 中需要設置scrollView的寬度。如代碼2中所示的添加 scrollView 和 contentView。

代碼2:在主視圖中添加滾動視圖和內容視圖

- (void)viewDidLoad{

[super viewDidLoad];

self.scrollView = [[UIScrollView alloc] init];

self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;

self.scrollView.backgroundColor = [UIColor blueColor];

[self.view addSubview:self.scrollView];

self.contentView = [[UIView alloc] init];

self.contentView.backgroundColor = [UIColor redColor];

self.contentView.translatesAutoresizingMaskIntoConstraints = NO;

[self.scrollView addSubview:self.contentView];

再一次我們設置 scrollview 相對於 view 的 margins 為0 ,contentView 相對於 content viewmarigins 為0。最後將 content view 的 width 與 main view 的 width 設為一致。這些都是以編程方式添加的約束。將代碼3中的代碼添加到 viewDidLoad 方法裡代碼2的後面。

代碼3:添加contentView和scrolView的約束

NSDictionary *tmpViewsDictionary = @{@"scrollView":self.scrollView,

@"contentView":self.contentView};

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[scrollView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[scrollView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[contentView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[contentView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];

在這份代碼中,我們使用了兩種不同類型的約束。第一種使用的是 Visual format language,這是一種很好的添加多個約束的字符串描述。例如:

把它們連接在一起作為第一個約束 @「V:|-(0)-[scrollView]-(0)-|」

這行代碼的意思是給scrollview添加距 superview 左右都為0的 margin。

更多關於visual format languge 請查看文檔:Visual Format Language

寬度約束是將約束添加到視圖的標準方式,你可以看得更清楚,但是有點繁瑣。

最後,調用一個新的方法,把剩餘的視圖添加到content view中,我們把它叫做 addContentSubViews。

代碼4 展示了這個複雜的 viewDidLoad 方法。

代碼4 完整的 viewDidLoad 方法

- (void)viewDidLoad{

[super viewDidLoad];

self.scrollView = [[UIScrollView alloc] init];

self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;

self.scrollView.backgroundColor = [UIColor blueColor];

[self.view addSubview:self.scrollView];

self.contentView = [[UIView alloc] init];

self.contentView.backgroundColor = [UIColor redColor];

self.contentView.translatesAutoresizingMaskIntoConstraints = NO;

[self.scrollView addSubview:self.contentView];

NSDictionary *tmpViewsDictionary = @{@"scrollView":self.scrollView,

@"contentView":self.contentView};

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[scrollView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[scrollView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[contentView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[contentView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];

[self addContentSubViews];

}

addContentSubViews方法十分簡單,僅僅創建了幾個label和一個box view.label的numberoflines = 0,意味著lable的content會滿足多行的需求。label 居中且自動換行。

代碼5 展示了應該添加下面的viewDidLoad方法完整的方法。

代碼5: addContentSubViews 實現

- (void)addContentSubViews{

self.topLabel = [[UILabel alloc] init];

self.topLabel.translatesAutoresizingMaskIntoConstraints = NO;

self.topLabel.numberOfLines = 0;

self.topLabel.textAlignment = NSTextAlignmentCenter;

self.topLabel.lineBreakMode = NSLineBreakByWordWrapping;

self.topLabel.text = @"Some text label. that may have several lines";

self.topLabel.textColor = [UIColor blackColor];

[self.contentView addSubview:self.topLabel];

self.boxView = [[UIView alloc] init];

self.boxView.translatesAutoresizingMaskIntoConstraints = NO;

self.boxView.backgroundColor = [UIColor lightGrayColor];

[self.contentView addSubview:self.boxView];

self.bottomLabel = [[UILabel alloc] init];

self.bottomLabel.numberOfLines = 0;

self.bottomLabel.textAlignment = NSTextAlignmentCenter;

self.bottomLabel.lineBreakMode = NSLineBreakByWordWrapping;

self.bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;

self.bottomLabel.text = [self bottomLabelText];

self.bottomLabel.textColor = [UIColor blackColor];

[self.contentView addSubview:self.bottomLabel];

[self addContentSubViewConstraints];

}

在代碼5 中 我們實現了兩個新方法。一個簡單地返回一個大字符串。代碼6展示 bottomLabelText 方法的實現。

代碼6: bottomLabelText 實現

- (NSString *)bottomLabelText{

return @"Put in a massive string of your own here to see the scrolling in action";

}

最後一種方法將添加所有的約束來定義內容視圖的內容高度。代碼7是 addContentSubViewConstraints 的最終實現,它添加了和IB中所展示的完全相同的約束。

這是相當多的。代碼7展示了完整的viewController.m文件。

代碼7:viewcontoller.m完整視圖

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad{

[super viewDidLoad];

self.scrollView = [[UIScrollView alloc] init];

self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;

self.scrollView.backgroundColor = [UIColor blueColor];

[self.view addSubview:self.scrollView];

self.contentView = [[UIView alloc] init];

self.contentView.backgroundColor = [UIColor redColor];

self.contentView.translatesAutoresizingMaskIntoConstraints = NO;

[self.scrollView addSubview:self.contentView];

NSDictionary *tmpViewsDictionary = @{@"scrollView":self.scrollView,

@"contentView":self.contentView};

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[scrollView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[scrollView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(0)-[contentView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[contentView]-(0)-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];

[self addContentSubViews];

}

- (void)addContentSubViews{

self.topLabel = [[UILabel alloc] init];

self.topLabel.translatesAutoresizingMaskIntoConstraints = NO;

self.topLabel.numberOfLines = 0;

self.topLabel.textAlignment = NSTextAlignmentCenter;

self.topLabel.lineBreakMode = NSLineBreakByWordWrapping;

self.topLabel.text = @"Some text label. that may have several lines";

self.topLabel.textColor = [UIColor blackColor];

[self.contentView addSubview:self.topLabel];

self.boxView = [[UIView alloc] init];

self.boxView.translatesAutoresizingMaskIntoConstraints = NO;

self.boxView.backgroundColor = [UIColor lightGrayColor];

[self.contentView addSubview:self.boxView];

self.bottomLabel = [[UILabel alloc] init];

self.bottomLabel.numberOfLines = 0;

self.bottomLabel.textAlignment = NSTextAlignmentCenter;

self.bottomLabel.lineBreakMode = NSLineBreakByWordWrapping;

self.bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;

self.bottomLabel.text = [self bottomLabelText];

self.bottomLabel.textColor = [UIColor blackColor];

[self.contentView addSubview:self.bottomLabel];

[self addContentSubViewConstraints];

}

- (NSString *)bottomLabelText{

return @"Mauris utinam singularis nostrud et vel et defui aliquip duis. Regula suscipere vel ratis damnum in vindico voco verto antehabeo sit bene. Singularis decet capto luptatum sit delenit suscipit aliquip consequat quis nullus ex.Gemino foras te pala consequat refero abbas in vel. Eum nimis commoveo eros eu. Facilisi in pagus gemino exputo quadrum conventio erat. Haero loquor ut quis sudo immitto adsum sit multo proprius esse.Iustum esse si reprobo utrum et vero ad loquor ne. Duis in nulla. Nutus autem brevitas meus iriure verto ullamcorper velit facilisi. Scisco minim damnum quis transverbero eligo nunc nibh tego.Pala vereor uxor ratis macto enim feugiat iustum os delenit. Antehabeo valetudo vel. Neo patria et iaceo nutus. Ut vero veniam ventosus duis consequat verto. Opto neque nonummy. Duis scisco quidne vero nostrud quidne exputo adsum meus qui. Zelus uxor nobis consequat uxor augue decet. Indoles populus consequat iusto et facilisis pecus nunc feugiat vel valde. Delenit sit nisl indoles minim incassum utinam epulae quae euismod dolor tation. Multo ut vero indoles exputo commoveo. Scisco molior tamen ille. Luptatum cogo accumsan luptatum eu fatua usitas. Molior bene elit paratus sed consequat augue veniam probo patria. Nutus quidem feugiat nonummy ad delenit facilisis ea quibus suscipit. Refero utrum torqueo feugait blandit aliquip ad vulputate cui ideo. Nunc vulputate paulatim dolor volutpat vel brevitas. Reprobo iusto vindico. Qui quis commodo augue nostrud nulla eu consequat minim at imputo. Iriure ullamcorper feugait genitus scisco in scisco obruo jus. Consequat abdo quae dignissim iusto suscipere nulla ad jugis duis virtus. Enim vulputate luptatum in voco haero. Feugiat euismod validus sudo uxor abbas. Ingenium obruo neo. Blandit consequat luptatum euismod sino utrum tego suscipit dignissim suscipit. Sed gilvus utrum in capto Velit ventosus adsum delenit et. Vel verto quidem sit qui vulputate ut autem. Accumsan distineo wisi populus hendrerit ne indoles ille facilisis ut erat hendrerit. Populus sino velit premo dolore neque. Augue ulciscor blandit venio facilisi capto quae praesent ad. Vero opto interdico a roto eros abico. Olim eros ad comis incassum wisi consequat dolus molior oppeto in voco. Genitus caecus duis usitas nisl illum suscipit nulla importunus melior autem. Ulciscor tum quia feugiat paratus olim quod quidem. Duis consequat refoveo nulla refoveo nulla wisi nostrud velit. Neque et caecus ne ad occuro nutus diam vulputate. Populus eros quis ne at quia sit luctus. Adipiscing verto olim et virtus luctus nimis foras nisl in eum mos. Imputo saepius lenis reprobo vero. Aliquam probo ea imputo vicis et suscipere. Vulpes iusto imputo dignissim. Dolore aptent feugiat qui et nibh vicis modo abigo. Sit verto minim feugiat nulla praemitto caecus capto lucidus ullamcorper. Fere eu duis facilisi torqueo.";

}

- (void)addContentSubViewConstraints{

NSDictionary *tmpViewsDictionary = @{@"topLabel":self.topLabel,

@"boxView":self.boxView,

@"bottomLabel":self.bottomLabel};

[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(60)-[topLabel]-[boxView(86)]-[bottomLabel]-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[topLabel]-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[bottomLabel]-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[boxView]-|" options:0 metrics:nil views:tmpViewsDictionary]];

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.boxView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];

}

@end

噢, 別忘了 swift,代碼8 是完整的 swift 版實現。

代碼8 :完整的swift 控制器

GeSHi Error: GeSHi could not find the language swift (using path /home1/jhoffman/nscookbook/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

注意:使用 swift 時我不得不為 content view 定義一個高,這如沒有任何意義一般,因為幾乎是逐字的將代碼轉換為 swift.目前看來像是一個 swift bug,有任何消息我會通知你,我猜在 swift 2 時會表現的更好。好了,這期就到這裡了,希望對你有所幫助。

相關焦點

  • 使用DIV+CSS 創建固定寬度的布局
    到目前為止,所有例子都使用流式布局(也就是布局會自動擴展和適應瀏覽器窗口的寬度)。現在是時候考慮另外一種主要的頁面布局方法了,這種布局方法是固定寬度布局。很多 Web 構建人員傾向於使用固定寬度的布局進行頁面設計,因為它們能生成精確且可預知的結果。
  • 帶你了解 Android 約束布局 ConstraintLayout
    然後通過layout_constraintDimensionRatio屬性設置一個比率即可。這個比率可以是一個浮點數,表示寬度和高度之間的比率;也可以是「寬度:高度」形式的比率。比如:<?xml version="1.0" encoding="utf-8"?
  • 為什麼當高度為固定大小值時,marign:auto 0很難垂直居中元素?
    二、居中原理分析1、使用margin:0 auto水平居中本質原因水平居中原理上一篇寫的很詳細,需要多讀幾遍,總結一下就是:元素定位是static/relative時,塊級元素表現具有滿屏特性,滿屏表現出水平方向上佔滿整個父容器的寬度
  • Android MotionLayout動畫:續寫ConstraintLayout新篇章
    有部分同學說性能問題,其實對於初中級開發者來說,暫無需考慮這個,相比自己動手嵌套幾層布局強吧,而且更重要的是業務UI的實現,尤其工作量大的時候。本文屬於入門級別,重點在於掃盲和入門。如果對你有用,歡迎點讚。個人能力有限,有些東西可能理解不透或不對,歡迎指正,非常感謝。
  • Android scrollView
    添加子視圖的位置params 為子視圖設置的layout參數public void addView (View child, ViewGroup.LayoutParams params)根據指定的layout參數添加子視圖。
  • 小程序滾動組件scrollview
    好久沒更新小程序的系列文章了,之前有出過小程序的實戰,但是,最近代碼君發現,代碼集中營的好多讀者都是小程序的初學者,所以我覺得有必要出一些基礎的教程給初學者學習和使用,因此代碼君決定每天講解小程序的一個基礎知識點,帶著初學者一起學習小程序,如果覺得簡單的讀者可以去看代碼君的小程序實戰篇,好,言歸正傳,今天我就先講一個基礎的滾動組件scrollview
  • MotionLayout系列之配合布局CoordinatorLayout, DrawerLayout, ViewPager使用
    在 Coordinatorlayout 中使用 MotionLayout:( MotionLayout 可以實現類似 CoodinatorLayout 的功能,我們將在以後的文章中提供示例)可以通過 MotionLayout 指定一部分 View 的動畫,將更多有趣的動畫加到已經存在的布局中。
  • 用Class組合實現Div+CSS布局
    首頁 > 教程 > 關鍵詞 > 布局最新資訊 > 正文 用Class組合實現Div+CSS布局
  • ConstraintLayout 介紹
    layout_constraintRight_toLeftOflayout_constraintRight_toRightOflayout_constraintTop_toTopOflayout_constraintTop_toBottomOf
  • 如何使英語和連續數字的自動換行用CSS代碼實現?
    像div,p等塊級元素 ,正常文字的換行(亞洲文字和非亞洲文字)元素都是自動設定的white-space:normal,當定義了寬度之後就會自動實現換行:<div id="wrap">正常文字的換行(亞洲文字和非亞洲文字)元素擁有默認的white-space:normal,當定義</div>
  • Google 開源的 Android 排版庫:FlexboxLayout
    的一種布局,但是要比 Linearlayout 要強大的多。+ RelativeLayout 基本可以實現大部分複雜的布局,但是Google就想了,有沒有類似 Flexbox 的一個布局呢?android:layout_width="80dp"        android:layout_height="80dp"        app:layout_alignSelf="center"        />    <TextView        android:id="@+id/textview3"        android:layout_width="160dp"
  • CSS 中你需要知道 auto 的一切!
    </div></div>要使.item獲得其容器的全部高度,我們可以使用以下方法之一:給.wrapper一個固定的高度,然後為.item元素添加height: 100%對.wrapper使用 flex 布局,默認情況下它將拉伸子項.itemCSS.wrapper
  • CSS教程:認真學習haslayout
    當我們說一個元素「擁有layout」或「得到layout」,或者說一個元素 「has layout」 的時候,我們的意思是指它的微軟專有屬性 hasLayout 被設為了 true 。一個「layout元素」可以是一個默認就擁有 layout 的元素或者是一個通過設置某些 CSS 屬性得到 layout 的元素。
  • Android開發:如何在MotionLayout中使用動態數據
    可以使用MotionLayout創建數據的動態動畫嗎?這是任何你在編譯時不知道的數據,比如用戶輸入。對!當然。可以使用MotionLayout代碼API在代碼中動態創建MotionScene。在本文中,我們將使用開發一個動態直方圖,該直方圖使用MotionLayout設置其更改的動畫。
  • 【精講】CoordinatorLayout與滾動的處理
    app:layout_scrollFlags屬性裡面必須至少啟用scroll這個flag,這樣這個view才會滾動出屏幕,否則它將一直固定在頂部。假設你定義了一個最小高度(minHeight)同時enterAlways也定義了,那麼view將在到達這個最小高度的時候開始顯示,並且從這個時候開始慢慢展開,當滾動到頂部的時候展開完。exitUntilCollapsed: 同樣顧名思義,這個flag時定義何時退出,當你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失。
  • Android 8.0 LinearLayout 源碼解析
    其中,最重要的就是有三類:a. mTotalLength:所有 childView 的高度和 + 本身的 padding,注意:它和 LinearLayout 本身的高度是不同的。b.三個寬度相關的變量maxWidth:所有 childView 中寬度的最大值alternativeMaxWidth:所有 layout_weight <= 0 的 childView 中寬度的最大值weightedMaxWidth:所有 layout_weight >0 的 childView 中寬度的最大值c. totalWeight