Problem having is that it start updating current page number after you turn 3 or 4 pages over then it start updating current page number starting from 1, 2, 3, 4,..... which is wrong. and if you start in reverse order turning page over lets suppose from 12 then it shows 13 and then from next page it starts updating current pagenumber in reverse order.
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
if (!completed) {
return;
}
if (currentIndex<totalPages -1 ){
[self displaycurrentIndex:currentIndex + 1];
}else if (currentIndex>totalPages + 1){
[self displaycurrentIndex:currentIndex - 1];
}
}
- (void) displaycurrentIndex:(NSUInteger)currentIndex {
self.navigationItem.title = [NSString stringWithFormat:
#"Page %i of %i",
currentIndex + 1,
CGPDFDocumentGetNumberOfPages(PDFDocument)];
}
Please help in how to fix this updating current page number from the beginning and also when going in reverse order.
Edit:
After removing
if (!completed) {
return;
}
Now it is Updating after turning first page over but now updates current page number from 0 of 20 and then 1 of 20 and so on but still when turning page over in reverse order it still updates current pagenumber in forward and then in reverse order.
Thanks for help.
From my experience (and also it is confirmed in the past WWDC session videos dedicated to this class) the best way to manage the page numbers in a UIPageViewController is to store as a property the page number information directly in the page view controller (that is in the view controller that contains the single page you want to show).
Then if you want to show a general purpose status bar with the page number, you simply fetch the viewControllers property of the UIPageViewController, which returns one or two view controllers depending on the UIPageViewController setup.
So in pseudo-code when the page view controller asks its data source which are the new view controllers to display your code:
- will get the current view controller(s)
- will fetch from it (them) the page number
- will calculate the next or prev page number(s) (depends on the page curl/swipe direction)
- will ask to the data source for the new calculated page numbers view controllers and will assign to their page number property the new value
In this way you are protected from strange animation behaviours and you don't need to keep in memory a global "currentIndex" which may lead to issues, as you experienced.
Related
I use this library: https://github.com/yuyakaido/CardStackView. It's like Tinder-like swiping cards left-right and it's based on RecyclerView.
This library has the following settings: cardStackLayoutManager.setVisibleCount(3) - that means that the number of visible cards at any time is MAXed to 3 cards.
Suppose I have an array with 5 elements, and then I load everything to my adapter.
On the screen, I'll see 3 cards - holding the first three elements from the array.
The Problem is that when I swipe the top card, (deleting it from the stack), then I have two cards left, but I'm expecting a new card appear at the bottom with the 4th element from the array, but it never happens unless I remove the first element from an array and then call: notifyDataSetChanged() which reloads the entire stack, adapter (and it comes up with blinking, flashing, etc.)
All I need is to load the NEXT element from the array in the new card at the bottom.
I figured this out. First, in Adapter, since I'm dealing with only 3 preloaded cards in stock at any time, I do this:
int countCards;
SwipeAdapter(ArrayList<String> userIDArr, Context ctx)
{
this.userIDArr2 = userIDArr;
.......
if (userIDArr2.size() >= 3) {
countCards = 3;
} else {
countCards = userIDArr2.size();
}
.......
this.ctx = ctx;
}
#Override
public int getItemCount() {
return countCards;
}
... that's provided that the total array userIDArr.size() might be more than 3 but getItemCount can only be MAX 3 or less (if the array size is less than 3).
Then, in an Activity that deals with an adapter, when I swipe the card whichever way, I remove index 0 (top card) from the array and then call notifyItemRemoved:
userIDArr.remove(0);
if (userIDArr.size() > 2) {
swipeAdapter.notifyItemRemoved(0);
}
NOTICE that notifyItemRemoved is only called when the array still has 3 or more items left.
Works perfectly smooth.
I have an old app where I have 5 tabs. Each tab have list of ads & there is details. Also each tab have respective add ad. Design for all 5 tabs is same except some changes, so I decided to use 1 screen only for all 5 tabs.
Now what I am doing is while add ad, I am checking which tab I am and based on tab bar index, I am showing hiding fields. Same is applicable for details screen also. Sample code is as shown below.
if (self.tabBarController.selectedIndex==0) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==1) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==2) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==3) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==4) {
field1.hidden = YES;
}
Now I have around 15 fields for each form so I write this code for all fields.
What I noticed that client change the tab bar position continuously so I was looking for efficient way of doing it.
Right now what I do is at all places manually change index positions by doing Search-Replace, however I dont like this.
I was looking for a way where instead of selectedIndex, I was looking for someconstant value that I will assign to tab item of tab bar, so my code will change as below
if (self.tabBarController.selectedIndex==adType_News) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==adType_Occasions) {
.
.
And so on...
This way, I only need to change in the storyboard and code level will not have any changes.
Is there way where I can achieve this?
Main Issue
As client ask to change tab bar completely, I need to make changes of selectedIndex changes at all places which I don't like and feel more in-efficient way. So I was looking for a way where I will make change in storyboard only and coding level there won't be any change.
The main issue for me is changing selectedIndex in all files which make more error.
I think I understand the question to mean that the code is full of number literals, referring to the selected index of the tabbar, and the business requirements about the ordering of items are shifting. Fix by changing the literals to something symbolic that can be controlled centrally:
// in a new file, indexes.h
#define INDEXA (0)
#define INDEXB (1)
#define INDEXC (2)
// wherever existing code refers to the tab selection
#import "indexes.h"
// in the code, for example if selectedIndex == 2, change to
if (self.tabBarController.selectedIndex==INDEXC) {
// ...
My app, using scrollview that loads multiple images with NSOperation (Max around 100sh). I tried to test it out on my ipod 2Gen and it crashes due to low memory on device, but works fine on ipod 4th Gen. On 2nd Gen, it crashes when it loads about 15-20 images. How should I handle this problem ?
You could load you images lazily. That means, e.g., just a couple of images at a time in your scroll view, so that you can animate to the next and the previous one; when you move to the right, e.g., you also load one more image; at the same time, you unload images that are not directly accessible anymore (e.g. those that have remained to the left).
You should make the number of preloaded image sufficiently high so that the user can scroll without waiting at any time; this also depends on how big those images are and where they come from (i.e., how long it takes to load them)... a good starting point would be, IMO, 5 images loaded at any time.
Here you will find a nice step by step tutorial.
EDIT:
Since the link above seems to be broken, here is the final code from that post:
-(void)scrollViewDidScroll:(UIScrollView *)myScrollView {
/**
* calculate the current page that is shown
* you can also use myScrollview.frame.size.height if your image is the exact size of your scrollview
*/
int currentPage = (myScrollView.contentOffset.y / currentImageSize.height);
// display the image and maybe +/-1 for a smoother scrolling
// but be sure to check if the image already exists, you can do this very easily using tags
if ( [myScrollView viewWithTag:(currentPage +1)] ) {
return;
}
else {
// view is missing, create it and set its tag to currentPage+1
}
/**
* using your paging numbers as tag, you can also clean the UIScrollView
* from no longer needed views to get your memory back
* remove all image views except -1 and +1 of the currently drawn page
*/
for ( int i = 0; i < currentPages; i++ ) {
if ( (i < (currentPage-1) || i > (currentPage+1)) && [myScrollView viewWithTag:(i+1)] ) {
[[myScrollView viewWithTag:(i+1)] removeFromSuperview];
}
}
}
My project needs to add and delete a uiwebview to uiscrollview at runtime. Means, when we scroll it horizontally (left or right) when paging is enabled, then a new view get added to the uiscrollview and it traverse to it.
Is it possible to detect the left or right scrolling in uiscrollview?
Plz tell me the best possible solution, sample code or any tutorial.
Thanks in advance
In such cases, we should have paging enabled in our scroll view.
Lets say you have scroll view of size 320x480, and it is supposed to show 10 pages, where size of each page is 320x480, making content size of scroll view as 320*10 x 480.
The best way to determine the current page is by using the content offset value of the scroll view.
So, in the beginning, when scrollview is showing 1st page, its content offset would be x=0, y=0.
For 2nd page x=320, y=0.
Thus we can get the current page value by dividing the contentOffset.x by page-width.
Thus, 0/320 = 0, means 1st page. 320/320 = 1, means 2nd page, and so on.
Thus, if we have current page value with us, we can determine in which direction the scroll view is moving, as follows:
-(void) scrollViewDidScroll:(UIScrollView *)scrollView{
int currentPageOffset = currentPage * PAGE_WIDTH;
if (self.pageScrollView.contentOffset.x >= currentPageOffset + PAGE_WIDTH) {
// Scroll in right direction. Reached the next page offset.
// Settings for loading the next page.
currentPage = self.pageScrollView.contentOffset.x/PAGE_WIDTH;
}else if (self.pageScrollView.contentOffset.x <= currentPageOffset - PAGE_WIDTH) {
// Scroll in left direction. Reached the previous page offset.
// Setting for loading the previous page.
currentPage = self.pageScrollView.contentOffset.x/PAGE_WIDTH;
}
}
I am new to programing so any help is appreciated. I am trying to find the method for the following. I need one button that will, when executed, perform a different task in a sequence when activated. For example the first time that the button is pressed, I would like it to act as if the user is confirming the information in the title of the button (i.e. confirms that the user is older than 45). The second time that the user presses the button it confirms the response in the negative (i.e. confirms the user is NOT older than 45). The third time the user presses the button the field is reset and no value has been assigned (i.e. it is as if the user never answered the question).
For real-estate purposes I would like the information in question to be the title of the button and update appropriately once the action has been captured. For example, if the action is positive the display is shown with a circle around the title. If the action results in a negative response, the title is shown with a line through it.
I have done quite a bit or reading to try to get a solution but no dice so far. I have tried overlaying a button on a label with the text of the label changing, but so far I am not having any luck
I can't imaging that this is a unique issue and any help is appreciated. Much thanks in advance.
On the event just have some code like this
Header
- (IBAction)buttonPressed:(id)sender{
static int counter;
if (counter == 0){
// do stuff for first time Example [sender setTitle:#"45"];
}else if (counter == 1){
// do stuff for second time Example [sender setTitle:#"-45"];
}else if (counter == 2){
// do stuff for the third time
}
counter += 1;
if (counter > 2){
// restart the counter
counter = 0;
}
}