zoukankan      html  css  js  c++  java
  • 抗拒“组合”的UITabBarController

    转自http://blog.zhaojie.me/2010/12/iphone-composition-resistant-uitabbarcontroller.html

    最近在写一个iPhone应用程序,基于MonoTouch,所以在开发方面的问题,基本都是在界面元素的搭建上。这个程序界面相对比较复杂,于是我根据自己的想法来进行组合,结果发现UITabBarController不能放入其他的视图内,而只能直接放在Window上(或Window里的UINavigationController里),否则就会出现界面向下偏移的情况。现在虽然有workaround,但是对于UITabBarController抗拒组合的情况,只能深表叹息了。

    先来看一下这个界面的最终效果吧:

    这里再简单描述一下效果。打开程序以后看到的是一个标准的带有两个标签界面,目前选中第一个,界面上有一个按钮。点击按钮,整个界面(连同下方的标签栏)都会切换至新界面,并可以退回。在第二个标签内则有另一个按钮,点击则会切换至新一级,注意此时下方的标签栏会保持不变。不过这个程序最关键的一点在于,标签栏上放浮动着一个文字区域,它独立于标签栏中的各个视图。

    显然这里会需要一个UINavigationController作为根元素,其中放入一个UITabBarController和文字区域。在UITabBarController的第二个标签中,则放入另一个UINavigationController。由于“根导航”在切换时,UITabBarController和文字区域要同时显示和消失,于是我很自然地打算将UITabBarController和一个UILabel组合成一个自定义的UIViewController。这样的界面本该很容易,因为控件的组合是编写界面的常用手段。

    于是我新建了一个CustomController.xib文件,放入了一个UITabBarController和一个UILabel,并补充了一些操作逻辑(显示拖动时的坐标)。这些文字显示的逻辑本就属于CustomController,在实际应用中它也会和UITabBarController内部的视图产生交互,因此我把这些逻辑都隐藏在CustomController中。我认为这个组合方式十分合理。不过,在界面上显示MyTabBarController后则出现了奇怪的状况:

    当然,上面这个只是我直接把一个UITabBarController的View放入Window里的UIView控件之后出现的情况:向下整体偏移了。这个偏移量是最上方状态栏的高度,这让我很摸不着头脑。经过了一整下午的纠结试验,我的结论是:似乎UITabBarController抗拒组合。说地具体一些:UITabBarController会把视图中的UITabBar控件定位在屏幕下方,但是在计算位置的时候,它不会关注自己父容器,而是茫然地认为自己一定是在根窗体上,于是会把顶部状态栏的高度考虑进去。于是,如果它的父视图不是从整个界面(包括状态栏)的顶部算起,UITabBar的位置便会出现偏移了。

    有资深iOS开发者告诉我,我把UITabBarController组合到另一个UIViewController里不是UITabBarController的标准用法,如果我要组合,就应该使用UITabBar控件自己搭配,自己处理切换逻辑。不过我始终认为UI元素(不单指控件)应该意识到自己会参与组合。例如UITableViewController,UIImagePickerController,组合使用是它们的天然职责。在我看来,如其他(我用过的)UI库一般,只要为每个控件设好Dock(类似iOS里的Auto Resizing),组合起来应该是随意自然的。

    既然不能组合,那么扩展的方法似乎只有继承了——这样我便不能使用Interface Builder绘制界面,麻烦了不少。这里我创建一个MyTabBarController继承UITabBarController,并补充一些逻辑:

    public class MyTabBarController : UITabBarController
    {
        /* Constructors */
    
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
    
            this.m_label = new UILabel()
            {
                Text = "Hello MonoTouch",
                TextAlignment = UITextAlignment.Center,
                Frame = new System.Drawing.RectangleF(0, 400, 320, 20),
                AutoresizingMask = UIViewAutoresizing.FlexibleTopMargin
            };
    
            this.View.AddSubview(this.m_label);
            this.View.BringSubviewToFront(this.m_label);
        }
    
        private UILabel m_label;
    
        public override void TouchesMoved(NSSet touches, UIEvent evt)
        {
            base.TouchesMoved(touches, evt);
    
            var touch = (UITouch)touches.AnyObject;
            var location = touch.LocationInView(this.View);
            this.m_label.Text = location.ToString();
        }
    }

    这样,就差不多了,剩下的就是简单地嵌套关系,以及在切换到第二个Tab的时候隐藏“根导航”的导航栏。

    如果您有更好的做法,请务必告诉我。

  • 相关阅读:
    [原]终于做了一个登陆页
    JDK 1.7环境变量的配置
    值类型和引用类型讲解,本人在大学时候的笔记,写给新手
    CDays2 习题一 (改进函数)及相关内容解析。Python 基础教程
    Winedt 7.0 Build: 20120321 永久试用方法 Winedt 7.0 破解
    Arduino 笔记。开篇
    What we find changes who we become.
    Python 中的POST/GET包构建以及随机字符串的生成。Python 初级应用
    CDays–2 完成核心功能 CMD模块 Python基础教程 cmd cli
    Python HDB3 AMI 编码与解码
  • 原文地址:https://www.cnblogs.com/linyawen/p/2546661.html
Copyright © 2011-2022 走看看