Classes

The following classes are available globally.

  • 这个控件是为了方便地实现那种类似设置界面的列表(每个 cell 的样式、内容、操作控件均不太一样,每个 cell 之间不复用),使用方式:

    1. 创建一个带 UITableView 的 viewController。
    2. 通过 init 或 initWithCellDataSections: 创建一个 dataSource。若通过 init 方法初始化,则请在 tableView 渲染前(viewDidLoad 或更早)手动设置一个 cellDataSections 数组。
    3. 将第 2 步里的 dataSource 赋值给 tableView.qmui_staticCellDataSource 即可完成一般情况下的界面展示。
    4. 若需要重写某些 UITableViewDataSource、UITableViewDelegate 方法,则在 viewController 里直接实现该方法,并在方法里调用 QMUIStaticTableViewCellDataSource (Manual) 提供的同名方法即可,具体可参考 QMUI Demo。
    See more

    Declaration

    Objective-C

    @interface QMUIStaticTableViewCellDataSource : NSObject

    Swift

    class QMUIStaticTableViewCellDataSource : NSObject
  • 一个 cellData 对象用于存储 static tableView(例如设置界面那种列表) 列表里的一行 cell 的基本信息,包括这个 cell 的 class、text、detailText、accessoryView 等。

    See

    QMUIStaticTableViewCellDataSource
    See more

    Declaration

    Objective-C

    @interface QMUIStaticTableViewCellData : NSObject

    Swift

    class QMUIStaticTableViewCellData : NSObject
  • QMUIToastView是一个用来显示toast的控件,其主要结构包括:backgroundViewcontentView,这两个view都是通过外部赋值获取,默认使用QMUIToastBackgroundViewQMUIToastContentView

    拓展性:QMUIToastBackgroundViewQMUIToastContentView是QMUI提供的默认的view,这两个view都可以通过appearance来修改样式,如果这两个view满足不了需求,那么也可以通过新建自定义的view来代替这两个view。另外,QMUI也提供了默认的toastAnimator来实现ToastView的显示和隐藏动画,如果需要重新定义一套动画,可以继承QMUIToastAnimator并且实现QMUIToastAnimatorDelegate中的协议就可以自定义自己的一套动画。

    样式自定义:建议通过 tintColor 统一修改整个 toastView 的内容样式。当然你也可以单独修改 contentView.tintColor。默认情况下 QMUIToastView.tintColor = UIColorWhite。

    建议使用QMUIToastView的时候,再封装一层,具体可以参考QMUITips这个类。

    See

    QMUIToastBackgroundView

    See

    QMUIToastContentView

    See

    QMUIToastAnimator

    See

    QMUITips
    See more

    Declaration

    Objective-C

    @interface QMUIToastView : UIView

    Swift

    class QMUIToastView : UIView
  • QMUIToastView默认使用的contentView。其结构是:customView->textLabel->detailTextLabel等三个view依次往下排列。其中customView可以赋值任意的UIView或者自定义的view。 注意,customView 会响应 tintColor 的变化。而 textLabel/detailTextLabel 在没设置颜色到 attributes 里的情况下,也会跟随 tintColor 变化,设置了 attributes 的颜色则优先使用 attributes 里的颜色。

    @TODO: 增加多种类型的progressView的支持。

    See more

    Declaration

    Objective-C

    @interface QMUIToastContentView : UIView

    Swift

    class QMUIToastContentView : UIView
  • QMUIToastAnimator可以让你通过实现一些协议来自定义ToastView显示和隐藏的动画。你可以继承QMUIToastAnimator,然后实现QMUIToastAnimatorDelegate中的方法,即可实现自定义的动画。QMUIToastAnimator默认也提供了几种type的动画:1、QMUIToastAnimationTypeFade;2、QMUIToastAnimationTypeZoom;3、QMUIToastAnimationTypeSlide;

    See more

    Declaration

    Objective-C

    @interface QMUIToastAnimator : NSObject <QMUIToastAnimatorDelegate>

    Swift

    class QMUIToastAnimator : NSObject, QMUIToastAnimatorDelegate
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUIToastBackgroundView : UIView
    
    /**
     * 是否需要磨砂,默认NO。仅支持iOS8及以上版本。可以通过修改`styleColor`来控制磨砂的效果。
     */
    @property(nonatomic, assign) BOOL shouldBlurBackgroundView;
    
    @property(nullable, nonatomic, strong, readonly) QMUIVisualEffectView *effectView;
    
    /**
     * 如果不设置磨砂,则styleColor直接作为`QMUIToastBackgroundView`的backgroundColor;如果需要磨砂,则会新增加一个`UIVisualEffectView`放在`QMUIToastBackgroundView`上面。
     */
    @property(nullable, nonatomic, strong) UIColor *styleColor UI_APPEARANCE_SELECTOR;
    
    /**
     * 设置圆角。
     */
    @property(nonatomic, assign) CGFloat cornerRadius UI_APPEARANCE_SELECTOR;
    
    @end

    Swift

    class QMUIToastBackgroundView : UIView
  • QMUIAlertController的按钮,初始化完通过QMUIAlertControlleraddAction:方法添加到 AlertController 上即可。

    See more

    Declaration

    Objective-C

    @interface QMUIAlertAction : NSObject

    Swift

    class QMUIAlertAction : NSObject
  • QMUIAlertController是模仿系统UIAlertController的控件,所以系统有的功能在QMUIAlertController里面基本都有。同时QMUIAlertController还提供了一些扩展功能,例如:它的每个 button 都是开放出来的,可以对默认的按钮进行二次处理(比如加一个图片);可以通过 appearance 在 app 启动的时候修改整个QMUIAlertController的主题样式。

    See more

    Declaration

    Objective-C

    @interface QMUIAlertController
        : UIViewController <QMUIModalPresentationComponentProtocol> {
      UIView *_containerView;
      UIView *_scrollWrapView;
      UIScrollView *_headerScrollView;
      UIScrollView *_buttonScrollView;
      UIControl *_maskView;
    }

    Swift

    class QMUIAlertController : UIViewController, QMUIModalPresentationComponentProtocol
  • 一个提供通用的弹出浮层功能的控件,可以将任意UIViewUIViewController以浮层的形式显示出来并自动布局。

    支持 3 种方式显示浮层:

    1. 推荐 新起一个 UIWindow 盖在当前界面上,将 QMUIModalPresentationViewControllerrootViewController 的形式显示出来,可通过 supportedOrientationMask 支持横竖屏,不支持在浮层不消失的情况下做界面切换(因为 window 会把背后的 controller 盖住,看不到界面切换)。 可通过 shownInWindowMode 属性来判断是否在用这种方式显示。

      [modalPresentationViewController showWithAnimated:YES completion:nil];
      
    2. 使用系统接口来显示,支持界面切换,注意 使用这种方法必定只能以动画的形式来显示浮层,无法以无动画的形式来显示,并且 animated 参数必须为 NO。可通过 supportedOrientationMask 支持横竖屏。 可通过 shownInPresentedMode 属性来判断是否在用这种方式显示。

      [self presentViewController:modalPresentationViewController animated:NO completion:nil];
      
    3. 将浮层作为一个 subview 添加到 superview 上,从而能够实现在浮层不消失的情况下进行界面切换,但需要 superview 自行管理浮层的大小和横竖屏旋转,而且 QMUIModalPresentationViewController 不能用局部变量来保存,会在显示后被释放,需要自行 retain。横竖屏跟随当前界面的设置。 可通过 shownInSubviewMode 属性来判断是否在用这种方式显示。

      self.modalPresentationViewController.view.frame = CGRectMake(50, 50, 100, 100);
      [self.view addSubview:self.modalPresentationViewController.view];
      

    默认的布局会将浮层居中显示,浮层的大小可通过接口控制:

    1. 如果是用 contentViewController,则可通过 preferredContentSizeInModalPresentationViewController:keyboardHeight:limitSize: 来设置
    2. 如果使用 contentView,或者使用 contentViewController 但没实现 preferredContentSizeInModalPresentationViewController:keyboardHeight:limitSize:,则调用contentViewsizeThatFits:方法获取大小。
    3. 浮层大小会受 maximumContentViewWidth 属性的限制,以及 contentViewMargins 属性的影响。

    通过layoutBlockshowingAnimationhidingAnimation可设置自定义的布局、打开及隐藏的动画,并允许你适配键盘升起时的场景。

    默认提供背景遮罩dimmingView,你也可以使用自己的遮罩 view。

    默认提供多种显示动画,可通过 animationStyle 来设置。

    Warning

    如果使用者retain了modalPresentationViewController,注意应该在hideWithAnimated:completion:里release

    See

    QMUIAlertController

    See

    QMUIDialogViewController

    See

    QMUIMoreOperationController

    See more

    Declaration

    Objective-C

    @interface QMUIModalPresentationViewController : UIViewController

    Swift

    class QMUIModalPresentationViewController : UIViewController
  • 专用于QMUIModalPresentationViewController的UIWindow,这样才能在UIApplication.sharedApplication.windows里方便地区分出来

    Declaration

    Objective-C

    @interface QMUIModalPresentationWindow : UIWindow

    Swift

    class QMUIModalPresentationWindow : UIWindow
  • 通过业务定义的一个 key 来缓存 cell 的高度,需搭配 UITableView 使用,一般不用你自己去 init。 具体使用方式请看 UITableView (QMUICellHeightKeyCache) 的注释。

    See more

    Declaration

    Objective-C

    @interface QMUICellHeightKeyCache : NSObject

    Swift

    class QMUICellHeightKeyCache : NSObject
  • 一个常见的场景:当通过 objc_setAssociatedObject 以弱引用的方式(OBJC_ASSOCIATION_ASSIGN)绑定对象A时,假如对象A稍后被释放了,则通过 objc_getAssociatedObject 再次试图访问对象A时会导致野指针。 这时你可以将对象A包装为一个 QMUIWeakObjectContainer,并改为通过强引用方式(OBJC_ASSOCIATION_RETAIN_NONATOMIC/OBJC_ASSOCIATION_RETAIN)绑定这个 QMUIWeakObjectContainer,进而安全地获取原始对象A。

    See more

    Declaration

    Objective-C

    @interface QMUIWeakObjectContainer : NSProxy

    Swift

    class QMUIWeakObjectContainer : NSProxy
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUISegmentedControl : UISegmentedControl
    
    /// 获取当前的所有 segmentItem,可能包括 NSString 或 UIImage。
    @property(nonatomic, copy, readonly) NSArray *segmentItems;
    
    /**
     * 重新渲染 UISegmentedControl 的 UI,可以比较大程度地修改样式。比如 tintColor,selectedTextColor 等等。
     *
     * @param tintColor             Segmented 的 tintColor,作用范围包括字体颜色和按钮 border
     * @param selectedTextColor     Segmented 选中状态的字体颜色
     * @param fontSize              Segmented 上字体的大小
     */
    - (void)updateSegmentedUIWithTintColor:(UIColor *)tintColor
                         selectedTextColor:(UIColor *)selectedTextColor
                                  fontSize:(UIFont *)fontSize;
    
    /**
     * 用图片而非 tintColor 来渲染 UISegmentedControl 的 UI
     *
     * @param normalImage               Segmented 非选中状态的背景图
     * @param selectedImage             Segmented 选中状态的背景图
     * @param devideImage00             Segmented 在两个没有选中按钮 item 之间的分割线
     * @param devideImage01             Segmented 在左边没选中右边选中两个 item 之间的分割线
     * @param devideImage10             Segmented 在左边选中右边没选中两个 item 之间的分割线
     * @param textColor                 Segmented 的字体颜色
     * @param selectedTextColor         Segmented 选中状态的字体颜色
     * @param fontSize                  Segmented 的字体大小
     */
    - (void)setBackgroundWithNormalImage:(UIImage *)normalImage
                           selectedImage:(UIImage *)selectedImage
                           devideImage00:(UIImage *)devideImage00
                           devideImage01:(UIImage *)devideImage01
                           devideImage10:(UIImage *)devideImage10
                               textColor:(UIColor *)textColor
                       selectedTextColor:(UIColor *)selectedTextColor
                                fontSize:(UIFont *)fontSize;
    @end

    Swift

    class QMUISegmentedControl : UISegmentedControl
  • 通过业务定义的一个 key 来缓存 cell 的 size,需搭配 UICollectionView 使用,一般不用你自己去 init。 具体使用方式请看 UICollectionView (QMUICellSizeKeyCache) 的注释。

    See more

    Declaration

    Objective-C

    @interface QMUICellSizeKeyCache : NSObject

    Swift

    class QMUICellSizeKeyCache : NSObject
  • 相册里某一个资源的包装对象,该资源可能是图片、视频等。

    Note

    QMUIAsset 重写了 isEqual: 方法,只要两个 QMUIAsset 的 identifier 相同,则认为是同一个对象,以方便在数组、字典等容器中对大量 QMUIAsset 进行遍历查找等操作。
    See more

    Declaration

    Objective-C

    @interface QMUIAsset : NSObject

    Swift

    class QMUIAsset : NSObject
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUIAssetsGroup : NSObject
    
    - (instancetype)initWithPHCollection:(PHAssetCollection *)phAssetCollection;
    
    - (instancetype)initWithPHCollection:(PHAssetCollection *)phAssetCollection fetchAssetsOptions:(PHFetchOptions *)pHFetchOptions;
    
    /// 仅能通过 initWithPHCollection 和 initWithPHCollection:fetchAssetsOption 方法修改 phAssetCollection 的值
    @property(nonatomic, strong, readonly) PHAssetCollection *phAssetCollection;
    
    /// 仅能通过 initWithPHCollection 和 initWithPHCollection:fetchAssetsOption 方法修改 phAssetCollection 后,产生一个对应的 PHAssetsFetchResults 保存到 phFetchResult 中
    @property(nonatomic, strong, readonly) PHFetchResult *phFetchResult;
    
    /// 相册的名称
    - (NSString *)name;
    
    /// 相册内的资源数量,包括视频、图片、音频(如果支持)这些类型的所有资源
    - (NSInteger)numberOfAssets;
    
    /**
     *  相册的缩略图,即系统接口中的相册海报(Poster Image)
     *
     *  @return 相册的缩略图
     */
    - (UIImage *)posterImageWithSize:(CGSize)size;
    
    /**
     *  枚举相册内所有的资源
     *
     *  @param albumSortType    相册内资源的排序方式,可以选择日期最新的排在最前面,也可以选择日期最新的排在最后面
     *  @param enumerationBlock 枚举相册内资源时调用的 block,参数 result 表示每次枚举时对应的资源。
     *                          枚举所有资源结束后,enumerationBlock 会被再调用一次,这时 result 的值为 nil。
     *                          可以以此作为判断枚举结束的标记
     */
    - (void)enumerateAssetsWithOptions:(QMUIAlbumSortType)albumSortType usingBlock:(void (^)(QMUIAsset *resultAsset))enumerationBlock;
    
    /**
     *  枚举相册内所有的资源,相册内资源按日期最新的排在最后面
     *
     *  @param enumerationBlock 枚举相册内资源时调用的 block,参数 result 表示每次枚举时对应的资源。
     *                          枚举所有资源结束后,enumerationBlock 会被再调用一次,这时 result 的值为 nil。
     *                          可以以此作为判断枚举结束的标记
     */
    - (void)enumerateAssetsUsingBlock:(void (^)(QMUIAsset *result))enumerationBlock;
    
    @end

    Swift

    class QMUIAssetsGroup : NSObject
  • 构建 QMUIAssetsManager 这个对象并提供单例的调用方式主要出于下面两点考虑:

    1. 保存照片/视频的方法较为复杂,为了方便封装系统接口,同时灵活地扩展功能,需要有一个独立对象去管理这些方法。
    2. 使用 PhotoKit 获取图片,基本都需要一个 PHCachingImageManager 的实例,为了减少消耗, QMUIAssetsManager 单例内部也构建了一个 PHCachingImageManager,并且暴露给外面,方便获取 PHCachingImageManager 的实例。
    See more

    Declaration

    Objective-C

    @interface QMUIAssetsManager : NSObject

    Swift

    class QMUIAssetsManager : NSObject
  • 查看图片的控件,支持横向滚动、放大缩小、loading 及错误语展示,内部使用 UICollectionView 实现横向滚动及 cell 复用,因此与其他普通的 UICollectionView 一样,也可使用 reloadData、collectionViewLayout 等常用方法。

    使用方式:

    1. 使用 initWithFrame: 或 init 方法初始化。
    2. 设置 delegate。
    3. 在 delegate 的 numberOfImagesInImagePreviewView: 方法里返回图片总数。
    4. 在 delegate 的 imagePreviewView:renderZoomImageView:atIndex: 方法里为 zoomImageView.image 设置图片,如果需要,也可调用 [zoomImageView showLoading] 等方法来显示 loading。
    5. 由于 QMUIImagePreviewViewDelegate 继承自 QMUIZoomImageViewDelegate,所以若需要响应单击、双击、长按事件,请实现 QMUIZoomImageViewDelegate 里的对应方法。
    6. 若需要从指定的某一张图片开始查看,可使用 currentImageIndex 属性。

    See

    QMUIImagePreviewViewController
    See more

    Declaration

    Objective-C

    @interface QMUIImagePreviewView
        : UIView <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>

    Swift

    class QMUIImagePreviewView : UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
  • 支持缩放查看静态图片、live photo、视频的控件 默认显示完整图片或视频,可双击查看原始大小,再次双击查看放大后的大小,第三次双击恢复到初始大小。

    支持通过修改 contentMode 来控制静态图片和 live photo 默认的显示模式,目前仅支持 UIViewContentModeCenter、UIViewContentModeScaleAspectFill、UIViewContentModeScaleAspectFit,默认为 UIViewContentModeCenter。注意这里的显示模式是基于 viewportRect 而言的而非整个 zoomImageView

    See

    viewportRect

    QMUIZoomImageView 提供最基础的图片预览和缩放功能以及 loading、错误等状态的展示支持,其他功能请通过继承来实现。

    See more

    Declaration

    Objective-C

    @interface QMUIZoomImageView : UIView <UIScrollViewDelegate>

    Swift

    class QMUIZoomImageView : UIView, UIScrollViewDelegate
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUIZoomImageViewVideoToolbar : UIView
    
    @property(nonatomic, strong, readonly) QMUIButton *playButton;
    @property(nonatomic, strong, readonly) QMUIButton *pauseButton;
    @property(nonatomic, strong, readonly) QMUISlider *slider;
    @property(nonatomic, strong, readonly) UILabel *sliderLeftLabel;
    @property(nonatomic, strong, readonly) UILabel *sliderRightLabel;
    
    // 可通过调整此属性来调整 toolbar 内部的间距,默认为 {0, 0, 0, 0}
    @property(nonatomic, assign) UIEdgeInsets paddings UI_APPEARANCE_SELECTOR;
    
    // 可通过这些属性修改 video 播放时屏幕底部工具栏的播放/暂停图标
    @property(nonatomic, strong) UIImage *playButtonImage UI_APPEARANCE_SELECTOR;
    @property(nonatomic, strong) UIImage *pauseButtonImage UI_APPEARANCE_SELECTOR;
    
    @end

    Swift

    class QMUIZoomImageViewVideoToolbar : UIView
  • 图片预览控件,主要功能由内部自带的 QMUIImagePreviewView 提供,由于以 viewController 的形式存在,所以适用于那种在单独界面里展示图片,或者需要从某张目标图片的位置以动画的形式放大进入预览界面的场景。

    使用方式:

    1. 使用 init 方法初始化
    2. 添加 self.imagePreviewView 的 delegate
    3. 以 push 或 present 的方式打开界面。如果是 present,则支持 QMUIImagePreviewViewControllerTransitioningStyle 里定义的动画。特别地,如果使用 zoom 方式,则需要通过 sourceImageView() 返回一个原界面上的 view 以作为 present 动画的起点和 dismiss 动画的终点。

    See

    QMUIImagePreviewView
    See more

    Declaration

    Objective-C

    @interface QMUIImagePreviewViewController <
        UIViewControllerTransitioningDelegate>

    Swift

    class QMUIImagePreviewViewController : UIViewControllerTransitioningDelegate
  • 负责处理 QMUIImagePreviewViewController 被 present/dismiss 时的动画,如果需要自定义动画效果,可按需修改 animationEnteringBlock、animationBlock、animationCompletionBlock。

    See

    QMUIImagePreviewViewController.transitioningAnimator
    See more

    Declaration

    Objective-C

    @interface QMUIImagePreviewViewTransitionAnimator
        : NSObject <UIViewControllerAnimatedTransitioning>

    Swift

    class QMUIImagePreviewViewTransitionAnimator : NSObject, UIViewControllerAnimatedTransitioning
  • Undocumented

    Declaration

    Objective-C

    @interface QMUITestView : UIView
    
    @end

    Swift

    class QMUITestView : UIView
  • Undocumented

    Declaration

    Objective-C

    @interface QMUITestWindow : UIWindow
    
    @end

    Swift

    class QMUITestWindow : UIWindow
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUIAnimationHelper : NSObject
    
    typedef NS_ENUM(NSInteger, QMUIAnimationEasings) {
        QMUIAnimationEasingsLinear,
        QMUIAnimationEasingsEaseInSine,
        QMUIAnimationEasingsEaseOutSine,
        QMUIAnimationEasingsEaseInOutSine,
        QMUIAnimationEasingsEaseInQuad,
        QMUIAnimationEasingsEaseOutQuad,
        QMUIAnimationEasingsEaseInOutQuad,
        QMUIAnimationEasingsEaseInCubic,
        QMUIAnimationEasingsEaseOutCubic,
        QMUIAnimationEasingsEaseInOutCubic,
        QMUIAnimationEasingsEaseInQuart,
        QMUIAnimationEasingsEaseOutQuart,
        QMUIAnimationEasingsEaseInOutQuart,
        QMUIAnimationEasingsEaseInQuint,
        QMUIAnimationEasingsEaseOutQuint,
        QMUIAnimationEasingsEaseInOutQuint,
        QMUIAnimationEasingsEaseInExpo,
        QMUIAnimationEasingsEaseOutExpo,
        QMUIAnimationEasingsEaseInOutExpo,
        QMUIAnimationEasingsEaseInCirc,
        QMUIAnimationEasingsEaseOutCirc,
        QMUIAnimationEasingsEaseInOutCirc,
        QMUIAnimationEasingsEaseInBack,
        QMUIAnimationEasingsEaseOutBack,
        QMUIAnimationEasingsEaseInOutBack,
        QMUIAnimationEasingsEaseInElastic,
        QMUIAnimationEasingsEaseOutElastic,
        QMUIAnimationEasingsEaseInOutElastic,
        QMUIAnimationEasingsEaseInBounce,
        QMUIAnimationEasingsEaseOutBounce,
        QMUIAnimationEasingsEaseInOutBounce,
        QMUIAnimationEasingsSpring, // 自定义任意弹簧曲线
        QMUIAnimationEasingsSpringKeyboard // 系统键盘动画曲线
    };
    
    /**
     * 动画插值器
     * 根据给定的 easing 曲线,计算出初始值和结束值在当前的时间 time 对应的值。value 目前现在支持 NSNumber、UIColor 以及 NSValue 类型的 CGPoint、CGSize、CGRect、CGAffineTransform、UIEdgeInsets
     * @param fromValue 初始值
     * @param toValue 结束值
     * @param time 当前帧时间
     * @param easing 曲线,见`QMUIAnimationEasings`
     */
    + (id)interpolateFromValue:(id)fromValue
                       toValue:(id)toValue
                          time:(CGFloat)time
                        easing:(QMUIAnimationEasings)easing;
    /**
     * 动画插值器,支持弹簧参数
     * mass|damping|stiffness|initialVelocity 仅在 QMUIAnimationEasingsSpring 的时候才生效
     */
    + (id)interpolateSpringFromValue:(id)fromValue
                             toValue:(id)toValue
                                time:(CGFloat)time
                                mass:(CGFloat)mass
                             damping:(CGFloat)damping
                           stiffness:(CGFloat)stiffness
                     initialVelocity:(CGFloat)initialVelocity
                              easing:(QMUIAnimationEasings)easing;
    
    @end

    Swift

    class QMUIAnimationHelper : NSObject
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUIDisplayLinkAnimation : NSObject
    
    @property(nonatomic, strong, readonly) CADisplayLink *displayLink;
    
    @property(nonatomic, strong) id fromValue;
    @property(nonatomic, strong) id toValue;
    
    /// 动画时间
    @property(nonatomic, assign) NSTimeInterval duration;
    
    /// 动画曲线
    @property(nonatomic, assign) QMUIAnimationEasings easing;
    
    /// 是否需要重复,如果设置为YES,那么会无限重复动画,默认NO
    /// TODO: 目前功能上不支持小数点的循环次数,例如 0.5 1.5
    @property(nonatomic, assign) BOOL repeat;
    
    /// 延迟开始动画
    @property(nonatomic, assign) NSTimeInterval beginTime;
    
    /// 只有设置了repeat之后这个值才有用
    @property(nonatomic, assign) float repeatCount;
    
    /// 只有设置了repeat之后这个值才有用。如果YES,则往前做动画之后自动往后做动画,默认NO
    @property(nonatomic, assign) BOOL autoreverses;
    
    /// 做动画的block,适用于只有一个属性需要做动画,curValue是经过计算后当前帧的值
    @property(nonatomic, copy) void (^animation)(id curValue);
    
    /// 做动画的block,适用于多个属性做动画,需要在block里面自己计算当前帧的所有属性的值
    @property(nonatomic, copy) void (^animations)(QMUIDisplayLinkAnimation *animation, CGFloat curTime);
    
    - (instancetype)initWithDuration:(NSTimeInterval)duration
                              easing:(QMUIAnimationEasings)easing
                           fromValue:(id)fromValue
                             toValue:(id)toValue
                           animation:(void (^)(id curValue))animation;
    
    - (instancetype)initWithDuration:(NSTimeInterval)duration
                              easing:(QMUIAnimationEasings)easing
                          animations:(void (^)(QMUIDisplayLinkAnimation *animation, CGFloat curTime))animations;
    
    /// 开始动画,无论是第一次做动画或者暂停之后再重新做动画,都调用这个方法
    - (void)startAnimation;
    
    /// 停止动画,CADisplayLink 对象会被移出
    - (void)stopAnimation;
    
    /// 即将开始做动画
    @property(nonatomic, copy) void (^willStartAnimation)(void);
    
    /// 动画结束
    @property(nonatomic, copy) void (^didStopAnimation)(void);
    
    @end

    Swift

    class QMUIDisplayLinkAnimation : NSObject
  • 主题管理组件,可添加自定义的主题对象,并为每个对象指定一个专门的 identifier,当主题发生变化时,会遍历 UIViewController 和 UIView,调用每个 viewController 和每个可视 view 的 qmui_themeDidChangeByManager:identifier:theme: 方法,在里面由业务去自行根据当前主题设置不同的外观(color、image 等)。借助 QMUIThemeManagerCenter,可实现一个项目里同时存在多个维度的主题(例如全局维度存在 light/dark 2套主题,局部的某个界面存在 white/yellow/green/black 4套主题),各自互不影响,如果业务项目只需要一个维度的主题,则全都使用 QMUIThemeManagerCenter.defaultThemeManager 来获取 QMUIThemeManager 即可,如果业务有多维度主题的需求,可使用 +[QMUIThemeManagerCenter themeManagerWithName:] 生成不同的 QMUIThemeManager。

    详细文档请查看 GitHub Wiki @link https://github.com/Tencent/QMUI_iOS/wiki/%E4%BD%BF%E7%94%A8-QMUITheme-%E5%AE%9E%E7%8E%B0%E6%8D%A2%E8%82%A4%E5%B9%B6%E9%80%82%E9%85%8D-iOS-13-Dark-Mode

    关于 theme 的概念:

    1. 一个主题包含两个元素:identifier 表示主题的标志/名字,不允许重复;theme 代表主题对象本身,可以是任意的 NSObject 类型,只要业务自行规定即可。对于任意主题而言,identifier 和 theme 都不能为空,也不能重复。
    2. 主题的增删需要通过 QMUIThemeManager 的 addThemeIdentifier:theme:、removeThemeIdentifier:/removeTheme: 来实现。
    3. 可通过 QMUIThemeManager 的 themeIdentifiers、themes 属性来获取当前已注册的所有主题。
    4. 可通过修改 QMUIThemeManager 的 currentThemeIdentifier、currentTheme 属性来切换当前 App 的主题,修改这两个属性的其中一个属性,内部都会同时自动修改另外一个属性,以保证两者匹配。

    关于 iOS 13 新增的 Dark Mode:

    1. 如果 App 只需要在 iOS 13 里才切换深色的主题,直接使用系统的方式去实现即可,无需用到 QMUIThemeManager 的任何功能,QMUIThemeManager 适用于 App 需要在全 iOS 版本里都支持相同的皮肤切换(也即 iOS 13 下系统的 Dark Mode 也只是被视为你业务的某个皮肤)。在 iOS 13 下,QMUIThemeManager 的作用只是帮你监听系统 Dark Mode 的切换,并将系统的样式转换成业务对应的主题名,后续的实际工作其实跟 iOS 12 下切换主题是一样的。
    2. 如果要令 QMUIThemeManager 自动响应 iOS 13 的 Dark Mode,请先为 identifierForTrait 赋值,在内部根据 trait.userInterfaceStyle 的值返回对应的主题 identifier,再把 respondsSystemStyleAutomatically 改为 YES 即可。

    关于 App 界面响应主题变化的方式: 组件支持三种层面来响应主题变化:

    1. UIView 层面,如果是颜色(UIColor/CGColor)变化,请使用 [UIColor qmui_colorWithThemeProvider:] 方法来创建 UIColor,以及获取该 color 对应的 CGColor,建议每个颜色对应一个 @property,然后使用 [UIView qmui_registerThemeColorProperties:] 来注册这些需要在主题变化时自动刷新样式的 property,这样的好处是对设置颜色的时机没有要求,在 init 时就设置也没问题,不需要因为实现换肤而大量修改业务原有代码。如果是非 NSObject 的变化(例如 enum/struct 或者业务代码逻辑),可重写 [UIView qmui_themeDidChangeByManager:identifier:theme:],在里面根据当前主题做代码逻辑上的区分。
    2. UIViewController 层面,仅支持重写 [UIViewController qmui_themeDidChangeByManager:identifier:theme:] 方法来实现换肤。
    3. NSObject 层面,可通过监听 QMUIThemeDidChangeNotification 通知,在回调里处理主题切换事件(例如将当前选择的主题持久化记录下来,下次 App 启动直接应用)。

    标准场景下的使用流程:

    1. App 启动时,按需初始化 theme 对象并注册到 QMUIThemeManager 里。
    2. 根据当前用户的选择记录(例如 NSUserDefaults),通过 currentThemeIdentifier/currentTheme 指定当前的主题。
    3. 对需要响应主题变化的界面,检查其中的所有 UIColor、CGColor 的代码,将颜色换成使用 [UIColor qmui_colorWithThemeProvider:] 创建,如果该颜色对应一个 property,则使用 [UIView qmui_registerThemeColorProperties:] 注册这个 property,如果不对应 property,则请在 qmui_themeDidChangeByManager:identifier:theme: 里重新设置该颜色。
    4. 通过 QMUIThemeDidChangeNotification 监听主题的变化,将其持久化存储以便下次启动时应用。
    5. 若需要响应 iOS 13 的 Dark Mode,参考 respondsSystemStyleAutomatically、identifierForTrait 的注释。
    See more

    Declaration

    Objective-C

    @interface QMUIThemeManager : NSObject

    Swift

    class QMUIThemeManager : NSObject
  • 用于获取 QMUIThemeManager,具体使用请查看 QMUIThemeManager 的注释。

    See more

    Declaration

    Objective-C

    @interface QMUIThemeManagerCenter : NSObject

    Swift

    class QMUIThemeManagerCenter : NSObject
  • Warning

    由于支持 NSCopying,增加属性时必须在 copyWithZone: 里复制一次
    See more

    Declaration

    Objective-C

    @interface QMUIThemeColor : UIColor

    Swift

    class QMUIThemeColor : UIColor
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUIThemeImage : UIImage <QMUIDynamicImageProtocol, NSCopying>
    
    @property(nonatomic, copy) NSObject<NSCopying> *managerName;
    @property(nonatomic, copy) UIImage *(^themeProvider)(__kindof QMUIThemeManager * _Nonnull manager, __kindof NSObject<NSCopying> * _Nullable identifier, __kindof NSObject * _Nullable theme);
    @end

    Swift

    class QMUIThemeImage : UIImage, QMUIDynamicImageProtocol, NSCopying
  • Warning

    由于支持 NSCopying,增加属性时必须在 copyWithZone: 里复制一次
    See more

    Declaration

    Objective-C

    @interface QMUIThemeVisualEffect : NSObject <QMUIDynamicEffectProtocol>

    Swift

    class QMUIThemeVisualEffect : NSObject, QMUIDynamicEffectProtocol
  • 带箭头的小tips浮层,自带 imageView 和 textLabel,可展示简单的图文信息,支持 UIViewContentModeTop/UIViewContentModeBottom/UIViewContentModeCenter 三种布局方式。 QMUIPopupContainerView 支持以两种方式显示在界面上:

    1. 添加到某个 UIView 上(适合于 viewController 切换时浮层跟着一起切换的场景),这种场景只能手动隐藏浮层。
    2. 在 QMUIPopupContainerView 自带的 UIWindow 里显示(适合于用完就消失的场景,不要涉及界面切换),这种场景支持点击空白地方自动隐藏浮层。

    使用步骤:

    1. 调用 init 方法初始化。
    2. 选择一种显示方式: 2.1 如果要添加到某个 UIView 上,则先设置浮层 hidden = YES,然后调用 addSubview: 把浮层添加到目标 UIView 上。 2.2 如果是轻量的场景用完即走,则 init 完浮层即可,无需设置 hidden,也无需调用 addSubview:,在后面第 4 步里会自动把浮层添加到 UIWindow 上显示出来。
    3. 通过为 sourceBarItem/sourceView/sourceRect 三者中的一个赋值,来决定浮层布局的位置。
    4. 调用 showWithAnimated: 或 showWithAnimated:completion: 显示浮层。
    5. 调用 hideWithAnimated: 或 hideWithAnimated:completion: 隐藏浮层。

    Warning

    如果使用方法 2.2,并且没有打开 automaticallyHidesWhenUserTap 属性,则记得在适当的时机(例如 viewWillDisappear:)隐藏浮层。

    如果默认功能无法满足需求,可继承它重写一个子类,继承要点:

    1. 初始化时要做的事情请放在 didInitialize 里。
    2. 所有 subviews 请加到 contentView 上。
    3. 通过重写 sizeThatFitsInContentView:,在里面返回当前 subviews 的大小。
    4. 在 layoutSubviews: 里,所有 subviews 请相对于 contentView 布局。
    See more

    Declaration

    Objective-C

    @interface QMUIPopupContainerView : UIControl {
      CAShapeLayer *_backgroundLayer;
      CGFloat _arrowMinX;
      CGFloat _arrowMinY;
    }

    Swift

    class QMUIPopupContainerView : UIControl
  • 每一条 QMUILog 日志都以 QMUILogItem 的形式包装起来

    See more

    Declaration

    Objective-C

    @interface QMUILogItem : NSObject

    Swift

    class QMUILogItem : NSObject
  • log.name 的管理器,由它来管理每一个 name 是否可用、以及清理不需要的 name

    See more

    Declaration

    Objective-C

    @interface QMUILogNameManager : NSObject

    Swift

    class QMUILogNameManager : NSObject
  • Undocumented

    See more

    Declaration

    Objective-C

    @interface QMUILogger : NSObject
    
    @property(nullable, nonatomic, weak) id<QMUILoggerDelegate> delegate;
    @property(nonnull, nonatomic, strong) QMUILogNameManager *logNameManager;
    
    + (nonnull instancetype)sharedInstance;
    - (void)printLogWithFile:(nullable const char *)file line:(int)line func:(nonnull const char *)func logItem:(nullable QMUILogItem *)logItem;
    @end

    Swift

    class QMUILogger : NSObject
  • 做类似 CSS 里的 float:left 的布局,自行使用 addSubview: 将子 View 添加进来即可。

    支持通过 contentMode 属性修改子 View 的对齐方式,目前仅支持 UIViewContentModeLeftUIViewContentModeRight,默认为 UIViewContentModeLeft

    See more

    Declaration

    Objective-C

    @interface QMUIFloatLayoutView : UIView

    Swift

    class QMUIFloatLayoutView : UIView
  • 存放多个 delegate 指针的容器,必须搭配其他控件使用,一般不需要你自己 init。作用是让某个 class 支持同时存在多个 delegate。更多说明请查看 NSObject (QMUIMultipleDelegates) 的注释。

    See more

    Declaration

    Objective-C

    @interface QMUIMultipleDelegates : NSObject

    Swift

    class QMUIMultipleDelegates : NSObject
  • 支持的特性包括:

    1. 自定义 placeholderColor。
    2. 自定义 UITextField 的文字 padding。
    3. 支持限制输入的文字的长度。
    4. 修复 iOS 10 之后 UITextField 输入中文超过文本框宽度后再删除,文字往下掉的 bug。
    See more

    Declaration

    Objective-C

    @interface QMUITextField : UITextField

    Swift

    class QMUITextField : UITextField
  • 提供以下功能:

    1. 支持让文字和图片自动跟随 tintColor 变化(系统的 UIButton 默认是不响应 tintColor 的)
    2. highlighted、disabled 状态均通过改变整个按钮的alpha来表现,无需分别设置不同 state 下的 titleColor、image。alpha 的值可在配置表里修改 ButtonHighlightedAlpha、ButtonDisabledAlpha。
    3. 支持点击时改变背景色颜色(highlightedBackgroundColor)
    4. 支持点击时改变边框颜色(highlightedBorderColor)
    5. 支持设置图片相对于 titleLabel 的位置(imagePosition)
    6. 支持设置图片和 titleLabel 之间的间距,无需自行调整 titleEdgeInests、imageEdgeInsets(spacingBetweenImageAndTitle)

Warning

QMUIButton 重新定义了 UIButton.titleEdgeInests、imageEdgeInsets、contentEdgeInsets 这三者的布局逻辑,sizeThatFits: 里会把 titleEdgeInests 和 imageEdgeInsets 也考虑在内(UIButton 不会),以使这三个接口的使用更符合直觉。

Declaration

Objective-C

@interface QMUIButton : UIButton

Swift

class QMUIButton : UIButton