博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#使用Xamarin开发可移植移动应用进阶篇(7.使用布局渲染器,修改默认布局),附源码...
阅读量:7028 次
发布时间:2019-06-28

本文共 8999 字,大约阅读时间需要 29 分钟。

前言

系列目录

源码地址:

可以Star一下,随意 - -

说点什么..

本篇..基本可以算是Xamarin在应用开发过程中的核心了..真的很很很重要..

想学习的..想用的..建议仔细阅读..嗯..打酱油的 ..快速滑倒下面点个推荐 - - 哈哈哈...

今天的学习内容?

也只讲一个,关于Xamarin.Forms针对各个平台如何进行可定制化的布局操作.

也就是针对某个平台的细颗粒化操作.

废话不多说,我们直接开始.

 

正文

嗯..今天我会拿一个项目中的例子出来讲.

说说原因吧,因为在谷歌的安卓开发建议中,是建议类似tab切换操作,是放在顶部的.

然而苹果则不然,他建议放在底部..这样就造成了APP上各个平台对于TabbedPage视图的渲染差别

如图:

虽然在墙外..大多数的APP都遵循了这个规则,然而在我们特色的社会主义新中国..几乎所有的APP都是仿苹果的建议 将Tab标签放到了下面..

嗯,入乡随俗,我们今天就来把这个tab,在安卓中给移到下面.

效果如图吧:

 

既然要移动到下面,那么我们肯定需要重写相关的内容,我们可以找到开源的Xamarin控件BottomNavigationBar

做过安卓的应该都知道,这个是一个安卓中比较流行的控件,嗯..直接被移植到了Xamarin中

我们在安卓的项目下,通过nuget添加这个包如下:

然后我们在可移植的项目中,照常编写我们的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
, IOnTabClickListener

注意,我们这里继承了IOnTabClickListener,这个就是第三方的BottomNavigationBar的事件了,待会我们会用到.

在注意:我们这里因为是重写布局,所以要继承VisualElementRenderer

接下来我们直接上MainPageRenderer 的完整代码,因为内容较多..涉及的方面也比较多.嗯..包含一些安卓方面的重绘之类的.

所以就不一一讲解了.大部分都已经写在了注释当中.请仔细看

class MainPageRenderer : VisualElementRenderer
, 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; } ///
/// 选中后,加载新的页面内容 /// ///
public void OnTabSelected(int position) { LoadPageContent(position); } public void OnTabReSelected(int position) { } protected override void OnElementChanged(ElementChangedEventArgs
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); } ///
/// 重写布局的方法 /// ///
///
///
///
///
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(); } } ///
/// 初始化方法 /// ///
private void InitializeElement(MainPage element) { PopulateChildren(element); } ///
/// 生成新的底部控件 /// ///
private void PopulateChildren(MainPage element) { //我们需要删除原有的底部控件,然后添加新的 _bottomBar?.RemoveFromParent(); _bottomBar = CreateBottomBar(element); AddView(_bottomBar); LoadPageContent(0); } ///
/// 清除旧的底部控件 /// ///
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; } } } ///
/// 创建新的底部控件 /// ///
///
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; } ///
/// 查询原来底部的菜单,并添加到新的控件 /// ///
///
private void PopulateBottomBarItems(BottomBar bar, IEnumerable
pages) { var barItems = pages.Select(x => new BottomBarTab(Context.Resources.GetDrawable(x.Icon), x.Title)); bar.SetItems(barItems.ToArray()); } ///
/// 通过选择的下标加载Page /// ///
private void LoadPageContent(int position) { ShowPage(position); } ///
/// 显示Page的方法 /// ///
private void ShowPage(int position) { if (position != _lastSelectedTabIndex) { Element.CurrentPage = Element.Children[position]; if (Element.CurrentPage != null) { LoadPageContent(Element.CurrentPage); } } _lastSelectedTabIndex = position; } ///
/// 加载方法 /// ///
private void LoadPageContent(Page page) { UnloadCurrentPage(); _currentPage = page; LoadCurrentPage(); Element.CurrentPage = _currentPage; } ///
/// 加载当前Page /// 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; } ///
/// 释放上一个Page /// 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); } } } }

 

这样,我们就完成了整个tab菜单的替换工作.当然各位还可以根据需要来直接调用BottomNavigationBar的一些动画效果.其实也是很不错的.

本篇就到此结束了.

 

转载于:https://www.cnblogs.com/GuZhenYin/p/7447336.html

你可能感兴趣的文章
POJ NOI MATH-7653 地球人口承载力估计
查看>>
iOS UI高级之网络编程(HTTP协议)
查看>>
使用cocoaPods import导入时没有提示的解决办法
查看>>
iOS数据持久化存储之归档NSKeyedArchiver
查看>>
JavaScript面向对象
查看>>
Intellij修改模板代码
查看>>
2.页面布局示例笔记
查看>>
一些老游戏CPU 100%占用的解决方法
查看>>
f5基本介绍
查看>>
博前语
查看>>
Java SE核心之一:常用类,包装类,其他基本数据类型包装类。
查看>>
郑捷《机器学习算法原理与编程实践》学习笔记(第二章 中文文本分类(一))...
查看>>
python (ploit)
查看>>
Android 用achartengine 画折线图怎么显示不正确
查看>>
程序简单的测试与升级(暨实践第一次作业)
查看>>
信号处理
查看>>
【100题】第五十九题 用C++编写不能被继承的类
查看>>
轻描淡写
查看>>
mysql基本操作
查看>>
39.CSS3弹性伸缩布局【下】
查看>>