Xamarin biểu mẫu Thêm nút trong TabbedPage
Tôi có một câu hỏi. Tôi đã tạo TabbedPage sau:
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:MyApp.Views"
mc:Ignorable="d"
x:Class="MyApp.Views.MainPage"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
BarBackgroundColor="White"
BarTextColor="Black"
android:TabbedPage.BarItemColor="#B2B2B2"
android:TabbedPage.BarSelectedItemColor="#56D7A5"
android:TabbedPage.IsSwipePagingEnabled="False">
<TabbedPage.Children>
<NavigationPage Title="page1" IconImageSource="navbar_page1">
<x:Arguments>
<views:page1 NavigationPage.HasNavigationBar="False" />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="page2" IconImageSource="navbar_page2">
<x:Arguments>
<views:page2 NavigationPage.HasNavigationBar="False" />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="page3" IconImageSource="navbar_page3">
<x:Arguments>
<views:page3 NavigationPage.HasNavigationBar="False" />
</x:Arguments>
</NavigationPage>
</TabbedPage>
Bây giờ trên mỗi trang tôi đã thêm FabMenu tùy chỉnh như thế này:
<c:FloatingMenu Margin="0, 0, 10, 10" BGColor="#56D7A5" OpenIcon="openFab_icon" CloseIcon="closeFab_icon"
AbsoluteLayout.LayoutBounds=".95,.95" AbsoluteLayout.LayoutFlags="PositionProportional">
<c:FloatingButton x:Name="btnAddHomework" BGColor="#59E1FF" IconSrc="add_homework_icon" OnClickCommand="{Binding btnAddHomeworkCommand}" />
<c:FloatingButton x:Name="btnAddDeadline" BGColor="#0FF1A0" IconSrc="add_deadline_icon"/>
<c:FloatingButton x:Name="btnAddTest" BGColor="#5988FF" IconSrc="add_test_icon"/>
</c:FloatingMenu>
Vấn đề là mỗi trang đều có FabMenu của riêng mình, vì vậy bạn sẽ thấy nó biến mất và xuất hiện lại trên mọi trang, vì vậy câu hỏi của tôi là: Có loại chế độ xem gốc nào đó phủ lên tất cả các tab trong TabbedPage không?
Xin vui lòng cho tôi biết làm thế nào tôi làm điều đó!
Trả lời
Khước từ
Tôi đã nghĩ ra một cách để tạo ra hiệu ứng mong muốn chỉ sử dụng Xamarin.Forms thuần túy. Đọc cùng và chú ý đến các phần phức tạp của giải pháp.
trừu tượng
Giải pháp này được thực hiện triển khai AbsoluteLayout, CarouselView, IndicatorViewvà DataTemplateSelector. Xamarin.Forms 4.8 được cho là như sau. Nếu sử dụng phiên bản thấp hơn, vui lòng lưu ý rằng các tính năng giống như CarouselViewhoặc IndicatorViewcó thể ở trạng thái Xem trước .
DataTemplateSelector, CarouselViewVà IndicatorViewđược sử dụng để mô phỏng một TabbedPage, và AbsoluteLayoutđược sử dụng để cung cấp các Overlay .
Vì vậy, bây giờ với giải pháp:
Tạo Chế độ xem của bạn
Tại đây, bạn tạo một dạng xem cho từng trang mà bạn muốn. Trong ví dụ này, tôi muốn ứng dụng của mình bao gồm hai trang, vì vậy tôi tạo hai chế độ xem (mã phía sau vẫn không bị ảnh hưởng):
View1.xaml
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="overlayTest.View1"
BackgroundColor="Black">
<ContentView.Content>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms 1!"
TextColor="White"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentView.Content>
</ContentView>
View2.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="overlayTest.View2">
<ContentView.Content>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms 2!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentView.Content>
</ContentView>
Tạo một DataTemplateSelector
Điều này sẽ được sử dụng CarouselViewđể chọn một chế độ xem này hoặc chế độ xem khác tùy thuộc vào hiện tại Position.
using System;
using Xamarin.Forms;
namespace overlayTest
{
class MyTemplateSelector : DataTemplateSelector
{
readonly DataTemplate view1, view2;
public MyTemplateSelector()
{
view1 = new DataTemplate(typeof(View1));
view2 = new DataTemplate(typeof(View2));
}
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
String s = item.ToString();
if(s == "1")
{
return view1;
}
return view2;
}
}
}
Tạo trang chính của bạn
Trang1.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"
xmlns:t="clr-namespace:overlayTest"
x:Class="overlayTest.Page1">
<ContentPage.Resources>
<ResourceDictionary>
<t:MyTemplateSelector x:Key="templateSelector"/>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<AbsoluteLayout>
<StackLayout AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
Padding="0"
Spacing="0">
<CarouselView ItemTemplate="{StaticResource templateSelector}"
IndicatorView="indicatorView">
<CarouselView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>1</x:String>
<x:String>2</x:String>
</x:Array>
</CarouselView.ItemsSource>
</CarouselView>
<IndicatorView x:Name="indicatorView">
<IndicatorView.IndicatorTemplate>
<DataTemplate>
<StackLayout HorizontalOptions="FillAndExpand">
<Frame Margin="10">
<Label/>
</Frame>
</StackLayout>
</DataTemplate>
</IndicatorView.IndicatorTemplate>
</IndicatorView>
</StackLayout>
<ContentView
IsVisible="True" VerticalOptions="Start"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Transparent">
<Frame CornerRadius="10"
Margin="20"
VerticalOptions="StartAndExpand"
HorizontalOptions="CenterAndExpand" InputTransparent="False">
<StackLayout Padding="0">
<Label
FontSize="Medium"
TextColor="Black"/>
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<Label Text="I am floating here"/>
<Switch IsToggled="True" />
</StackLayout>
<Button Text="Save"
BackgroundColor="Accent"/>
</StackLayout>
</Frame>
</ContentView>
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
Và trong đoạn mã đằng sau, chúng tôi đặt tên của các tab. Ở đây, hãy lưu ý rằng tôi đang giả sử một cây phần tử của a StackLayout-> Frame-> Label. Nếu bạn thay đổi IndicatorTemplate, bạn cũng sẽ phải sửa đổi phần này của mã!
Trang1.xaml.cs
using System.Linq;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace overlayTest
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
indicatorView.PropertyChanged += (s, a) =>
{
if (a.PropertyName == IndicatorView.HeightProperty.PropertyName)
{
var indicators = indicatorView.IndicatorLayout.Children.ToList();
int counter = 0;
foreach(var indicator in indicators)
{
var indicatorBaseStack = (StackLayout)indicator;
var indicatorFrame = (Frame)indicatorBaseStack.Children[0];
var indicatorFrameLabel = (Label)indicatorFrame.Content;
indicatorFrameLabel.Text = counter == 0 ? "View1" : "View2";
counter++;
}
}
};
}
}
}
Cuối cùng đặt Trang đó thành thuộc tính MainPage của Ứng dụng:
public App()
{
InitializeComponent();
MainPage = new Page1();
}
Kết quả cuối cùng trông như thế này:
Để giải quyết vấn đề này, bạn có thể đặt ToolbarItem của mỗi ContentPage (hoặc bạn có thể xác định một ContentPage cơ sở).
<ContentPage.ToolbarItems>
<ToolbarItem Text="Example Item"
IconImageSource="xxx.png"
Order="Secondary"
Clicked="{Binding xx}"
Priority="0" />
<ToolbarItem Text="Example Item"
IconImageSource="xxx.png"
Order="Secondary"
Priority="1" />
<ToolbarItem Text="Example Item"
IconImageSource="xxx.png"
Order="Secondary"
Priority="2" />
</ContentPage.ToolbarItems>
Tôi khuyên bạn nên tạo một BaseContentPagebao gồm một static FloatingButton. Điều này cho phép mọi trang kế thừa BaseContentPagevà sử dụng như nhau FloatingButton.
Mã
BaseContentPage
abstract class BaseContentPage : ContentPage
{
protected static Button Button { get; } = new Button { Text = $"This button was created at {DateTimeOffset.UtcNow}" }.Invoke(button => button.Clicked += HandleButtonClicked);
static async void HandleButtonClicked(object sender, EventArgs e) =>
await Application.Current.MainPage.DisplayAlert("Button Clicked", "This is the same button on both pages", "OK");
}
Nhãn trang mẫu
class LabelPage : BaseButtonPage
{
public LabelPage()
{
Title = "LabelPage";
Content = new StackLayout
{
Children =
{
new Label { Text = "Label Page" }.TextCenter().Center(),
Button
}
}
}
}
Trang nút mẫu
class ButtonPage : BaseButtonPage
{
public ButtonPage()
{
Title = "ButtonPage";
Content = Button;
}
}
Ứng dụng mẫu
public class App : Application
{
public App()
{
Device.SetFlags(new[] { "Markup_Experimental" });
MainPage = new TabbedPage
{
Children =
{
new ButtonPage(),
new LabelPage()
}
};
}
}
Ứng dụng mẫu
Đây là ứng dụng mẫu được sử dụng để tạo GIF đính kèm: https://github.com/brminnick/TabbedPageButton/