LayoutOptions ของ Xamarin.Form แตกต่างกันอย่างไรโดยเฉพาะ Fill และ Expand?


170

ใน Xamarin.Forms ทุกViewมีสองคุณสมบัติและHorizontalOptions VerticalOptionsทั้งสองเป็นประเภทLayoutOptionsและสามารถมีหนึ่งในค่าต่อไปนี้:

  • LayoutOptions.Start
  • LayoutOptions.Center
  • LayoutOptions.End
  • LayoutOptions.Fill
  • LayoutOptions.StartAndExpand
  • LayoutOptions.CenterAndExpand
  • LayoutOptions.EndAndExpand
  • LayoutOptions.FillAndExpand

เห็นได้ชัดว่ามันควบคุมการจัดแนวของมุมมองในมุมมองหลัก แต่พฤติกรรมของแต่ละตัวเลือกเป็นอย่างไร และความแตกต่างระหว่างFillและคำต่อท้ายExpandคืออะไร?

คำตอบ:


335

คำตอบสั้น ๆ

Start, Center, EndและFillกำหนดมุมมองของการจัดตำแหน่งภายในพื้นที่ของตน

Expandกำหนดว่าจะใช้พื้นที่มากขึ้นถ้ามี

ทฤษฎี

โครงสร้างLayoutOptionsควบคุมพฤติกรรมที่แตกต่างกันสองอย่าง:

  1. การจัดแนว: มุมมองจัดแนวภายในมุมมองพาเรนต์อย่างไร

    • Start: สำหรับการจัดแนวตั้งมุมมองจะถูกย้ายไปด้านบน สำหรับการจัดตำแหน่งแนวนอนโดยปกติแล้วจะอยู่ทางด้านซ้ายมือ (แต่โปรดทราบว่าในอุปกรณ์ที่มีการตั้งค่าภาษาจากขวาไปซ้ายนี่เป็นอีกทางหนึ่งเช่นจัดชิดขวา)
    • Center: มุมมองอยู่กึ่งกลาง
    • End: โดยปกติมุมมองจะจัดชิดด้านล่างหรือขวา (แน่นอนว่าภาษาจากขวาไปซ้ายจัดชิดซ้าย)
    • Fill: การจัดตำแหน่งนี้จะแตกต่างกันเล็กน้อย มุมมองจะขยายไปทั่วขนาดเต็มของมุมมองพาเรนต์

    อย่างไรก็ตามหากผู้ปกครองไม่ใหญ่กว่าลูกของคุณคุณจะไม่สังเกตเห็นความแตกต่างระหว่างการจัดแนวเหล่านั้น การจัดตำแหน่งจะทำเฉพาะมุมมองพาเรนต์เท่านั้นที่มีพื้นที่เพิ่มเติม

  2. การขยายตัว: องค์ประกอบจะใช้พื้นที่มากขึ้นหรือไม่ถ้ามี

    • คำต่อท้ายExpand: หากมุมมองพาเรนต์มีขนาดใหญ่กว่าขนาดรวมของเด็กทั้งหมดเช่นพื้นที่เพิ่มเติมจะมีอยู่พื้นที่นั้นจะถูกจัดสัดส่วนตามมุมมองของเด็กด้วยส่วนต่อท้ายนั้น เด็กเหล่านั้นจะ "ครอบครอง" พื้นที่ของพวกเขา แต่ไม่จำเป็นต้อง "เติม" มัน เราจะดูพฤติกรรมนี้ในตัวอย่างด้านล่าง
    • ไม่มีคำต่อท้าย: เด็กที่ไม่มีExpandคำต่อท้ายจะไม่ได้รับพื้นที่เพิ่มเติมแม้ว่าจะมีพื้นที่ว่างเพิ่มขึ้นก็ตาม

    อีกครั้งถ้ามุมมองพาเรนต์ไม่ใหญ่กว่าลูกของมันส่วนต่อท้ายการขยายก็ไม่ได้สร้างความแตกต่างเช่นกัน

ตัวอย่าง

ลองมาดูตัวอย่างต่อไปนี้เพื่อดูความแตกต่างระหว่างตัวเลือกเค้าโครงทั้งแปด

แอพประกอบด้วยสีเทาเข้มStackLayoutพร้อมปุ่มสีขาวซ้อนกันแปดปุ่มแต่ละปุ่มมีป้ายกำกับพร้อมตัวเลือกการจัดวางแนวตั้ง เมื่อคลิกที่ปุ่มใดปุ่มหนึ่งมันจะกำหนดตัวเลือกโครงร่างแนวตั้งให้กับโครงร่างสแต็ก วิธีนี้เราสามารถทดสอบการโต้ตอบของมุมมองกับผู้ปกครองได้อย่างง่ายดายด้วยตัวเลือกการจัดวางที่แตกต่างกัน

(โค้ดสองสามบรรทัดสุดท้ายเพิ่มกล่องสีเหลืองเพิ่มเติมเราจะกลับมาที่นี่อีกสักครู่)

public static class App
{
    static readonly StackLayout stackLayout = new StackLayout {
        BackgroundColor = Color.Gray,
        VerticalOptions = LayoutOptions.Start,
        Spacing = 2,
        Padding = 2,
    };

    public static Page GetMainPage()
    {
        AddButton("Start", LayoutOptions.Start);
        AddButton("Center", LayoutOptions.Center);
        AddButton("End", LayoutOptions.End);
        AddButton("Fill", LayoutOptions.Fill);
        AddButton("StartAndExpand", LayoutOptions.StartAndExpand);
        AddButton("CenterAndExpand", LayoutOptions.CenterAndExpand);
        AddButton("EndAndExpand", LayoutOptions.EndAndExpand);
        AddButton("FillAndExpand", LayoutOptions.FillAndExpand);

        return new NavigationPage(new ContentPage {
            Content = stackLayout,
        });
    }

    static void AddButton(string text, LayoutOptions verticalOptions)
    {
        stackLayout.Children.Add(new Button {
            Text = text,
            BackgroundColor = Color.White,
            VerticalOptions = verticalOptions,
            HeightRequest = 20,
            Command = new Command(() => {
                stackLayout.VerticalOptions = verticalOptions;
                (stackLayout.ParentView as Page).Title = "StackLayout: " + text;
            }),
        });
        stackLayout.Children.Add(new BoxView {
            HeightRequest = 1,
            Color = Color.Yellow,
        });
    }
}

ภาพหน้าจอต่อไปนี้แสดงผลลัพธ์เมื่อคลิกที่ปุ่มทั้งแปดปุ่ม เราทำการสังเกตต่อไปนี้:

  • ตราบใดที่พาเรนต์stackLayoutแน่น (ไม่ใช่Fillเพจ) ตัวเลือกเลย์เอาต์แนวตั้งของแต่ละรายการButtonนั้นเล็กน้อย
  • ตัวเลือกเลย์เอาต์แนวตั้งนั้นสำคัญหากstackLayoutมีขนาดใหญ่ขึ้น (เช่นผ่านFillการจัดตำแหน่ง) และปุ่มแต่ละปุ่มจะมีExpandคำต่อท้าย
  • พื้นที่เพิ่มเติมถูกแบ่งสัดส่วนอย่างชัดเจนในทุกปุ่มด้วยExpandคำต่อท้าย เมื่อต้องการดูสิ่งนี้ชัดเจนยิ่งขึ้นเราได้เพิ่มเส้นแนวนอนสีเหลืองระหว่างปุ่มสองปุ่มที่อยู่ใกล้เคียง
  • ปุ่มที่มีพื้นที่มากกว่าความสูงที่ร้องขอไม่จำเป็นต้อง "เติม" ในกรณีนี้พฤติกรรมที่แท้จริงจะถูกควบคุมโดยการจัดตำแหน่งของพวกเขา เช่นมีการจัดแนวทั้งด้านบนกึ่งกลางหรือปุ่มของพื้นที่หรือเติมให้สมบูรณ์
  • VerticalOptionsปุ่มทั้งหมดครอบคลุมทั่วทั้งความกว้างของรูปแบบตั้งแต่เราปรับเปลี่ยน

ภาพหน้าจอ

ที่นี่คุณจะพบภาพหน้าจอความละเอียดสูงที่เกี่ยวข้อง


6
ภาพดูเหมือน [[midfing]], lol เพียงแค่ล้อเล่นมันมีประโยชน์จริงๆ
Joy Rex

1
@JoyRex: เอาละรุ่นนี้อาจจะสับสนเล็กน้อย ;)
Falko

2
ฉันสับสนกับผลลัพธ์ข้างต้น เริ่ม & เริ่มและขยายทั้งสองเป็นเอาต์พุตเดียวกัน .. ความแตกต่างระหว่างสิ่งเหล่านี้คืออะไร คุณสามารถให้คำอธิบายหากเป็นไปได้ ..
Ranjith Kumar

1
FillAndExpandคือสิ่งที่คุณต้องการ 99% ตลอดเวลา
Stephane Delcroix

1
@RanjithKumar พวกเขาเหมือนกัน มัน StackLayout ถูกซ่อนอยู่ในปกครองอีกแล้ว FillAndExpand มันสามารถสร้างความแตกต่าง - มันจะขยายภายในของผู้ปกครอง
Miha Markic

16

มีข้อผิดพลาดเล็กน้อยในรุ่นปัจจุบันของ Xamarin.Forms; อาจจะมีสักพัก

CenterAndExpand โดยทั่วไปจะไม่ขยายและการแก้ไขอาจทำให้สับสนได้

ตัวอย่างเช่นถ้าคุณมีStackLayoutชุดCenterAndExpandแล้วคุณใส่ป้ายภายในที่ยังตั้งค่าให้เป็นคุณจะคาดหวังฉลากที่มีความกว้างเต็มรูปแบบของการCenterAndExpand StackLayoutNope มันจะไม่ขยายตัว คุณจะต้องตั้งค่าStackLayoutที่ " FillAndExpand" เพื่อรับวัตถุป้ายซ้อนกันที่จะขยายไปเต็มความกว้างของแล้วบอกฉลากไปยังศูนย์ข้อความที่ตัวเองไม่ได้เป็นวัตถุที่มีStackLayout HorizontalTextAlignment="Center"จากประสบการณ์ของฉันคุณต้องตั้งค่าให้ทั้งผู้ปกครองและเด็กซ้อนกันFillAndExpandหากคุณต้องการให้แน่ใจว่ามันขยายให้พอดี

        <StackLayout HorizontalOptions="FillAndExpand"
                     Orientation="Vertical"
                     WidthRequest="300">
            <Label BackgroundColor="{StaticResource TileAlerts}"
                   HorizontalOptions="FillAndExpand"
                   Style="{StaticResource LabelStyleReversedLrg}"
                   HorizontalTextAlignment="Center"
                   Text="Alerts" />

3
"... คุณคาดหวังว่าป้ายกำกับที่เต็มความกว้างของ StackLayout" สมมติฐานนี้ไม่ถูกต้อง Expandใช้สำหรับลูกของ StackLayout เท่านั้น ดังนั้นหาก StackLayout ของคุณเป็นรูตหรือไม่อยู่ใน StackLayout อื่นExpandจะไม่มีผลกระทบ ตัวเลือกอื่น ๆ นอกเหนือจากการเติมจะทำหน้าที่เป็น "เนื้อหาแบบเต็ม" สำหรับการปรับขนาดซึ่งเป็นสิ่งที่คุณเห็น
therealjohn

นอกจากนี้การขยายจะใช้งานได้เฉพาะกับ LayoutOptions ที่มีการวางแนวเดียวกันของ StackLayout ในกรณีนี้โครงร่างคือ "แนวตั้ง" แต่ตัวเลือกที่เป็นปัญหาคือแนวนอน (ตรงกันข้าม)
therealjohn

คำว่า "And ขยาย" ไม่ชัดเจน สามารถตีความได้ว่า "ขยายให้มากที่สุด" หรือ "ขยายเท่าที่ต้องการ" ผมคิดว่าไมโครซอฟท์ควรเปลี่ยนเงื่อนไขเพื่อสิ่งที่น้อยทำให้เกิดความสับสนเช่น "CenterAndExpandToParent" หรือ "CenterAndExpandAsNeeded"
technoman23

1

Falko ให้คำอธิบายที่ดี แต่ฉันต้องการเพิ่มเข้าไปในภาพอีกภาพหนึ่งและแท็กเหล่านี้ทำงานอย่างไรใน xaml ซึ่งเป็นสิ่งที่ฉันชอบใช้เป็นส่วนใหญ่ ฉันทำโครงการง่าย ๆ สำหรับทดสอบผลลัพธ์ที่แสดง นี่คือ Xaml สำหรับหน้าหลัก:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Alignments.MainPage"
             BackgroundColor="White">


    <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="LightGray" Padding="1" Margin="30">
        <Label Text="Vert: EndAndExpand, Horz: EndAndExpand" VerticalOptions="EndAndExpand" HorizontalOptions="EndAndExpand" BackgroundColor="White"/>
    </StackLayout>


</ContentPage>

อย่างที่คุณเห็นมันเป็น StackLayout ที่ง่ายมากพร้อมกับมี Label อยู่ข้างใน สำหรับแต่ละภาพด้านล่างฉันเก็บ StackLayout ไว้เหมือนเดิมฉันเพิ่งเปลี่ยนตัวเลือกแนวนอนและแนวตั้งสำหรับรายการและเปลี่ยนข้อความเพื่อแสดงตัวเลือกที่เลือกเพื่อให้คุณสามารถดูว่ารายการย้ายและปรับขนาดอย่างไร

เริ่มเทียบกับ StartAnd ขยาย นี่คือรหัสที่ใช้สำหรับการเริ่มต้น:

<Label Text="Vert: Start, Horz: Start" VerticalOptions="Start" HorizontalOptions="Start" BackgroundColor="White"/>

และรหัสที่ใช้สำหรับ StartAnd ขยาย:

<Label Text="Vert: StartAndExpand, Horz: StartAndExpand" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" BackgroundColor="White"/>

อย่างที่คุณเห็นว่าไม่มีความแตกต่างทางสายตานอกจากมีข้อความเพิ่มเติมที่ใช้ในตัวเลือก StartAnd ขยาย สิ่งนี้ได้รับการทดสอบบนอุปกรณ์ฟิสิคัล Samsung A30 ของฉัน สิ่งเหล่านี้อาจแสดงแตกต่างกันไปตามอุปกรณ์ต่าง ๆ แต่ฉันคิดว่าภาพทั้งหมดในที่นี้แสดงให้เห็นว่ามีข้อบกพร่องบางอย่างในซามาริน สำหรับส่วนที่เหลือฉันจะแสดงภาพหน้าจอฉันคิดว่าพวกเขาอธิบายตนเองได้

End vs EndAnd ขยาย

Center vs CenterAnd ขยาย

เติม vs FillAnd ขยาย

ฉันยังแนะนำให้ดูเอกสารของ Microsoftสำหรับรายละเอียดเพิ่มเติมบางอย่าง ที่โดดเด่นคือ "การขยายตัวถูกใช้โดย StackLayout เท่านั้น"


การสร้างภาพที่ดี แต่ฉันไม่เห็นว่าทำไมสิ่งนี้ควรแสดงข้อบกพร่องใน Xamarin สิ่งที่อาจทำให้เกิดความสับสนคือฉลากสามารถใช้พื้นที่มากกว่าพื้นหลังสีขาว (พื้นที่สีเทาในตัวอย่างของฉัน) ดังนั้นฉลาก "Vert Center" จึงอยู่กึ่งกลางภายในพื้นที่ที่ใช้ - ไม่ใช่ภายในหน้าทั้งหมด เห็นได้ชัดว่าหลังจากผ่านไปเกือบหกปีหัวข้อนี้ก็ยังคงสับสนเหมือนเดิม
Falko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.