62

iOS | PNChart与UITableView的联动

 5 years ago
source link: http://www.cocoachina.com/ios/20180710/24103.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

aiqEv2a.jpg!web

效果图

VJfqyea.gif

效果图.gif

1.点击chart,tableView对应模块高亮

PNChart提供了一个代理方法,用来处理用户的点击事件:

#pragma mark - PNChart Delegate
- (void)userClickedOnPieIndexItem:(NSInteger)pieIndex {
    for (int i = 0; i < self.model.department_sale.count; i++) {
        CQSaleDetailDepartmentItemModel *model = self.model.department_sale[i];
        model.selected = (i == pieIndex);
    }
    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:pieIndex inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}

2.点击cell,chart对应模块高亮

PNChart并未提供相应方法让某一模块高亮,怎么办?

思路:

虽然PNChart未直接提供让某一模块高亮的方法,但是我们可以从用户点击模块高亮那部分代码入手,看看用户点击到模块高亮是怎样一个过程。

1.在PNPieChart.m里面找到touchesBegan方法:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        CGPoint touchLocation = [touch locationInView:_contentView];
        [self didTouchAt:touchLocation];
    }
}

发现它调用了didTouchAt:方法。

2.分析didTouchAt:

- (void)didTouchAt:(CGPoint)touchLocation
{
    CGPoint circleCenter = CGPointMake(_contentView.bounds.size.width/2, _contentView.bounds.size.height/2);
    
    CGFloat distanceFromCenter = sqrtf(powf((touchLocation.y - circleCenter.y),2) + powf((touchLocation.x - circleCenter.x),2));
    
    if (distanceFromCenter < _innerCircleRadius) {
        if ([self.delegate respondsToSelector:@selector(didUnselectPieItem)]) {
            [self.delegate didUnselectPieItem];
        }
        [self.sectorHighlight removeFromSuperlayer];
        return;
    }
    
    CGFloat percentage = [self findPercentageOfAngleInCircle:circleCenter fromPoint:touchLocation];
    int index = 0;
    while (percentage > [self endPercentageForItemAtIndex:index]) {
        index ++;
    }
    
    if ([self.delegate respondsToSelector:@selector(userClickedOnPieIndexItem:)]) {
        [self.delegate userClickedOnPieIndexItem:index];
    }
    
    if (self.shouldHighlightSectorOnTouch)
    {
        if (!self.enableMultipleSelection)
        {
            if (self.sectorHighlight)
                [self.sectorHighlight removeFromSuperlayer];
        }
        
        PNPieChartDataItem *currentItem = [self dataItemForIndex:index];
        
        CGFloat red,green,blue,alpha;
        UIColor *old = currentItem.color;
        [old getRed:&red green:&green blue:&blue alpha:α];
        alpha /= 2;
        UIColor *newColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
        
        CGFloat startPercentage = [self startPercentageForItemAtIndex:index];
        CGFloat endPercentage   = [self endPercentageForItemAtIndex:index];
        
        self.sectorHighlight = [self newCircleLayerWithRadius:_outerCircleRadius + 5
                                                  borderWidth:10
                                                    fillColor:[UIColor clearColor]
                                                  borderColor:newColor
                                              startPercentage:startPercentage
                                                endPercentage:endPercentage];
        
        if (self.enableMultipleSelection)
        {
            NSString *dictIndex = [NSString stringWithFormat:@"%d", index];
            CAShapeLayer *indexShape = [self.selectedItems valueForKey:dictIndex];
            if (indexShape)
            {
                [indexShape removeFromSuperlayer];
                [self.selectedItems removeObjectForKey:dictIndex];
            }
            else
            {
                [self.selectedItems setObject:self.sectorHighlight forKey:dictIndex];
                [_contentView.layer addSublayer:self.sectorHighlight];
            }
        }
        else
        {
            [_contentView.layer addSublayer:self.sectorHighlight];
        }
    }
}

通过源代码我们可以发现,用户点击chart的时候,将传入的参数touchLocation转换成了index,这个index正是代理方法userClickedOnPieIndexItem:所需要的参数。另外,chart的某一模块高亮,实际上是addSublayer:,而这个sublayer的属性也是由index决定的。所以,通过主动调用一个方法让chart的某个模块高亮,关键就是这个index。

这样的话,就很简单了。只需把didTouchAt :的后半段代码提出来,就是我们需要的新方法了:

/**
 某一模块高亮
 @param index 高亮模块的index
 */
- (void)highlightItemWithIndex:(NSInteger)index {
    if (self.shouldHighlightSectorOnTouch)
    {
        if (!self.enableMultipleSelection)
        {
            if (self.sectorHighlight)
                [self.sectorHighlight removeFromSuperlayer];
        }
        
        PNPieChartDataItem *currentItem = [self dataItemForIndex:index];
        
        CGFloat red,green,blue,alpha;
        UIColor *old = currentItem.color;
        [old getRed:&red green:&green blue:&blue alpha:α];
        alpha /= 2;
        UIColor *newColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
        
        CGFloat startPercentage = [self startPercentageForItemAtIndex:index];
        CGFloat endPercentage   = [self endPercentageForItemAtIndex:index];
        
        self.sectorHighlight = [self newCircleLayerWithRadius:_outerCircleRadius + 5
                                                  borderWidth:10
                                                    fillColor:[UIColor clearColor]
                                                  borderColor:newColor
                                              startPercentage:startPercentage
                                                endPercentage:endPercentage];
        
        if (self.enableMultipleSelection)
        {
            NSString *dictIndex = [NSString stringWithFormat:@"%ld", (long)index];
            CAShapeLayer *indexShape = [self.selectedItems valueForKey:dictIndex];
            if (indexShape)
            {
                [indexShape removeFromSuperlayer];
                [self.selectedItems removeObjectForKey:dictIndex];
            }
            else
            {
                [self.selectedItems setObject:self.sectorHighlight forKey:dictIndex];
                [_contentView.layer addSublayer:self.sectorHighlight];
            }
        }
        else
        {
            [_contentView.layer addSublayer:self.sectorHighlight];
        }
    }
}

现在就可以实现点击cell,chart对应模块高亮了:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    for (int i = 0; i < self.model.department_sale.count; i++) {
        CQSaleDetailDepartmentItemModel *model = self.model.department_sale[i];
        model.selected = (i == indexPath.row);
    }
    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    // 对应的模块高亮
    [self.pieChart highlightItemWithIndex:indexPath.row];
}

修改源码注意事项

如果你的PNChart是手动拖进去的,修改源码无所谓;

但如果是用CocoaPods管理的话,就要注意一下了:pod update的时候会覆盖你写的代码。为避免这种事情发生,你可以指定库的版本,如:

pod 'PNChart','0.8.9'

pod update的时候,若发现其版本是指定的版本,就不会更新了。

作者:无夜之星辰

链接:https://www.jianshu.com/p/759ea22a2a0f


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK