在Xamarin中,Xamarin布局渲染器修改默认布局,修改默认布局的渲染器可以通过自定义渲染器来实现。自定义渲染器允许您覆盖默认控件的渲染行为,从而实现您需要的布局和外观。
源码地址:https://github.com/l2999019/DemoApp
以下是一个示例,展示如何通过自定义渲染器修改ContentPage
的默认布局。这个示例将演示如何在Xamarin.Forms中创建一个自定义渲染器来修改ContentPage
的默认布局。
创建自定义页面
首先,创建一个自定义的ContentPage
:
using Xamarin.Forms; namespace YourNamespace { public class CustomContentPage : ContentPage { } }
Xamarin布局渲染器修改默认布局
创建自定义渲染器
接下来,在您的平台项目(例如,Android和iOS项目)中创建一个自定义渲染器。这里以Android为例:
Android 自定义渲染器
在您的Android项目中创建一个新的渲染器类:
using Xamarin.Forms; using Xamarin.Forms.Platform.Android; using YourNamespace; using YourNamespace.Droid; using Android.Content; [assembly: ExportRenderer(typeof(CustomContentPage), typeof(CustomContentPageRenderer))] namespace YourNamespace.Droid { public class CustomContentPageRenderer : PageRenderer { public CustomContentPageRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<Page> e) { base.OnElementChanged(e); if (e.OldElement != null || Element == null) return; // 在这里可以自定义布局 var layout = new Android.Widget.LinearLayout(Context); layout.Orientation = Android.Widget.Orientation.Vertical; // 添加自定义控件 var customTextView = new Android.Widget.TextView(Context) { Text = "This is a custom TextView", TextSize = 20 }; layout.AddView(customTextView); AddView(layout); } } }
Xamarin布局渲染器修改默认布局
iOS 自定义渲染器
在您的iOS项目中创建一个新的渲染器类:
using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; using YourNamespace; using YourNamespace.iOS; using UIKit; [assembly: ExportRenderer(typeof(CustomContentPage), typeof(CustomContentPageRenderer))] namespace YourNamespace.iOS { public class CustomContentPageRenderer : PageRenderer { public override void ViewDidLoad() { base.ViewDidLoad(); // 在这里可以自定义布局 var customLabel = new UILabel { Text = "This is a custom UILabel", TextColor = UIColor.Black, Font = UIFont.SystemFontOfSize(20) }; View.AddSubview(customLabel); } } }
Xamarin布局渲染器修改默认布局
使用自定义页面
最后,在您的Xamarin.Forms项目中使用自定义页面:
using Xamarin.Forms; namespace YourNamespace { public class App : Application { public App() { MainPage = new CustomContentPage { Content = new StackLayout { Children = { new Label { Text = "Welcome to Xamarin.Forms!" } } } }; } } }
通过这些步骤,您可以在Xamarin.Forms中创建一个自定义渲染器,修改默认布局并添加自定义控件。根据需要,您可以在自定义渲染器中进一步自定义布局和控件。
Xamarin布局渲染器修改默认布局
本篇..基本可以算是Xamarin在应用开发过程中的核心了..真的很很很重要..
想学习的..想用的..建议仔细阅读..嗯..打酱油的 ..快速滑倒下面点个推荐 – – 哈哈哈…
也只讲一个,关于Xamarin.Forms针对各个平台如何进行可定制化的布局操作.
也就是针对某个平台的细颗粒化操作.
废话不多说,我们直接开始.
嗯..今天我会拿一个项目中的例子出来讲.
说说原因吧,因为在谷歌的安卓开发建议中,是建议类似tab切换操作,是放在顶部的.
然而苹果则不然,他建议放在底部..这样就造成了APP上各个平台对于TabbedPage视图的渲染差别
如图:
虽然在墙外..大多数的APP都遵循了这个规则,然而在我们特色的社会主义新中国..几乎所有的APP都是仿苹果的建议 将Tab标签放到了下面..
嗯,入乡随俗,我们今天就来把这个tab,在安卓中给移到下面.
效果如图吧:
既然要移动到下面,那么我们肯定需要重写相关的内容,我们可以找到开源的Xamarin控件BottomNavigationBar
做过安卓的应该都知道,这个是一个安卓中比较流行的控件,嗯..直接被移植到了Xamarin中
我们在安卓的项目下,通过nuget添加这个包如下:
然后我们在可移植的项目中,照常编写我们的TabbedPage页面如下:
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Xamarin.FormsDemo_CHN.Views;assembly=Xamarin.FormsDemo_CHN" x:Class="Xamarin.FormsDemo_CHN.Views.MainPage" BarBackgroundColor="#7EC0EE" BarTextColor="White"> <local:ItemsPage Icon="ic_Messaget"/> <local:AboutPage Icon="ic_Info"/> <local:BaiDuMapPage Icon="ic_Star" /> </TabbedPage>
我们给这个页面取名叫MainPage,后台代码如下:
[XamlCompilation(XamlCompilationOptions.Compile)] public partial class MainPage : TabbedPage { public MainPage() { InitializeComponent(); } protected override void OnCurrentPageChanged() { base.OnCurrentPageChanged(); Title = CurrentPage?.Title; } }
啥也不用干,就重写一下页面变更事件,改写一下title而已,很常见的代码.
然后我们回到安卓的项目下.
添加一个类,取名为MainPageRenderer,表示是重新渲染MainPage的
编写渲染特性如下:
[assembly: ExportRenderer(typeof(MainPage), typeof(MainPageRenderer))] namespace Xamarin.FormsDemo_CHN.Droid { class MainPageRenderer : VisualElementRenderer<MainPage>, IOnTabClickListener
注意,我们这里继承了IOnTabClickListener,这个就是第三方的BottomNavigationBar的事件了,待会我们会用到.
在注意:我们这里因为是重写布局,所以要继承VisualElementRenderer
接下来我们直接上MainPageRenderer 的完整代码,因为内容较多..涉及的方面也比较多.嗯..包含一些安卓方面的重绘之类的.
所以就不一一讲解了.大部分都已经写在了注释当中.请仔细看
class MainPageRenderer : VisualElementRenderer<MainPage>, IOnTabClickListener { private BottomBar _bottomBar; private Page _currentPage; private int _lastSelectedTabIndex = -1; public MainPageRenderer() { // Required to say packager to not to add child pages automatically AutoPackage = false; } /// <summary> /// 选中后,加载新的页面内容 /// </summary> /// <param name="position"></param> public void OnTabSelected(int position) { LoadPageContent(position); } public void OnTabReSelected(int position) { } protected override void OnElementChanged(ElementChangedEventArgs<MainPage> e) { base.OnElementChanged(e); if (e.OldElement != null) { ClearElement(e.OldElement); } if (e.NewElement != null) { InitializeElement(e.NewElement); } } protected override void Dispose(bool disposing) { if (disposing) { ClearElement(Element); } base.Dispose(disposing); } /// <summary> /// 重写布局的方法 /// </summary> /// <param name="changed"></param> /// <param name="l"></param> /// <param name="t"></param> /// <param name="r"></param> /// <param name="b"></param> protected override void OnLayout(bool changed, int l, int t, int r, int b) { if (Element == null) { return; } int width = r - l; int height = b - t; _bottomBar.Measure( MeasureSpec.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); //这里需要重新测量位置和尺寸,为了重新布置tab菜单的位置 _bottomBar.Measure( MeasureSpec.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(_bottomBar.ItemContainer.MeasuredHeight, MeasureSpecMode.Exactly)); int barHeight = _bottomBar.ItemContainer.MeasuredHeight; _bottomBar.Layout(0, b - barHeight, width, b); float density = Resources.DisplayMetrics.Density; double contentWidthConstraint = width / density; double contentHeightConstraint = (height - barHeight) / density; if (_currentPage != null) { var renderer = Platform.GetRenderer(_currentPage); renderer.Element.Measure(contentWidthConstraint, contentHeightConstraint); renderer.Element.Layout(new Rectangle(0, 0, contentWidthConstraint, contentHeightConstraint)); renderer.UpdateLayout(); } } /// <summary> /// 初始化方法 /// </summary> /// <param name="element"></param> private void InitializeElement(MainPage element) { PopulateChildren(element); } /// <summary> /// 生成新的底部控件 /// </summary> /// <param name="element"></param> private void PopulateChildren(MainPage element) { //我们需要删除原有的底部控件,然后添加新的 _bottomBar?.RemoveFromParent(); _bottomBar = CreateBottomBar(element); AddView(_bottomBar); LoadPageContent(0); } /// <summary> /// 清除旧的底部控件 /// </summary> /// <param name="element"></param> private void ClearElement(MainPage element) { if (_currentPage != null) { IVisualElementRenderer renderer = Platform.GetRenderer(_currentPage); if (renderer != null) { renderer.ViewGroup.RemoveFromParent(); renderer.ViewGroup.Dispose(); renderer.Dispose(); _currentPage = null; } if (_bottomBar != null) { _bottomBar.RemoveFromParent(); _bottomBar.Dispose(); _bottomBar = null; } } } /// <summary> /// 创建新的底部控件 /// </summary> /// <param name="element"></param> /// <returns></returns> private BottomBar CreateBottomBar(MainPage element) { var bar = new BottomBar(Context); // TODO: Configure the bottom bar here according to your needs bar.SetOnTabClickListener(this); bar.UseFixedMode(); PopulateBottomBarItems(bar, element.Children); var barcolor = element.BarBackgroundColor; // Color a = new Color(Convert.ToByte(barcolor.), Convert.ToByte(barcolor.G), Convert.ToByte(barcolor.B), Convert.ToByte(barcolor.A)); bar.ItemContainer.SetBackgroundColor(barcolor.ToAndroid()); bar.SetActiveTabColor(Color.White); //bar.ItemContainer. //bar.ItemContainer.SetBackgroundColor(Color.Red); return bar; } /// <summary> /// 查询原来底部的菜单,并添加到新的控件 /// </summary> /// <param name="bar"></param> /// <param name="pages"></param> private void PopulateBottomBarItems(BottomBar bar, IEnumerable<Page> pages) { var barItems = pages.Select(x => new BottomBarTab(Context.Resources.GetDrawable(x.Icon), x.Title)); bar.SetItems(barItems.ToArray()); } /// <summary> /// 通过选择的下标加载Page /// </summary> /// <param name="position"></param> private void LoadPageContent(int position) { ShowPage(position); } /// <summary> /// 显示Page的方法 /// </summary> /// <param name="position"></param> private void ShowPage(int position) { if (position != _lastSelectedTabIndex) { Element.CurrentPage = Element.Children[position]; if (Element.CurrentPage != null) { LoadPageContent(Element.CurrentPage); } } _lastSelectedTabIndex = position; } /// <summary> /// 加载方法 /// </summary> /// <param name="page"></param> private void LoadPageContent(Page page) { UnloadCurrentPage(); _currentPage = page; LoadCurrentPage(); Element.CurrentPage = _currentPage; } /// <summary> /// 加载当前Page /// </summary> private void LoadCurrentPage() { var renderer = Platform.GetRenderer(_currentPage); if (renderer == null) { renderer = Platform.CreateRenderer(_currentPage); Platform.SetRenderer(_currentPage, renderer); } else { var basePage = _currentPage as BaseContentPage; basePage?.SendAppearing(); } AddView(renderer.ViewGroup); renderer.ViewGroup.Visibility = ViewStates.Visible; } /// <summary> /// 释放上一个Page /// </summary> private void UnloadCurrentPage() { if (_currentPage != null) { var basePage = _currentPage as BaseContentPage; basePage?.SendDisappearing(); var renderer = Platform.GetRenderer(_currentPage); if (renderer != null) { renderer.ViewGroup.Visibility = ViewStates.Invisible; RemoveView(renderer.ViewGroup); } } } }
Xamarin布局渲染器修改默认布局
这样,我们就完成了整个tab菜单的替换工作.当然各位还可以根据需要来直接调用BottomNavigationBar的一些动画效果.其实也是很不错的.
本篇就到此结束了.
作者:顾振印 出处:http://www.cnblogs.com/GuZhenYin/
【江湖人士】(jhrs.com)原创文章,作者:江小编,如若转载,请注明出处:https://jhrs.com/2017/850.html
扫码加入电报群,让你获得国外网赚一手信息。
文章标题:Xamarin布局渲染器修改默认布局