Android中的自定义控件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android中的自定义控件相关的知识,希望对你有一定的参考价值。

参考技术A         组合控件:即由原生控件拼装而成,不需要自己实现或者绘制具体的页面内容和效果,常用于标题栏TitlleView

        eg:

        继承控件的意思就是,我们并不需要自己重头去实现一个控件,只需要去继承一个现有的控件,然后在这个控件上增加一些新的功能,就可以形成一个自定义的控件了。这种自定义控件的特点就是不仅能够按照我们的需求加入相应的功能,还可以保留原生控件的所有功能。

熟悉view的绘制原理

1.measure用来测量View的宽和高。 

2.layout用来确定View在父容器中放置的位置。 

3.draw用来将view绘制在屏幕上

iPhone Interface Builder 中的自定义控件

【中文标题】iPhone Interface Builder 中的自定义控件【英文标题】:Custom Control in iPhone Interface Builder 【发布时间】:2011-07-06 22:14:56 【问题描述】:

这似乎是一个常见问题,但我没有看到它得到清晰或简洁的回答 - 因此我无法让它发挥作用。

我在 Interface Builder 中创建了一个 Widget.xib 文件。它包括:

View (UIView)
  ImageView (UIImageView)
  Button (UIButton)
  Label (UILabel)

我创建了 Widget.h 和 Widget.m,它们实现了派生自 UIView 的类 Widget。在 Interface Builder 中,Widget.xib 将其 File's Owner 设置为 Widget 类。

Widget.h 看起来像这样:

@interface IconView : UIView 
IBOutlet UIButton *widgetButton;
IBOutlet UILabel *widgetLabel;
IBOutlet UIView *widgetView;
IBOutlet UIImageView *widgetImage;


@property (nonatomic, retain) IBOutlet UIButton *widgetButton;
@property (nonatomic, retain) IBOutlet UILabel *widgetLabel;
@property (nonatomic, retain) IBOutlet UIView *widgetView;
@property (nonatomic, retain) IBOutlet UIImageView *widgetImage;

Widget.h 包括:

@synthesize widgetButton, widgetLabel, widgetView, widgetImage;

它的 dealloc 释放了这四个对象。在 Interface Builder 中,按钮、标签、视图和图像视图都连接到相应的 IBOutlets。

回到 Interface Builder,我从项目中打开了另一个 XIB。这是 Playfield.xib。这是一个更传统的视图,由 PlayfieldViewController.h 和 .m 支持。它包含:

View (UIView)
  ImageView (with a static graphic) (UIImageView)
  Button (UIButton)
  Widget
  Widget
  Widget

在 Playfield.h 中,我为按钮和三个小部件创建了 IBOutlets。

@interface LinkViewController : UIViewController 
IBOutlet UIButton *buttonBack;
IBOutlet Widget *widget0;
IBOutlet Widget *widget1;
IBOutlet Widget *widget2;


@property (nonatomic, retain) IBOutlet Widget *widget0;
@property (nonatomic, retain) IBOutlet Widget *widget1;
@property (nonatomic, retain) IBOutlet Widget *widget2;
- (IBAction)buttonBackClicked:(id)sender;

这些也是在 Playfield.h 中合成和发布的。在 Interface Builder 中,Playfield.xib 显示了三个放置小部件的空矩形,这是我所期望的。它们连接到 Playfield.h 中相应的 IBOutlets。

所以,在这一点上,我假设一切都准备好了。在 Playfield.m 的 viewDidLoad 中,我这样做:

self.widget0.label.text = @"喂我";

在我看来,它引用了 Playfield.h 中声明的 widget0 IBOutlet。它连接到 Playfield.xib 中的第一个 Widget 项。反过来,它在 Widget.xib 和 Widget.h 中有一个声明的标签 IBOutlet。 UILabel 有一个 Text 属性。所以它应该改变小部件内标签上的文本。

但事实并非如此。我做错了什么?

(我想强调一下,我并不是要制作一个 Interface Builder 插件。我知道这些很复杂。在 IB 中,我可以很好地将我的小部件操作为空矩形。我还要注意,我已经在 Widget.xib 中将小部件视图的背景颜色设置为白色。当我运行项目时,我可以清楚地看到运动场图形顶部的白色矩形,所以我知道小部件“在”那里。我只是可以似乎无法访问它们。)

【问题讨论】:

感谢您的建议...最终,我决定放弃这种方法。它在对象保留和内存方面造成了很多麻烦,而且由于小部件非常简单(它是一个 UILabel 和一个 UIImageView),以编程方式添加这些项目比为它们创建一个自定义类更容易。跨度> 【参考方案1】:

您在哪里调用了loadNibNamed:owner:options: 方法来从您的 Widget.XIB 加载您的 Widget 子视图?

此外,您确实将 Widget.XIB 文件中的视图连接到文件所有者(这是一个 Widget 对象),因此连接了 IBOutlets 并允许您访问视图……但是您是否将视图作为子视图添加到您的小部件?

当您尝试使用 self.widget0.label 访问它时,出口是否为零?检查self.widget0 是否不是nil(我想这没关系),但也检查self.widget0.label 是否也不是nil(我想这是真正的问题)。如果是,您可能忘记为每个小部件视图加载 Widget.xib。如果不是,则可能意味着您有标签,但它没有添加到视图层次结构中。

【讨论】:

呃,我没有。在 Playfield.xib 中,我转到 IB 工具箱中的 Classes 选项卡并手动将 Widget 类拖入。我确实将 Widget.xib 中的 UIView 连接到 File's Owner 中的 IBOutlet UIView ......但我没有做任何编程来添加子视图。看,我想我需要更多关于如何做到这一点的演练。这里的所有问答(以及我发现的其他任何地方)都是零散的,并没有涵盖整个过程。 旅游类被命名为 Widget 而你有一个 Widget.XIB 的事实是不够的。当您有 MyViewController.xib 时,您通常可以通过在检查器中设置 XIB 文件名在 IB 中使用此 XIB(因为 ViewControllers 将此类属性暴露给 IB),或者在通过代码创建 VC 时,使用 initWithNibNamed:bundle:它确实采用了 XIB 名称(并在需要时在内部使用它来执行loadNibNamed:owner:options:)。 [...] [...] 因此,对于您的小部件,您还需要(通过代码)告诉(通过代码)要加载哪个 XIB。 loadNibNamed:owner:options: 方法(将在 [NSBundle mainBundle] 上调用)将加载 XIB,从而实例化您在 XIB 中创建的视图,然后连接出口,包括连接到 XIB 的“文件所有者”的出口(其中是作为 owner: 参数传递的 Widget 对象)。调用此方法后,您的 IBOutlets 将指向通过加载 NIB 创建的实例,但您仍需要将主视图添加为 Widget 的子视图。 请注意,一旦您了解了所有这些是如何工作的,您就可以在 Widget 类的 initWithFrame:initWithCoder: 方法中移动代码;这样,Widget.XIB 的加载(以及将视图添加为小部件的子视图的工作)将在每次实例化新小部件时完成 - 通过显式使用 ìnitWithFrame:` 的代码,或从 XIB 创建时就像来自 Playfield.XIB 和 initWithCoder: 被调用。【参考方案2】:

您对 XIB 设置的描述没有提到 Widget 上的 label 插座实际上连接到 XIB 中的标签。检查一下,也许?听起来好像您已经设置了所有其他内容,尽管您不需要在实例变量上声明 IBOutlet 属性,只需声明属性即可。

【讨论】:

在 Widget.xib 中,UILabel 连接到 File's Owner(它是 Widget 类,UIView 的后代),连接到标签 IBOutlet。 好吧,那就这样吧。在尝试设置标签文本的行上设置断点,然后尝试po [self widget0]po [[self widget0] label] 等,并确保所有对象都已实际设置。【参考方案3】:

我经常错过的一个常见问题是在 IB 中将类类型设置为小部件。

【讨论】:

那么类和文件的所有者应该是Widget?

以上是关于Android中的自定义控件的主要内容,如果未能解决你的问题,请参考以下文章

Android中的自定义控件

我生成了一个换行的自定义Label控件,如何取得该行数啊??

Android 自定义控件

Android自定义控件

如何设计WinForm中DataGridView控件的自定义按钮列

一手遮天 Android