Image sorting bug in Scrollview - iPad application - iphone

We are building a catalog app that has 2 rows of sorted images with varying widths but same height. We draw the artwork on scrollview in sorted order (from A to Z) As per attached image.
We search using a alphabetically ordered bar on top that has letters (A to Z) If i touch on letter J the i want the artwork which starts from j comes first. The code we are using is not working well. E.g. clicking on J takes us to A. Will greatly appreciate your help or advice.
Code is as follows:
NSString *newStr = [currentArtworkTitle substringWithRange:NSMakeRange(0,1)];
if([newStr isEqualToString:self.searchString])
if (scrollViewTopRowWidth > scrollViewBottomRowWidth) {
xCordForSortedView = scrollViewTopRowWidth - c - imgForButton.size.width;//self.touchLengthCount;//50 ;// -10//c scrollViewBottomRowWidth
}
else {
xCordForSortedView = scrollViewBottomRowWidth - c - imgForButton.size.width;// self.touchLengthCount;//40;//scrollViewTopRowWidth
}
// For shifting the screen
if(scrollViewTopRowWidth > scrollViewBottomRowWidth){
int tmpMargin = scrollViewTopRowWidth - xCordForSortedView;
if(tmpMargin < 1024)
scrollView.contentSize = CGSizeMake(scrollViewTopRowWidth+1024,scrollView.bounds.size.height);
}
else{
int tmpMargin = scrollViewBottomRowWidth - xCordForSortedView;
if(tmpMargin < 1024)
scrollView.contentSize = CGSizeMake(scrollViewBottomRowWidth+1024,scrollView.bounds.size.height);
}
[scrollView scrollRectToVisible:CGRectMake(xCordForSortedView, 0,scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];

I won't edit your code but I can give you a hint.
Look, when you populate the scrollwiew, by adding an imageview, add also an entry into a NSMutableDictionary (instance variable), so the key will be the A-Z letter, and the value will be the x position of the image. When you finish populating the scrollview, you will have also the dictionary containing the position of all your images (and you need only the x) and the corresponding letter. Now you tap "J" and hit "Search" - you parse your dictionary to fing the object with the key "J" and read it's value. Use this (x) value to set your srollview's contentOffset. Tada!

Related

iTextSharp v. 5.5.3 to 5.5.6 - error flattening TextField

I have a problem. I using iTextSharp v. (5.5.3 to 5.5.6).
I have one file PDF and 1 page.
On the side I have 4 TextField (rotation: 0, 90, 180, 270) and one red polygon
My page rotation is set 270
I can flatten page
In code, I set
stamper.AnnotationFlattening = true;
stamper.FormFlattening = true;
After flattening my 2 TextField are rotated incorrectly
Image 1 of the original PDF:
Image 2 with error:
The PDF:
http://www.pdf-archive.com/2015/08/20/wyslac/
There is an issue in iText(Sharp) when flattening form fields with existing appearances rotated by means of their Matrix attribute if pdfStamper.AcroFields.GenerateAppearances is true.
The original
after flattening with GenerateAppearances == true looks like this:
Workaround
As the document already has appearance streams, you can switch off GenerateAppearances:
stamper.AcroFields.GenerateAppearances = false;
stamper.AnnotationFlattening = true;
stamper.FormFlattening = true;
The result you get now:
The issue
If GenerateAppearances == true, then iTextSharp (when flattening forms) first looks whether a field already has an appearance. If the field has one, iTextSharp only attempts to neatly fit the existing appearance into the rectangle of the form field. Unfortunately it (a) ignores the existing form field Matrix entry and (b) replaces it with a new matrix doing the fitting. If the appearance was rotated by means of its Matrix, that rotation is lost and instead the value is stretched to fit into the falsely oriented rectangle.
if (acroFields.GenerateAppearances) {
if (appDic == null || as_n == null) {
[...]
} else if (as_n.IsStream()) {
PdfStream stream = (PdfStream) as_n;
PdfArray bbox = stream.GetAsArray(PdfName.BBOX);
PdfArray rect = merged.GetAsArray(PdfName.RECT);
if (bbox != null && rect != null) {
float rectWidth = rect.GetAsNumber(2).FloatValue - rect.GetAsNumber(0).FloatValue;
float bboxWidth = bbox.GetAsNumber(2).FloatValue - bbox.GetAsNumber(0).FloatValue;
float rectHeight = rect.GetAsNumber(3).FloatValue - rect.GetAsNumber(1).FloatValue;
float bboxHeight = bbox.GetAsNumber(3).FloatValue - bbox.GetAsNumber(1).FloatValue;
float widthCoef = Math.Abs(bboxWidth != 0 ? rectWidth / bboxWidth : float.MaxValue);
float heightCoef = Math.Abs(bboxHeight != 0 ? rectHeight / bboxHeight : float.MaxValue);
if (widthCoef != 1 || heightCoef != 1)
{
NumberArray array = new NumberArray(widthCoef, 0, 0, heightCoef, 0, 0);
stream.Put(PdfName.MATRIX, array);
MarkUsed(stream);
}
}
}
}
(PdfStamperImp method FlatFields)
The background
The reason why iTextSharp ignores the appearance Matrix is that appearance generation in the course of form filling is not supposed to use such matrix values:
For non-rich text fields, the appearance stream—which, like all appearance streams, is a form XObject—has the contents of its form dictionary initialized as follows:
The resource dictionary (Resources) shall be created using resources from the interactive form dictionary’s DR entry (see Table 218).
The lower-left corner of the bounding box (BBox) is set to coordinates (0, 0) in the form coordinate system. The box’s top and right coordinates are taken from the dimensions of the annotation rectangle (the Rect entry in the widget annotation dictionary).
All other entries in the appearance stream’s form dictionary are set to their default values (see 8.10, “Form XObjects”).
(section 12.7.3.3 "Variable Text" of ISO 32000-1)
This means for the Matrix:
Matrix array (Optional) An array of six numbers specifying the form matrix, which maps form space into user space (see 8.3.4, "Transformation Matrices"). Default value: the identity matrix [1 0 0 1 0 0].
(Table 95 – Additional Entries Specific to a Type 1 Form Dictionary - in section 8.10.2 "Form Dictionaries", ibidem)
Thus, form field appearance streams created during fill-in according to the specification, can be assumed to have a an identity Matrix value, and no rotation.
So the issue in iTextSharp actually merely reflects the assumption that form field appearances are generated due to form fill-in.

Relative UILabel in a game object

I created a game object which acts as a repeating item for a UIGrid which I populate dynamically. The gameobject (RowItem) has couple of UILabel whose text can change on runtime depending on the content. The content of these UILabels overlap when the text is bigger. Can anybody help me in how to make UILabel expand relative to the adjacent UILabel when the text is more/less?
You can use transform.localScale property of the UILabel's property to scale it. Just make them bigger when the text is bigger than let's say 20 characters. Try with arbitrary values.
Also when you change the scale, run a re-align method, which aligns other labels so that they don't overlap.
you can get the text length in pixel by this:
UILabel label;
float width = label.relativeSize.x * label.transform.localScale.x;
float height = label.relativeSize.y * label.transform.localScale.y;
Let's say that you want to set you max length to 100, you can do this:
if (width > 100)
{
label.localScale = new Vector3(100 / label.relativeSize.x, 100/ label.relativeSize.x, 1);
}
the second param for Vector3 is also based on relativeSize.x is not a typo, that makes sure your text will not become thin.
Hope this works.

Differentiating between dynamically generated buttons

I have ten options on a view controller, each of which 'pushes' to the same new view controller displaying a specific amount of buttons (for each option a different amount of buttons may be available, ranging from 3 buttons through to 15). Currently, my code is performing similarily to the answer posted on this question.
All these buttons are created dynamically (the amount obviously depending on the length of the array) for each option using a for-loop:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if(option 1) {
Array contains different values...
}
if(option 2) {
Array contains different values...
}
etc...
for(int i = 0; i < xCoordinatePosition.count; i++) {
UIButton *imageOne = [UIButton buttonWithType:UIButtonTypeCustom];
[imageOne setTag:i];
[imageOne addTarget:self action:#selector(webViewChanged:) forControlEvents:UIControlEventTouchUpInside];
}
}
As you can see I've set a tag for each button to differentiate between the dynamically created buttons, as I want each one to display a different UIWebView when selected.
When I've selected an option and NSLog the resulting tags of each button on a results page, I get the reply I'm after: 1, 2, 3 etc.
- (IBAction)webViewChanged:(UIButton*)sender
{
NSLog(#"%d", sender.tag);
}
The problem is, I want a unique number for each button in regard to ALL option buttons - currently each of my ten options returns with buttons that have the tags 1, 2, 3 etc. up to ten, whereas I need the first option return with 1-10, the second option return with 11-20 etc, as each individual button will be returning something unique.
For example:
Clicking the button with the tag of 7 on one option will bring up a completely different web-view to clicking on a button with the tag of 7 on another, therefore I need to make a distinction between every button.
Does anyone know how I could set the tag so that is unique for each option (instead of just setting each button of the currently chosen option to be unique like it does currently)?
Just use another integerVariable which have the values multiple of 10.
int factor;
if(option 1)
{
factor = 0;
}
if(option 2)
{
factor = 10;
}
etc..
Then put tag as,
[imageOne setTag:i+factor];
If I understood your question correctly, one way to solve the problem can be to set a base tag for each option like 100, 200, ...
So, in your prepareForSegue:
int baseTag;
if(option 1) {
// Array contains different values...
baseTag = 100;
}
if(option 2) {
// Array contains different values...
baseTag = 200;
}
// etc...
And in the for loop, simply:
[imageOne setTag: baseTag + i];
For option 1, your image tags will start from 101, and for option 2, from 201, etc.

iOS draw the table in pdf document

I will create the pdf from the contents of UIViewController.
When UIViewController has a table region(the same as Excel), I didn't find the method for drawing an table in pdf document.
Does anyone know to solve this problem? Please help me.
There is no easy method of creating a table I know of if you're using a Quartz graphics context (CGContextRef type). I was able to create a table programmatically by drawing lines on the PDF in nested for loops, and by paying careful attention to spacing to make it look right.
Psuedo-code:
for (int i=0; i < numberOfRows; i++)
{
// display each row
// Draw row line
CGPoint horizontalRowDivider[2] = {CGPointMake(x_startPoint, y_startPoint + (i * row_width)), CGPointMake(x_endPoint, y_endPoint + (i * row_width))};
CGContextStrokeLineSegments(pdfContext, newlineItemDivider, 2);
for(int j = 0; j < numberOfColumns; j++)
{
//Draw each column cell
const char *desc_text = "Table value"
CGContextShowTextAtPoint (pdfContext, x_cellDataLoc, y_cellDataLoc, desc_text, strlen(desc_text));
CGPoint verticalLineCellDivider[2] = {CGPointMake(x_startPoint + (j * col_width), y_startPoint), CGPointMake(x_endPoint + (j * col_width), y_endPoint)};
CGContextStrokeLineSegments(pdfContext, verticalLineCellDivider, 2);
}
}
This is a rough example of the kind of logic you might use to draw a table. You'll probably want a rectangle, or a border, around your table to make it look right, among any other kinds of tweaks to make it how you want. You can find the list of methods on how to do that and more through the below link. I know this probably isn't what you had in mind, but I hope this gives you some direction to take if you were totally stuck. Good luck!
You can find the full library of functions available for drawing PDFs in Apple's documentation: http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html

How to scroll a GWT TextArea?

I am calling com.google.gwt.user.client.ui.TextArea.setText(myText) to set the content. After that I call setCursorPosition(myText.length()) to get the cursor to the end. This works well.
When myText has more lines then the text area can display at once, it shows a scroll bar. But it does not scroll to the cursor position. Even worse - it scrolls to the top.
How can I scroll the GWT TextArea to the cursor position? I realy need the cursor position, not the bottom of the TextArea. A JSNI workaround would be ok too.
Try adding this after setting the cursor position:
textAreaToScroll.getElement().setScrollTop(textAreaToScroll.getElement().getScrollHeight());
This will scroll the element to the bottom.
EDIT:
To scroll to the any cursor position there is (as far as I know) no easy way to do so. I don't think there is any way to ask the browser wich line the cursor is on.
I just got an idea for something that may work (haven't actually tested it) to guess a rough estimate of how long to scroll.
int cursorPos = textAreaToScroll.getCursorPos();
long offsetRatio = cursorPos / textAreaToScroll.getText().length();
//gives 0.0 to 1.0
offsetRatio += someMagicNumber; // -0.1 maybe?
// Depending on the font you may need to adjust the magic number
// to adjust the ratio if it scrolls to far or to short.
offsetRatio = offsetRatio>0.0 ? offsetRatio : 0; //make sure
//we don't get negative ratios
//(negative values may crash some browsers while others ignore it)
textAreaToScroll.getElement().setScrollTop(
textAreaToScroll.getElement().getScrollHeight() * offsetRatio );
This may scroll the roughly the desired distance. Note, this assumes each line is filled about the same amount since it uses the cursor position divided by the length of the text and not the number of lines (wich is hard to calculate). Manual newlines will skew this estimate, and proportional fonts will allso make it less accurate.
You'll probably need to adjust the ratio so that it scrolls sligtly too short rather than too far since the cursor will still be visible if it's slightly below the top of the text area.
As I said I haven't actually tested this, I may have inverted the logic and other subtle bugs.
I had a scenario where the textarea will already have something and when a new command is submitted it will add the data to it and scroll to the start of the newly added data. this is what I did
// Hold the previous height to set the scroll.
final int prevHeight = document.get().getElementById(textareadid).getScrollHeight();
// Hold the prev position if output area already has some data.
final int prevPos = this.textArea.getValue() != null ?
this.textArea.getValue().length() : 0;
after processing and setting the new data
int posCount = 0;
if (previousResponse != null && !previousResponse.isEmpty())
{
final String dataStr = "new data from process";
// add 15 lines for the cursor position
posCount = getRelativeCount(dataStr);
}
this.textArea.getElement().setScrollTop(prevHeight);
this.textArea.setCursorPos(prevPos + posCount);
private int getRelativeCount(final String str)
{
int charCount = 0;
if (str != null)
{
int NUM_ROWS = 15;
if (getUserAgent().contains("msie"))
{
NUM_ROWS = 16;
}
final String[] splitArr = str.split("\n"); // split on the new line
// char
for (int index = 0; index < splitArr.length && index < NUM_ROWS; index++)
{
charCount += splitArr[index].length();
}
}
return charCount;
}
To improve on Stein's answer, you can count the number of lines in the text, and then set the top position based on the desired line over the total lines, rather than using characters.
While you are counting lines, you will also have to determine which line the cursor is in.
String text = textArea.getText();
int lines = 1;
int pos = 0;
int cursorPos = ...;
int cursorLine = -1;
while((pos = 1+text.indexOf("\n", pos)) > 0)
{
if (cursorLine == -1 && pos > cursorPos)
cursorLine = lines;
lines++;
}
if (lines > 0 && cursorLine > 0 && cursorLine < lines)
{
int scroll = textArea.getElement().getScrollHeight();
scroll *= cursorLine;
scroll /= lines;
scroll -= 30; // Back up a bit so it's not right at the top
if (scroll < 0)
scroll = 0;
textArea.getElement().setScrollTop(scroll);
}
this worked for me:
GWT textArea Scroll issue
http://www.gwtplayground.com/2012/08/gwt-textarea-scroll-issue_21.html