@@ -15,95 +15,128 @@ typedef enum {
1515} QMUIPopupContainerViewLayoutDirection;
1616
1717/* *
18- * 带箭头的小tips浮层,自带 imageView 和 textLabel,可展示简单的图文信息。<br/>
18+ * 带箭头的小tips浮层,自带 imageView 和 textLabel,可展示简单的图文信息。
19+ * QMUIPopupContainerView 支持以两种方式显示在界面上:
20+ * 1. 添加到某个 UIView 上(适合于 viewController 切换时浮层跟着一起切换的场景),这种场景只能手动隐藏浮层。
21+ * 2. 在 QMUIPopupContainerView 自带的 UIWindow 里显示(适合于用完就消失的场景,不要涉及界面切换),这种场景支持点击空白地方自动隐藏浮层。
1922 *
20- * 如果默认功能无法满足需求,请继承它重写一个子类。<br/>
21- * 继承要点:<br/>
22- * <ol>
23- * <li>所有subviews请加到contentView上,相对于contentView布局</li>
24- * <li>通过重写sizeThatFitsInContentView:,在里面返回当前subviews的大小,控件会根据这个大小来布局</li>
25- * </ol>
26- * 使用步骤:<br/>
27- * <ol>
28- * <li>使用init初始化</li>
29- * <li>将控件添加到某个View上(一定要先添加,再layout,因为layout里会使用superview的bounds进行计算)</li>
30- * <li>调用layoutWithReferenceItemRectInSuperview:将需要指向的目标的rect传进去,tipsView就会自动计算宽高和x/y,让箭头对准rect的中心点</li>
31- * <li>注意传进去的rect必须和tipsView处于同一个坐标系内,必要时记得转换坐标系</li>
32- * <li>如果需要显示/消失带有动画,则调用<i>showWithAnimated:</i>、<i>hideWithAnimated:</i>,记得show前先setHidden为YES。</li>
33- * </ol>
23+ * 使用步骤:
24+ * 1. 调用 init 方法初始化。
25+ * 2. 选择一种显示方式:
26+ * 2.1 如果要添加到某个 UIView 上,则先设置浮层 hidden = YES,然后调用 addSubview: 把浮层添加到目标 UIView 上。
27+ * 2.2 如果是轻量的场景用完即走,则 init 完浮层即可,无需设置 hidden,也无需调用 addSubview:。
28+ * 3. 在适当的时机(例如 layoutSubviews: 或 viewDidLayoutSubviews:)调用 layoutWithTargetView: 让浮层参考目标 view 布局,或者调用 layoutWithTargetRectInScreenCoordinate: 让浮层参考基于屏幕坐标系里的一个 rect 来布局。
29+ * 4. 调用 showWithAnimated: 或 showWithAnimated:completion: 显示浮层。
30+ * 5. 调用 hideWithAnimated: 或 hideWithAnimated:completion: 隐藏浮层。
31+ *
32+ * 如果默认功能无法满足需求,可继承它重写一个子类,继承要点:
33+ * 1. 初始化时要做的事情请放在 didInitialized 里。
34+ * 2. 所有 subviews 请加到 contentView 上。
35+ * 3. 通过重写 sizeThatFitsInContentView:,在里面返回当前 subviews 的大小,控件最终会被布局为这个大小。
36+ * 4. 在 layoutSubviews: 里,所有 subviews 请相对于 contentView 布局。
3437 */
3538
3639@interface QMUIPopupContainerView : UIControl {
3740 CAShapeLayer *_backgroundLayer;
3841 CGFloat _arrowMinX;
3942}
4043
41- @property (nonatomic ,assign ) BOOL debug;
44+ @property (nonatomic , assign ) BOOL debug;
45+
46+ // / 在浮层显示时,点击空白地方是否要自动隐藏浮层,仅在用方法 2 显示时有效。默认为 NO,也即需要代码手动调用才能隐藏。
47+ @property (nonatomic , assign ) BOOL automaticallyHidesWhenUserTap;
4248
4349// / 所有subview都应该添加到contentView上,默认contentView.userInteractionEnabled = NO,需要事件操作时自行打开
44- @property (nonatomic ,strong ,readonly ) UIView *contentView;
50+ @property (nonatomic , strong , readonly ) UIView *contentView;
4551
4652// / 预提供的UIImageView,默认为nil,调用到的时候才初始化
47- @property (nonatomic ,strong ,readonly ) UIImageView *imageView;
53+ @property (nonatomic , strong , readonly ) UIImageView *imageView;
4854
4955// / 预提供的UILabel,默认为nil,调用到的时候才初始化。默认支持多行。
50- @property (nonatomic ,strong ,readonly ) UILabel *textLabel;
56+ @property (nonatomic , strong , readonly ) UILabel *textLabel;
5157
5258// / 圆角矩形气泡内的padding(不包括三角箭头),默认是(8, 8, 8, 8)
53- @property (nonatomic ,assign ) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR;
59+ @property (nonatomic , assign ) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR;
5460
5561// / 调整imageView的位置,默认为UIEdgeInsetsZero。top/left正值表示往下/右方偏移,bottom/right仅在对应位置存在下一个子View时生效(例如只有同时存在imageView和textLabel时,imageEdgeInsets.right才会生效)。
56- @property (nonatomic ,assign ) UIEdgeInsets imageEdgeInsets UI_APPEARANCE_SELECTOR;
62+ @property (nonatomic , assign ) UIEdgeInsets imageEdgeInsets UI_APPEARANCE_SELECTOR;
5763
5864// / 调整textLabel的位置,默认为UIEdgeInsetsZero。top/left/bottom/right的作用同<i>imageEdgeInsets</i>
59- @property (nonatomic ,assign ) UIEdgeInsets textEdgeInsets UI_APPEARANCE_SELECTOR;
65+ @property (nonatomic , assign ) UIEdgeInsets textEdgeInsets UI_APPEARANCE_SELECTOR;
6066
61- // / 三角箭头的大小
62- @property (nonatomic ,assign ) CGSize arrowSize UI_APPEARANCE_SELECTOR;
67+ // / 三角箭头的大小,默认为 CGSizeMake(18, 9)
68+ @property (nonatomic , assign ) CGSize arrowSize UI_APPEARANCE_SELECTOR;
6369
6470// / 最大宽度(指整个控件的宽度,而不是contentView部分),默认为CGFLOAT_MAX
65- @property (nonatomic ,assign ) CGFloat maximumWidth UI_APPEARANCE_SELECTOR;
71+ @property (nonatomic , assign ) CGFloat maximumWidth UI_APPEARANCE_SELECTOR;
6672
6773// / 最小宽度(指整个控件的宽度,而不是contentView部分),默认为0
68- @property (nonatomic ,assign ) CGFloat minimumWidth UI_APPEARANCE_SELECTOR;
74+ @property (nonatomic , assign ) CGFloat minimumWidth UI_APPEARANCE_SELECTOR;
6975
7076// / 最大高度(指整个控件的高度,而不是contentView部分),默认为CGFLOAT_MAX
71- @property (nonatomic ,assign ) CGFloat maximumHeight UI_APPEARANCE_SELECTOR;
77+ @property (nonatomic , assign ) CGFloat maximumHeight UI_APPEARANCE_SELECTOR;
7278
7379// / 最小高度(指整个控件的高度,而不是contentView部分),默认为0
74- @property (nonatomic ,assign ) CGFloat minimumHeight UI_APPEARANCE_SELECTOR;
80+ @property (nonatomic , assign ) CGFloat minimumHeight UI_APPEARANCE_SELECTOR;
7581
7682// / 计算布局时期望的默认位置,默认为QMUIPopupContainerViewLayoutDirectionAbove,也即在目标的上方
77- @property (nonatomic ,assign ) QMUIPopupContainerViewLayoutDirection preferLayoutDirection UI_APPEARANCE_SELECTOR;
83+ @property (nonatomic , assign ) QMUIPopupContainerViewLayoutDirection preferLayoutDirection UI_APPEARANCE_SELECTOR;
7884
7985// / 最终的布局方向(preferLayoutDirection只是期望的方向,但有可能那个方向已经没有剩余空间可摆放控件了,所以会自动变换)
80- @property (nonatomic ,assign ,readonly ) QMUIPopupContainerViewLayoutDirection currentLayoutDirection;
86+ @property (nonatomic , assign , readonly ) QMUIPopupContainerViewLayoutDirection currentLayoutDirection;
8187
8288// / 最终布局时箭头距离目标边缘的距离,默认为5
83- @property (nonatomic ,assign ) CGFloat distanceBetweenTargetRect UI_APPEARANCE_SELECTOR;
89+ @property (nonatomic , assign ) CGFloat distanceBetweenTargetRect UI_APPEARANCE_SELECTOR;
8490
8591// / 最终布局时与父节点的边缘的临界点,默认为(10, 10, 10, 10)
86- @property (nonatomic ,assign ) UIEdgeInsets safetyMarginsOfSuperview UI_APPEARANCE_SELECTOR;
92+ @property (nonatomic , assign ) UIEdgeInsets safetyMarginsOfSuperview UI_APPEARANCE_SELECTOR;
8793
88- @property (nonatomic ,strong ) UIColor *backgroundColor UI_APPEARANCE_SELECTOR;
89- @property (nonatomic ,strong ) UIColor *highlightedBackgroundColor UI_APPEARANCE_SELECTOR;
90- @property (nonatomic ,strong ) UIColor *shadowColor UI_APPEARANCE_SELECTOR;
91- @property (nonatomic ,strong ) UIColor *borderColor UI_APPEARANCE_SELECTOR;
92- @property (nonatomic ,assign ) CGFloat borderWidth UI_APPEARANCE_SELECTOR;
93- @property (nonatomic ,assign ) CGFloat cornerRadius UI_APPEARANCE_SELECTOR;
94+ @property (nonatomic , strong ) UIColor *backgroundColor UI_APPEARANCE_SELECTOR;
95+ @property (nonatomic , strong ) UIColor *highlightedBackgroundColor UI_APPEARANCE_SELECTOR;
9496
95- // / 子类重写,告诉父类subviews的合适大小
96- - (CGSize)sizeThatFitsInContentView : (CGSize)size ;
97+ // / 当使用方法 2 显示时,可修改背景遮罩的颜色,默认为 UIColorClear。
98+ @property (nonatomic , strong ) UIColor *maskViewBackgroundColor UI_APPEARANCE_SELECTOR;
99+ @property (nonatomic , strong ) UIColor *shadowColor UI_APPEARANCE_SELECTOR;
100+ @property (nonatomic , strong ) UIColor *borderColor UI_APPEARANCE_SELECTOR;
101+ @property (nonatomic , assign ) CGFloat borderWidth UI_APPEARANCE_SELECTOR;
102+ @property (nonatomic , assign ) CGFloat cornerRadius UI_APPEARANCE_SELECTOR;
103+
104+ /* *
105+ * 相对于某个 view 布局(布局后箭头不一定会水平居中)
106+ * @param targetView 注意如果这个 targetView 自身的布局发生变化,需要重新调用 layoutWithTargetView:,否则浮层的布局不会自动更新。
107+ */
108+ - (void )layoutWithTargetView : (UIView *)targetView ;
97109
98110/* *
99- * 利用参考的目标itemRect,计算出tips合适的布局位置(箭头并非绝对居中 )
100- * @param itemRect 参考对齐的UIBarButtonItem的rect(rect是相对于toolbar的坐标系而言)
111+ * 相对于给定的 itemRect 布局(布局后箭头不一定会水平居中 )
112+ * @param targetRect 注意这个 rect 应该是处于屏幕坐标系里的 rect,所以请自行做坐标系转换。
101113 */
102- - (void )layoutWithReferenceItemRectInSuperview : (CGRect)itemRect ;
114+ - (void )layoutWithTargetRectInScreenCoordinate : (CGRect)targetRect ;
103115
104116- (void )showWithAnimated : (BOOL )animated ;
105117- (void )showWithAnimated : (BOOL )animated completion : (void (^)(BOOL finished))completion ;
106118- (void )hideWithAnimated : (BOOL )animated ;
107119- (void )hideWithAnimated : (BOOL )animated completion : (void (^)(BOOL finished))completion ;
108120- (BOOL )isShowing ;
121+
122+ /* *
123+ * 即将隐藏时的回调
124+ * @argv hidesByUserTap 用于区分此次隐藏是否因为用户手动点击空白区域导致浮层被隐藏
125+ */
126+ @property (nonatomic , copy ) void (^willHideBlock)(BOOL hidesByUserTap);
127+
128+ /* *
129+ * 已经隐藏后的回调
130+ * @argv hidesByUserTap 用于区分此次隐藏是否因为用户手动点击空白区域导致浮层被隐藏
131+ */
132+ @property (nonatomic , copy ) void (^didHideBlock)(BOOL hidesByUserTap);
133+ @end
134+
135+ @interface QMUIPopupContainerView (UISubclassingHooks)
136+
137+ // / 子类重写,在初始化时做一些操作
138+ - (void )didInitialized NS_REQUIRES_SUPER;
139+
140+ // / 子类重写,告诉父类subviews的合适大小
141+ - (CGSize)sizeThatFitsInContentView : (CGSize)size ;
109142@end
0 commit comments