IOS UICollectionView with ScrollView - ios

I have 6 images in my database.
I have created UIScrollView *scroll;, after that, I had created UICollectionView and added UICollectionView to UIScrollView
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(screenWidth*i,5,screenWidth ,self.scroll.frame.size.height-5) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:YES];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.showsVerticalScrollIndicator = NO;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[collectionView setBackgroundColor:[UIColor purpleColor]];
[self.scroll addSubview:collectionView];
And now, when scroll I want reload data of UICollectionView on below this code:
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
[getAllEmoji removeAllObjects];
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroll.frame.size.width;
int page = floor((self.scroll.contentOffset.x - pageWidth / 3) / pageWidth) + 1;
self.pageControl.currentPage = page;
//Change Emoji when scroll
NSString *str = [getAllCategory objectAtIndex:page];
NSArray *arr = [Emoji MR_findByAttribute:#"category" withValue:str];
if (arr.count > 0) {
for (int i = 0; i < arr.count; i++) {
Emoji *emoji = [arr objectAtIndex:i];
[getAllEmoji addObject:emoji.name_emoji];
}
[collectionView reloadData];
}
}
}
first pageControl is 2 images.
When I scroll to second pageControl is 2 images(But, it's don't load new image).
When I scroll to third pageControl is 2 images(it's load new image).
You can see some images in my project on below link:
http://imgur.com/a/nIMic
And my project demo.
https://github.com/VMTrinh/Sticker
Please help me!

I guess your problem is that you don't need to embed collection view in a scroll view.
The scroll mechanism is managed by the collection view.
You can scroll your collection with the scrollToItemAtIndexPath: method.

Related

Repeatedly representing the frame of the collectionView's cell causes memory growth?

I am working on a custom keyboard app and have encountered a difficult problem. I have inquired about some documents, but unfortunately did not find the answer. I want to ask everyone to help me.
The problem is this, when I type in the keyboard, the input results will be displayed in the candidate column.I use the UICollectionView to create the candidate column.
- (void)createCandideteColection {
if (!_collectionView) {
CGFloat height = self.frame.size.height-pinyinHeight-lineHeight;
CGFloat y = pinyinHeight+lineHeight;
CGFloat showButtonH = height;
CGFloat candidateShowWidth = self.frame.size.width - showButtonH;
UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flow.minimumInteritemSpacing = 20;
flow.minimumLineSpacing = 20;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, y, candidateShowWidth, height) collectionViewLayout:flow];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.dataSource = self;
_collectionView.delegate = self;
_collectionView.bounces = NO;
_collectionView.showsHorizontalScrollIndicator = NO;
[_collectionView registerClass:[GZCandidateCell class] forCellWithReuseIdentifier:#"candidateCell"];
[self addSubview:_collectionView];
}
}
Sets the frame of the cell, _data changes with the input (each time a text is entered, _data changes once, and [collectionView reloadData] is called once).The width of the cell changes with the number of characters entered.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
NSString *str = _data[indexPath.row];
CGFloat height = self.frame.size.height-pinyinHeight-lineHeight;
CGFloat width = str.length * 20 + 10;
return CGSizeMake(width, height);
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
GZCandidateCell *cell = (GZCandidateCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"candidateCell" forIndexPath:indexPath];
NSString *str = _data[indexPath.row];
[cell setTitleText:str];
return cell;
}
Assign titleLabel value, titleLabel size will be recalculate when calling [cell setTitleText:str].
when [collectionView removeFromSuperview] is called, collectionView will be destroyed,but there is little memory that cannot be released.Every time the input is completed and the collectionView is removed, some memory will not be released and will become a larger number after it is accumulated.
The reason why I will eventually locate this problem on the collectionView is because I don't create this collectionView, the memory does not grow.
Get input data and show on the collectionView,and tabBar is the candidate column I mentioned above:
if (!_textKeyboard) {
_textKeyboard = [[GZQwertyKeyboard alloc] initWithFrame:CGRectMake(0, navigaitonHeight, SCREEN_WIDTH, height) andKeyboardType:type];
_textKeyboard.backgroundColor = Color_background_kb;
[self.view addSubview:_textKeyboard];
}
__weak KeyboardViewController *weakSelf = self;
__weak GZQwerty *getdata = [GZQwerty defaultQwerty]; //init qwerty
_textKeyboard.sendSelectedStr = ^(NSString *text) {
if (!weakSelf.tabBar) {
[weakSelf addCandidateBarView];
}
int asciiCode = [text characterAtIndex:0];
[getdata sendInput:asciiCode complation:^(NSString *compontText, NSArray *candiateArray) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.tabBar changeShowText:candiateArray];
});
}];
};
Call [weakSelf addCandidateBarView] to create the tabBar.Call [weakSelf.tabBar changeShowText:candiateArray] to modify the data source of the collectionView and refresh the collectionView.Like this:
- (void)changeShowText:(NSArray*)textArr {
_data = textArr;
if (!_collectionView) {
[self createCandideteColection];
}
[_collectionView reloadData];
[_collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
When the keyboard is typed, if changeShowText: is not called, the memory is stable and there is no memory growth.
So, can anyone help me? Is there a better way than collectionView or how to avoid memory growth?Is it caused by repeated changes to the width of the cell?

UITableView viewForHeaderInSection Issue with UITableView content Inset

I'm working with a UITableView.
The table view has a HeaderView with a UIImageView that changes its height when the user scroll the table view.
In addition to this I also have a custom uiview for the section of the tableview .. My problem is that after setting the content Inset for the tableview, the section does not follow the scrolling of the table ..
Before Scroll
After Scroll
Surely it is a problem of content Inset, I did various tests but I could not find a solution ...
I would like the section of the tableView to follow the scroll and stop when it gets under the status bar (about 25 points of self.view.frame.origin.y)
Which path should I follow to solve my problem?
This is the code I am using
Register Xib for section header
- (void)viewDidLoad {
[super viewDidLoad];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellID];
[_tableView registerNib:[UINib nibWithNibName:#"DashboardTopHeader" bundle:nil] forHeaderFooterViewReuseIdentifier:dashboardTopHeader];
[self setupHeaderView];
}
Generate Section Header
#pragma mark - Dashboard Top Header
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
DashboardTopHeader *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:dashboardTopHeader];
return header;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 100;
}
Setup the Header View of TableView With Photo
-(void)setupHeaderView {
_headerView = [[UIView alloc] init];
_headerView = self.tableView.tableHeaderView;
_tableView.tableHeaderView = nil;
[_tableView addSubview:_headerView];
// 130 is Height of headerView
CGFloat newHeight = 130 - 50 /2;
_tableView.contentOffset = CGPointMake(0, -newHeight);
_tableView.contentInset = UIEdgeInsetsMake(newHeight, 0, 0, 0 );
[self updateHeaderView];
}
-(void)updateHeaderView {
CGFloat newHeight = 130 - 50 /2;
CGRect headerFrame = CGRectMake(0, -newHeight, self.tableView.frame.size.width, 130);
if (self.tableView.contentOffset.y < newHeight) {
headerFrame.origin.y = self.tableView.contentOffset.y;
headerFrame.size.height = - self.tableView.contentOffset.y + 50/2;
}
_headerView.frame = headerFrame;
}
Use TableView Delegate for scroll Content
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self updateHeaderView];
}

Multiple UiCollectionview Reload issue

I have created multiple UICollectionView programmatically and I have set values dynamically working fine. I want update now 3 UICollectionView only. How to reload it.
Below I attached my code:
for (int i=0; i<4; i++) {
CGFloat x =0;
CGFloat viewWidth = CGRectGetWidth(self.view.frame);
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
collectionview =[[UICollectionView alloc] initWithFrame:CGRectMake(0,0, viewWidth, 160) collectionViewLayout:layout];
collectionview.backgroundColor=[UIColor clearColor];
collectionview.tag=i;
[collectionview setTag:i];
[collectionview registerNib:[UINib nibWithNibName:#“Cell” bundle:nil] forCellWithReuseIdentifier:#“Cell”];
collectionview.delegate=self;
collectionview.dataSource=self;
[self.view addSubview:collectionview];
x=x+viewWidth;
}
Get collectionView using viewWithTag.
UICollectionView *Collection = (UICollectionView *)[self.view viewWithTag:3];
Then, just reload the data or do whatever:
[Collection reloadData];

Create Multi UICollectionView in a ViewController

Title is my problem.
I had created UICollectionView in for loop. So, it's created some UICollectionView
My code:
for (int i = 0; i < getAllCategory.count; i ++) {
CGRect frame;
frame.origin.x = self.scroll.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scroll.frame.size;
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(screenWidth*i,5,screenWidth ,self.scroll.frame.size.height-5) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:YES];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.showsVerticalScrollIndicator = NO;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[collectionView setBackgroundColor:[UIColor purpleColor]];
[self.scroll addSubview:collectionView];
}
So, When I scroll to new UICollectionView to show new image, it's not show new image. Because, it's reload data for last UICollectionView.
My code when show new image.
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
[getAllEmoji removeAllObjects];
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroll.frame.size.width;
int page = floor((self.scroll.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
//Change Emoji when scroll
NSString *str = [getAllCategory objectAtIndex:page];
NSArray *arr = [Emoji MR_findByAttribute:#"category" withValue:str];
if (arr.count > 0) {
for (int i = 0; i < arr.count; i++) {
Emoji *emoji = [arr objectAtIndex:i];
[getAllEmoji addObject:emoji.name_emoji];
}
[collectionView reloadData];
}
}
}
So, it's only show old image for all UICollectionView, it's only change image for last UICollectionView
How to I can resolve this problem.
Here is link to you see some images my problem
http://imgur.com/a/nIMic
Please help me!
************************** I had resolved my problem *******************
Add code
#property (strong, nonatomic) NSMutableArray *collectionArray;
self.collectionArray = [[NSMutableArray alloc]init];
[self.collectionArray addObject:collectionView];
[self.collectionArray[page] reloadData];
Your code just handles a collectionView (the last collection).
You should create a property to hold these collectionView: NSMutableArray * arrCollectionView
for (int i = 0; i < getAllCategory.count; i ++) {
CGRect frame;
frame.origin.x = self.scroll.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scroll.frame.size;
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
UICollectionView * collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(screenWidth*i,5,screenWidth ,self.scroll.frame.size.height-5) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:YES];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.showsVerticalScrollIndicator = NO;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[collectionView setBackgroundColor:[UIColor purpleColor]];
[self.scroll addSubview:collectionView];
[arrCollectionView addObject: collectionView];
}
Then in scrollViewDidScroll
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
[getAllEmoji removeAllObjects];
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroll.frame.size.width;
int page = floor((self.scroll.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
//Change Emoji when scroll
NSString *str = [getAllCategory objectAtIndex:page];
NSArray *arr = [Emoji MR_findByAttribute:#"category" withValue:str];
if (arr.count > 0) {
for (int i = 0; i < arr.count; i++) {
Emoji *emoji = [arr objectAtIndex:i];
[getAllEmoji addObject:emoji.name_emoji];
}
//[collectionView reloadData];
for (UICollectionView * collectionView in arrCollectionView) {
if (collectionView == sender) {
[collectionView reloadData];
break;
}
}
}
}
}
Please thinking your design model, you can separate the UICollectionView in different Class, every pointer to object by self, create different array and datasource for load.

Can I put a page view controller within a table view cell?

I'm wondering if I could put a page view within a table view cell. Basically I'm trying to get each table view cell to be able to scroll left/right for more content.
Can I do it by putting a page view within a table view cell? Or is there another way to be able to swipe left/right in a table view cell?
It's possible to load another view controller and add its view as a subview of another controller's view.
Although it's not recommended by Apple's guidelines:
Each custom view controller object you create is responsible for
managing all of the views in a single view hierarchy. [...] The
one-to-one correspondence between a view controller and the views in
its view hierarchy is the key design consideration. You should not use
multiple custom view controllers to manage different portions of the
same view hierarchy.
More info on the guidelines click here
A better way to do it is using a UIScrollView and a UIPageControl like this…
cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSArray *photo = [NSArray arrayWithObjects:[UIImage imageNamed:#"image1.png"], [UIImage imageNamed:#"image2.png"], [UIImage imageNamed:#"image3.png"], nil];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 150)];
self.scrollView.backgroundColor = [UIColor clearColor];
self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleBlack; //Scroll bar style
self.scrollView.showsHorizontalScrollIndicator = NO;
[self.scrollView setDelegate:self];
//Show horizontal scroll bar
self.scrollView.showsVerticalScrollIndicator = YES; //Close vertical scroll bar
self.scrollView.bounces = YES; //Cancel rebound effect
self.scrollView.pagingEnabled = YES; //Flat screen
self.scrollView.contentSize = CGSizeMake(640, 30);
NSLog(#"LOG");
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 155, 320, 40)];
self.pageControl.numberOfPages = photo.count;
self.pageControl.currentPage = 0;
self.pageControl.backgroundColor = [UIColor redColor];
[self.pageControl setTintColor:[UIColor whiteColor]];
[cell.contentView addSubview:self.pageControl];
for(int i = 0; i < photo.count; i++)
{
CGRect frame;
frame.origin.x = (self.scrollView.frame.size.width *i) + 10;
frame.origin.y = 0;
frame.size = CGSizeMake(self.scrollView.frame.size.width - 20, self.scrollView.frame.size.height);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
[imageView setImage:[photo objectAtIndex:i]];
[self.scrollView addSubview:imageView];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width*photo.count, self.scrollView.frame.size.height);
}
[cell.contentView addSubview:self.scrollView];
return cell;
}
update PageControl
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = scrollView.frame.size.width;
//int page = floor((scrollView.contentOffset.x - pageWidth*0.3) / pageWidth) + 1);
self.pageControl.currentPage = (int)scrollView.contentOffset.x / (int)pageWidth;
NSLog(#"CURRENT PAGE %d", self.pageControl.currentPage);
}
Yes, you can.
However, be aware that you can't get rid of the black background to the page control in it if you choose to go that route. I did this a couple days ago but ended up getting rid of the page view controller in favor of using a UIScrollView that has paging enabled and a UIPageControl. I use the -scrollViewWillEndDragging:withVelocity:targetContentOffset: scroll view delegate method to determine when to determine the currentPage in the page control.
If you're going to have quite a few views in the scroll view, it would be more memory efficient to use a collection view instead of a normal scroll view.
Instead of using a UIPageview, try to put another UITableview (rotated by 90 degrees in anticlockwise direction)inside a cell. This will give you more control over touch events and more customization too.
1) Have a class for UITableViewCell and an xib file too, say PageViewTableCell
2) Xib file should have a UITableView inside the cell
3) Rotate the table when awakeFromNib is called
- (void)awakeFromNib
{
horizontalTable.transform = CGAffineTransformMakeRotation(-M_PI_2);
horizontalTable.frame = CGRectMake(0,0,horizontalTable.frame.size.width,horizontalTable.frame.size.height);
}
4) Have the delegate and datasource for horizontalTable according to your design.
5) Load the main table which has the above customized cell
- (void)viewDidLoad
{
[self.mainTable registerNib:[UINib nibWithNibName:#"PageViewTableCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:#"samplecell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PageViewTableCell* cell = [tableView dequeueReusableCellWithIdentifier:#"samplecell"];
return cell;
}

Resources