To run the example project, clone the repo, and run pod install
from the Example directory first.
ios 8 or higher
RXProgressBar is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'RXProgressBar'
This is the library can build in your uitableview complex ProgressBar step by step (like in web). In a few lines of code, you can easily integrate the RXProgressBar into your project. In one cell you can insert a field with text and from zero to five photos.
iPhone Demo | iPad Demo |
---|---|
- 🏎️ Quick integration into your table
- ✳️ Ability to insert multiple instruction into a single uitableview at the same time
- 🗑 Easy to remove cells or entire instructions
- 📊 5 standard UI styles + ability to create your own
- 🎮 Unlimited UI customization options
- 🎚 Dynamic calculations of the height of the cell relative to the text and images
- ⚙️ Automatic frame layout of all photos in a grid
- 🎞 Support for GIF images in the instructions
- 🖼 Ability to open a photo in full screen mode
- 📄 Ability to add up to three text descriptions to a photo
- ⬆️ ⬇️ Supports all orientations (Horizontal / Vertical)
- 📈 Optimized table operation
- 🌋 Fast work on older devices starting from ios 8
- 📋 Examples of implementation on MVC and MVVM.
- 📖 Full documentation
Also choose from five ui styles, or create your own.
RXProgressBarStyle1 | RXProgressBarStyle2 | RXProgressBarStyle3 |
---|---|---|
RXProgressBarStyle4 | RXProgressBarStyle5 | RXProgressBarCustomStyle |
Import next files in your ViewController
// Cell's ViewModels from RXProgressBar
#import <RXProgressBar/RXBaseViewModelCell.h>
#import <RXProgressBar/RXBeginViewModelCell.h>
#import <RXProgressBar/RXMiddleViewModelCell.h>
#import <RXProgressBar/RXEndViewModelCell.h>
// Cell from RXProgressBar
#import <RXProgressBar/RXBaseCell.h>
#import <RXProgressBar/RXBeginCell.h>
#import <RXProgressBar/RXMiddleCell.h>
#import <RXProgressBar/RXEndCell.h>
// RXProgressBar's main core files
#import <RXProgressBar/RXCollectionPB.h>
#import <RXProgressBar/RXProgressBar.h>
#import <RXProgressBar/RXUIConfig.h>
#import <RXProgressBar/RXIndexPath.h>
Implement the following properties.
@interface TableViewControllerMVC ()
...
@property (nonatomic, strong) NSMutableArray* dataTableView; // Here store RXProgressBar's viewmodels and own models
@property (nonatomic, strong) RXCollectionPB* pbCollection; // Here store the progressbars aka instruction
@property (nonatomic, strong) NSCache* imageCache; // Here store cache images from all progressBar
...
@end
Initialize them in a convenient place for you (for example: - init or-viewDidLoad)
...
self.dataTableView = [NSMutableArray array];
self.pbCollection = [RXCollectionPB new];
self.imageCache = [[NSCache alloc] init];
...
Override the -didReceiveMemoryWarning method. In case of a call, it will clear the cache with photos.
-(void) didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
[self.imageCache removeAllObjects];
}
RXProgressBar is an account manager with cells. You can transfer the data models which confrom "RXInstructionModelProtocol" protocol to the RXProgressBar after that, it will do all the work for you. Object which conform this protocol, must have next properties:
{
"instruction" : "Wash the pumpkin",
"images" : [
{
"url" : "https:///site.com/1.jpg",
"title" : "Pumplin ",
"summary" : "it should be bright",
"credit" : "Wash and wipe the pumpkin dry"
},
{
"url" : "https:///site.com/2.jpg",
"title" : "Pumplin ",
"summary" : "it should be bright",
"credit" : "Wash and wipe the pumpkin dry"
}
]
}
Create model object which confrom this protocol and implement next properties:
#import "RXInstructionModelProtocol.h"
@interface RXInstructionModel : NSObject <RXInstructionModelProtocol>
@property (nonatomic, strong) NSString* instruction;
@property (nonatomic, strong) NSArray<id<RXInstructionImgModelProtocol >>* imagesURL;
- (instancetype)initWithInstruction:(NSString*) instruction
withImgsURL:(NSArray<id<RXInstructionImgModelProtocol>>*)imgArr;
- (instancetype)initWithInstruction:(NSString*) instruction
withMixArrImgs:(NSArray*)imgArr;
@end
Create and call a method that contains the following strings
- Create array with model which conform with protocol "RXInstructionModelProtocol"
- Create RXProgressBar object
- Create UIConfig object
- Call -createVMfromModelsArray method and get ViewModel from your array with protocol objects
- Save these objects (viewmodels) in your ViewController or (if you use MVVM pattern, then in your ViewModel)
- Add RXProgressBar to self.pbCollection
{
...
// Get array with object which conform with protocol "RXInstructionModelProtocol"
NSArray<id<RXInstructionModelProtocol>>* dataForFirstInstruction = [DataBuilder createPumkinInstruction];
// Create first RXProgressBar(aka."Instruction") with reference on RXCollectionPB (aka. "super collection")
RXProgressBar* firstInstruction = [[RXProgressBar alloc] initWithCollectionPB: self.pbCollection addAdditionalBeginAndEndCells: YES];
// Select ui style for our RXProgressBar
firstInstruction.configUI = [[RXUIConfig alloc] initConfigWithStyle: RXProgressBarStyle3];
// Transform (object which conform with protocol "RXInstructionModelProtocol") to -> RXProgressBar's private viewmodel's cells
NSArray* arrVMFromFirstBar = [firstInstruction createVMfromModelsArray: dataForFirstInstruction withRefOnImgCache:self.imageCache];
// Add these viewmodels to tableview datasource array
[self.dataTableView addObjectsFromArray: arrVMFromFirstBar];
[self.pbCollection addPB: firstInstruction];
...
}
Implement or modify the following methods
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = 40.f;
// Get viewmodel from our datasource array
id vm = [self.dataTableView objectAtIndex:indexPath.row];
// depending on what kind of viewModel, will calculate the unique height
if ([vm isKindOfClass:[RXBaseViewModelCell class]])
{
Class classOfCell = [RXBaseCell class];
RXBaseViewModelCell* convetVM = (RXBaseViewModelCell*)vm;
if ([convetVM isMemberOfClass:[RXBeginViewModelCell class]]) classOfCell = [RXBeginCell class];
if ([convetVM isMemberOfClass:[RXMiddleViewModelCell class]]) classOfCell = [RXMiddleCell class];
if ([convetVM isMemberOfClass:[RXEndViewModelCell class]]) classOfCell = [RXEndCell class];
height = [classOfCell calculateHeightByUIConfig:convetVM.progressBar.configUI
withVM:vm
withSuperViewWidth:CGRectGetWidth(self.tableView.frame)];
}
return roundf(height);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
id cell;
NSString* identifier = [self getClassNameByViewModelCell:[self.dataTableView objectAtIndex:indexPath.row]];
cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell){
cell = [[NSClassFromString(identifier) alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
return cell;
}
- (NSString*) getClassNameByViewModelCell:(id) viewmodel
{
NSString* identifier;
if ([viewmodel isKindOfClass:[RXBeginViewModelCell class]]) identifier = NSStringFromClass([RXBeginCell class]);
if ([viewmodel isKindOfClass:[RXMiddleViewModelCell class]]) identifier = NSStringFromClass([RXMiddleCell class]);
if ([viewmodel isKindOfClass:[RXEndViewModelCell class]]) identifier = NSStringFromClass([RXEndCell class]);
if (!identifier)
identifier = NSStringFromClass([viewmodel class]);
return identifier;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[self configureCell:cell atIndexPath:indexPath];
}
Implement this method -configureCell or add its code to your similar method.
- (void)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath *)indexPath
{
if ([cell isMemberOfClass:[RXBeginCell class]])
{
RXBeginCell* convertCell = (RXBeginCell*)cell;
if (![convertCell.vm_cell isEqual:[self.dataTableView objectAtIndex:indexPath.row]]){
convertCell.vm_cell = [self.dataTableView objectAtIndex:indexPath.row];
}
}
if ([cell isMemberOfClass:[RXMiddleCell class]])
{
RXMiddleCell* convertCell = (RXMiddleCell*)cell;
if (![convertCell.vm_cell isEqual:[self.dataTableView objectAtIndex:indexPath.row]]){
convertCell.vm_cell.actualCalculationsForWidth = 0;
convertCell.vm_cell.actualCalculationsForHeight = 0;
for (NSURLSessionDownloadTask* task in convertCell.vm_cell.arrConnection) {
[task cancel];
}
[convertCell.vm_cell.arrConnection removeAllObjects];
[convertCell cancelAllRequest];
convertCell.vm_cell = [self.dataTableView objectAtIndex:indexPath.row];
}
[convertCell.vm_cell.imageOperationQueue setSuspended:NO];
}
if ([cell isMemberOfClass:[RXEndCell class]])
{
RXEndCell* convertCell = (RXEndCell*)cell;
if (![convertCell.vm_cell isEqual:[self.dataTableView objectAtIndex:indexPath.row]]){
convertCell.vm_cell = [self.dataTableView objectAtIndex:indexPath.row];
}
[convertCell setupColors:convertCell.vm_cell andFrameSuperView:convertCell.contentView.frame andIndexInArray:0];
}
}
You're done ! Now you can start and see how it works. If you encounter errors, open the test project and copy the code from there
If you have any questions about the library. You can always look at the class diagram
[Watch class diagram in full resolution] (https://raw.githubusercontent.com/m1a7/RXProgressBar/master/Documentation/FinalDiagram-Full-Resolution.png)
P.S. To build these schemes, I use draw.io If you want to modify the scheme. You can take from the folder /Documentation file FinalDiagram.xml and open it with draw.io
- ❌ On older devices work with FLAnimatedImage doesn't look impressive. Idea for next version is to replace the FLAnimatedImage or to another library or to own.
- ☑️ To make a class diagram.
- ❌ Write wiki (in proccess)
m1a7, thisismymail03@gmail.com
RXProgressBar is available under the MIT license. See the LICENSE file for more info.