iOS开发之修改分页控制器UIPageControl的图片和大小以及圆点之间的距离

今天遇到这个需求,需要修改UIPageControl圆点之间的间距。查资料找到以下两种方法,其一是自定义继承UIPageControl的类,其二是使用runtime交换方法来修改。

文笔不好直接代码记录

法一:继承UIPageControl

#import "HYRPageControl.h"
#define kDotW 30  //圆点的宽度
#define kMagrin 20 //圆点之间的间隔


@interface HYRPageControl ()

@end



@implementation HYRPageControl

#pragma mark - 法一
- (void)layoutSubviews
{
    [super layoutSubviews];
    
    //计算圆点尺寸和间距的长度
    CGFloat marginX = kDotW + kMagrin;
    
    //计算整个pageControll的宽度
    CGFloat newW = self.frame.size.width;//(self.subviews.count - 1 ) * magrin + self.subviews.count *dotW;
    
    //计算左边距
    CGFloat leftRight = (newW - ((self.subviews.count - 1 ) * kMagrin + self.subviews.count * kDotW)) / 2;
    
    //设置新frame
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, newW, self.frame.size.height);
    
    //遍历subview,设置圆点frame
    for (int i=0; i<[self.subviews count]; i++) {
        UIImageView* dot = [self.subviews objectAtIndex:i];
        [dot setFrame:CGRectMake(i * marginX + leftRight, dot.frame.origin.y, kDotW, kDotW)];
    }
}

@end

运行效果如下图:

iOS开发之修改分页控制器UIPageControl的图片和大小以及圆点之间的距离_第1张图片



法二:使用runtime交换UIPageControl的私有方法

首先找私有的方法或者所有的成员变量。

我本来是在demo中已经输出所有的成员变量了,但是没有发现相关距离的变量。简单看看代码

// runtime:根据模型中属性,去字典中取出对应的value给模型属性赋值
    // 1.获取模型中所有成员变量 key
    // 获取哪个类的成员变量
    // count:成员变量个数
    unsigned int count = 0;
    // 获取成员变量数组
    Ivar *ivarList = class_copyIvarList([UIPageControl class], &count);
    for (NSInteger i = 0; i



其次利用runtime的 class_copyMethodList 函数获取到UIPageControl的的所有方法

//runtime 获取所有方法名
    unsigned int count = 0;
    //获取方法列表
    Method *methodList = class_copyMethodList([UIPageControl class], &count);
    for (NSInteger i = 0; i < count; i++) {
        //
        Method method = methodList[i];
        SEL sel = method_getName(method);
        NSString *methodName = [NSString stringWithUTF8String:sel_getName(sel)];
        
        //返回值类型
        char *dst = method_copyReturnType(method);
        
//        size_t dstLen = 512;
//        char dst[512] = {};
//        method_getReturnType(method, dst, dstLen);
        
        NSLog(@"methodName:%@- retunType:%@",methodName,[NSString stringWithUTF8String:dst]);
        
    }

这for循环里面输出的结果如下:

2017-08-26 21:02:37.377 Runtime修改分页控制器的距离[2794:135521] methodName:.cxx_destruct- retunType:v
2017-08-26 21:02:37.380 Runtime修改分页控制器的距离[2794:135521] methodName:layoutSubviews- retunType:v
2017-08-26 21:02:37.380 Runtime修改分页控制器的距离[2794:135521] methodName:_populateArchivedSubviews:- retunType:v
2017-08-26 21:02:37.381 Runtime修改分页控制器的距离[2794:135521] methodName:_contentHuggingDefault_isUsuallyFixedHeight- retunType:B
2017-08-26 21:02:37.381 Runtime修改分页控制器的距离[2794:135521] methodName:_contentHuggingDefault_isUsuallyFixedWidth- retunType:B
2017-08-26 21:02:37.381 Runtime修改分页控制器的距离[2794:135521] methodName:gestureRecognizerShouldBegin:- retunType:B
2017-08-26 21:02:37.381 Runtime修改分页控制器的距离[2794:135521] methodName:canBecomeFocused- retunType:B
2017-08-26 21:02:37.381 Runtime修改分页控制器的距离[2794:135521] methodName:intrinsicContentSize- retunType:{CGSize=dd}
2017-08-26 21:02:37.382 Runtime修改分页控制器的距离[2794:135521] methodName:_didChangeFromIdiom:onScreen:traverseHierarchy:- retunType:v
2017-08-26 21:02:37.382 Runtime修改分页控制器的距离[2794:135521] methodName:endTrackingWithTouch:withEvent:- retunType:v
2017-08-26 21:02:37.382 Runtime修改分页控制器的距离[2794:135521] methodName:_controlEventsForActionTriggered- retunType:Q
2017-08-26 21:02:37.384 Runtime修改分页控制器的距离[2794:135521] methodName:_effectiveContentView- retunType:@
2017-08-26 21:02:37.384 Runtime修改分页控制器的距离[2794:135521] methodName:setHidesForSinglePage:- retunType:v
2017-08-26 21:02:37.384 Runtime修改分页控制器的距离[2794:135521] methodName:setCurrentPageIndicatorTintColor:- retunType:v
2017-08-26 21:02:37.385 Runtime修改分页控制器的距离[2794:135521] methodName:setPageIndicatorTintColor:- retunType:v
2017-08-26 21:02:37.385 Runtime修改分页控制器的距离[2794:135521] methodName:setNumberOfPages:- retunType:v
2017-08-26 21:02:37.385 Runtime修改分页控制器的距离[2794:135521] methodName:setCurrentPage:- retunType:v
2017-08-26 21:02:37.385 Runtime修改分页控制器的距离[2794:135521] methodName:currentPage- retunType:q
2017-08-26 21:02:37.385 Runtime修改分页控制器的距离[2794:135521] methodName:_pageIndicatorImageForPage:- retunType:@
2017-08-26 21:02:37.385 Runtime修改分页控制器的距离[2794:135521] methodName:_pageIndicatorCurrentImageForPage:- retunType:@
2017-08-26 21:02:37.386 Runtime修改分页控制器的距离[2794:135521] methodName:_commonPageControlInit- retunType:v
2017-08-26 21:02:37.386 Runtime修改分页控制器的距离[2794:135521] methodName:numberOfPages- retunType:q
2017-08-26 21:02:37.386 Runtime修改分页控制器的距离[2794:135521] methodName:_invalidateIndicators- retunType:v
2017-08-26 21:02:37.386 Runtime修改分页控制器的距离[2794:135521] methodName:_activePageIndicatorImage- retunType:@
2017-08-26 21:02:37.386 Runtime修改分页控制器的距离[2794:135521] methodName:_cachedPageIndicatorImageForPage:- retunType:@
2017-08-26 21:02:37.386 Runtime修改分页控制器的距离[2794:135521] methodName:_cachedPageIndicatorCurrentImageForPage:- retunType:@
2017-08-26 21:02:37.387 Runtime修改分页控制器的距离[2794:135521] methodName:_pageIndicatorImage- retunType:@
2017-08-26 21:02:37.387 Runtime修改分页控制器的距离[2794:135521] methodName:_cachePageIndicatorImages- retunType:v
2017-08-26 21:02:37.387 Runtime修改分页控制器的距离[2794:135521] methodName:_indicatorViewEnabled:index:- retunType:@
2017-08-26 21:02:37.387 Runtime修改分页控制器的距离[2794:135521] methodName:_setCurrentPage:- retunType:v
2017-08-26 21:02:37.387 Runtime修改分页控制器的距离[2794:135521] methodName:_setDisplayedPage:- retunType:v
2017-08-26 21:02:37.388 Runtime修改分页控制器的距离[2794:135521] methodName:_updateCurrentPageDisplay- retunType:v
2017-08-26 21:02:37.388 Runtime修改分页控制器的距离[2794:135521] methodName:_indicatorSpacing- retunType:d
2017-08-26 21:02:37.388 Runtime修改分页控制器的距离[2794:135521] methodName:_indicatorFrameAtIndex:- retunType:{CGRect={CGPoint=dd}{CGSize=dd}}
2017-08-26 21:02:37.388 Runtime修改分页控制器的距离[2794:135521] methodName:_hasCustomImageForPage:enabled:- retunType:B
2017-08-26 21:02:37.388 Runtime修改分页控制器的距离[2794:135521] methodName:_modernBounds- retunType:{CGRect={CGPoint=dd}{CGSize=dd}}
2017-08-26 21:02:37.389 Runtime修改分页控制器的距离[2794:135521] methodName:_transitionIndicator:toEnabled:index:- retunType:v
2017-08-26 21:02:37.389 Runtime修改分页控制器的距离[2794:135521] methodName:_modernTransitionIndicator:toEnabled:index:legible:- retunType:v
2017-08-26 21:02:37.389 Runtime修改分页控制器的距离[2794:135521] methodName:_shouldDrawLegibly- retunType:B
2017-08-26 21:02:37.389 Runtime修改分页控制器的距离[2794:135521] methodName:_transitionIndicator:toEnabled:index:legible:- retunType:v
2017-08-26 21:02:37.390 Runtime修改分页控制器的距离[2794:135521] methodName:_indicatorViewEnabled:index:legible:- retunType:@
2017-08-26 21:02:37.390 Runtime修改分页控制器的距离[2794:135521] methodName:_drawModernIndicatorInView:enabled:- retunType:v
2017-08-26 21:02:37.390 Runtime修改分页控制器的距离[2794:135521] methodName:_modernIndicatorImageEnabled:- retunType:@
2017-08-26 21:02:37.390 Runtime修改分页控制器的距离[2794:135521] methodName:_setLegibilitySettings:- retunType:v
2017-08-26 21:02:37.390 Runtime修改分页控制器的距离[2794:135521] methodName:_modernColorEnabled:- retunType:@
2017-08-26 21:02:37.391 Runtime修改分页控制器的距离[2794:135521] methodName:_modernCornerRadius- retunType:d
2017-08-26 21:02:37.391 Runtime修改分页控制器的距离[2794:135521] methodName:_createModernIndicatorImageFromView:- retunType:@
2017-08-26 21:02:37.391 Runtime修改分页控制器的距离[2794:135521] methodName:hidesForSinglePage- retunType:B
2017-08-26 21:02:37.391 Runtime修改分页控制器的距离[2794:135521] methodName:setDefersCurrentPageDisplay:- retunType:v
2017-08-26 21:02:37.392 Runtime修改分页控制器的距离[2794:135521] methodName:defersCurrentPageDisplay- retunType:B
2017-08-26 21:02:37.392 Runtime修改分页控制器的距离[2794:135521] methodName:updateCurrentPageDisplay- retunType:v
2017-08-26 21:02:37.392 Runtime修改分页控制器的距离[2794:135521] methodName:sizeForNumberOfPages:- retunType:{CGSize=dd}
2017-08-26 21:02:37.393 Runtime修改分页控制器的距离[2794:135521] methodName:_displayedPage- retunType:q
2017-08-26 21:02:37.393 Runtime修改分页控制器的距离[2794:135521] methodName:_setLegibilityStyle:- retunType:v
2017-08-26 21:02:37.393 Runtime修改分页控制器的距离[2794:135521] methodName:_legibilityStyle- retunType:q
2017-08-26 21:02:37.393 Runtime修改分页控制器的距离[2794:135521] methodName:currentPageIndicatorTintColor- retunType:@
2017-08-26 21:02:37.394 Runtime修改分页控制器的距离[2794:135521] methodName:pageIndicatorTintColor- retunType:@
2017-08-26 21:02:37.394 Runtime修改分页控制器的距离[2794:135521] methodName:_legibilitySettings- retunType:@
2017-08-26 21:02:37.394 Runtime修改分页控制器的距离[2794:135521] methodName:isElementAccessibilityExposedToInterfaceBuilder- retunType:B
2017-08-26 21:02:37.394 Runtime修改分页控制器的距离[2794:135521] methodName:encodeWithCoder:- retunType:v
2017-08-26 21:02:37.395 Runtime修改分页控制器的距离[2794:135521] methodName:initWithCoder:- retunType:@
2017-08-26 21:02:37.395 Runtime修改分页控制器的距离[2794:135521] methodName:initWithFrame:- retunType:@
2017-08-26 21:02:37.395 Runtime修改分页控制器的距离[2794:135521] methodName:sizeThatFits:- retunType:{CGSize=dd}


找啊找 找啊找  终于让我发现了这个方法 

_indicatorSpacing

返回值类型是double


再次,根据私有方法的方法名和参数以及返回值类型 定义一个自己想要功能的方法

这样的话 我就先在我的控制器里面写一个方法,方法名最好是我们的前缀加上这个私有的方法名,这样一看就可以猜到是什么作用了。

#pragma mark - 自定义方法来实现 圆点之间的距离  利用runtime交换方法
-(CGFloat)hyr_indicatorSpacing{
    return 80.0;
}


最后,利用runtime运行时调换私有方法和自定义方法的实现

//runtime 交换方法 实现圆点之间的距离
    //系统的方法
    Method origin = class_getInstanceMethod([UIPageControl class], sel_registerName("_indicatorSpacing"));
    Method custom = class_getInstanceMethod([self class], sel_registerName("hyr_indicatorSpacing"));
    //但是调用了私有的API方法,据说上传appstroe会被拒的
    method_exchangeImplementations(origin, custom);
    
运行结果如下:

iOS开发之修改分页控制器UIPageControl的图片和大小以及圆点之间的距离_第2张图片















你可能感兴趣的:(iOS高级编程)