I'm using the Android version of PDFNet 6.5.0.
I need to set the vertical scroll of the PDFViewCtrl to an absolute point in the pdf, expressed in PDF Canvas coordinates.
For example, say that I want to zoom to the middle of the second page.
I could get the y coordinate, in PDF Canvas position like:
int y = doc.getPage(1).getPageHeight() + (doc.getPage(2).getPageHeight() / 2)
How could I scroll to the y position?
I'm trying to do it with PDFViewCtrl#setVScrollPos(), but I don't know how to convert y to a valid parameter for this method.
Have you tried to use PDFViewCtrl#scrollTo(int, int)?
i.e. first convert points from PDF space to canvas space(PDFViewCtrl#convPagePtToCanvasPt), then scrollTo the position.
Although I have accepted Shirley G's answer I am posting this other answer for clarification.
The tricky bit is which number to pass as parameter to PDFViewCtrl#setVScrollPos(int) or PDFViewCtrl#scrollTo(int, int)
You need to use PDFViewCtrl#convPagePtToScreenPt() to convert the page position into a physical screen point.
But you also need to take into account the current scroll offset of the scroll view pdfViewCtrl#getVScrollPos()
So, given you want to scroll to verticalPosition in page:
public void scrollToDocPosition( final int verticalPosition, final int page) {
double[] screenPos = pdfViewCtrl.convPagePtToScreenPt(0, verticalPosition, page);
pdfViewCtrl.setVScrollPos((int) screenPos[1] + pdfViewCtrl.getVScrollPos());
}
I came to this thanks to https://groups.google.com/forum/?fromgroups#!searchin/pdfnet-sdk/scroll/pdfnet-sdk/7Wy00goWfyQ/t1tvApNDrr8J, where Thomas Hoffman explains:
The first thing to look at is the scroll position. y after
converting is in screen space, while SetX/YScrollPos is in the
coordinates of the scroll viewer. That is, the top left corner of the
PDFViewCtrl is at position (0, 0) in screen space, but at position
(GetHScrollPos and GetVScrollPos) in scroll coordinates
Related
I am using the MPAndroidChart library to graph live sensor data in a line graph. I'm hoping to give the data a sort of 'buffer' on the right-hand end so that new data is in the centre of the screen. I've tried to illustrate what I mean below:
Basically, I have got it so the ViewPort scrolls and shows the most recent item in the right-most end of the screen, but I would like it in the centre. Thanks!
you need to set Xaxis maximum, set visibleXrange and last move the viewport
double range = 5; // how many data you want to show in view port
double maxX = 100; // your highest X value
chartView.getXAxis().setAxisMaximum(maxX + range/2);
chartView.setVisibleXRange(range, range);
chartView.moveViewToX(maxX);
chartView.notifyDataSetChanged();
Suppose I have six points drawn in a Canvas along the circumference of a circle, in the pattern of a hexagon.
I want to simultaneously move and re-draw each of these six points in a small circular path - for example, each point moves along the circumference of a circle with 1/10th the radius of the larger circle.
I'm a little lost on how to do this with Canvas and onDraw and I don't know if better solutions exist. How would you do this?
Some answers have at least pointed me toward this which shows how a point might move along a circular path, but I don't know how to implement it for this situation:
for (double t = 0; t < 2*Pi; t += 0.01)
{
x = R*cos(t) + x_0;
y = R*sin(t) + y_0;
}
Thank you!
Here's one approach:
Start with a custom view that extends View and overrides onDraw. You are on the right track with using the drawing functions of Canvas.
Give your custom view a field to hold the current angle:
private float mTheta;
Then add a method like:
public void setTheta(float radians) {
mTheta = radians;
invalidate();
}
Then in onDraw, use the current value of mTheta to calculate the position of your points.
Of course, with the custom view you might need to handle sizing with an onMeasure override and possibly some layout with an onLayout override. If you set the dimensions of the view to an absolute dp value, the default behavior should work for you.
Doing it this way will set you up to override onTouch and allow user interaction to move the graphics, or use a ValueAnimator to cycle from 0 to 2π calling setTheta from within your AnimatorUpdateListener.
Put some code together and when you get stuck, post another question. If you add a comment to this answer with a link to the new question, I'll take a look at it.
I have a 600x1000 pixel screen and my player starts near the bottom left. His x and y coordinates are (50, 900). I'm drawing this player to a canvas and using
canvas.translate(-player.getX()+GAMEWIDTH/2, 0)
to make sure the player stays in the middle of the screen with respect to the x-axis. This results in my player being rendered at (300, 900), however the player's x and y coordinates remain at (50, 900). This presents an issue because I need the player's coordinates to be the same as his rendered location because I use touch events on the player's collision rectangles to move him around. Is there any way to make my screen's coordinates be relative to my canvas coordinates so that my player's coordinates correspond to where they actually get rendered? Or is there maybe another way to do it?
The touchEvents are always based on the the x & y relative to the canvas element itself. Since the view is centering the character by translating the view canvas.translate(-player.getX() + GAMEWIDTH/2 , 0); you need to also apply that translation to the touchEvent. You can do it in the touch handler itself, or you could store both a relative and absolute position for the items in your game world. This will become more important if items become nested in one another. This is typically done by storing the parent element of a sprite/object.
//example of how I usually handle object hierarchy
this._x = this.x + this.parent._x;
this._y = this.y + this.parent._y;
the canvas/stage would also store it's center as a ._x and ._y which would be the parent of the the objects added, this way when you generate the global position to do your touchEvents against instead of passing in the .x or .y you would pass in the ._x and ._y which are already translated by the GAMEWIDTH/2.
I need to apply click/touch events for only visible part of the View. Say for example a image of size 200X200. Apart from center 50X50, remaining part is transparent. I want to get touch events only for that 50X50 visible part Not on remaining transparent part.
In above image (its single image), only inner Diamond has got visible part. Apart from that Diamond is transparent area. So, if I touch Diamond then only I want to do something else ignore.
Edit :
Rachita's link helped me. I gone through that link and got idea how can I implement. But I could not understand some constants like 320, 240 etc while creating Points. In my case, I know the Diamond (in above image) x and y Ponits (hard coded values asctually). So, using those how can I determine, whether I touched inside Diamond or outside?
my Diamond points are as below
pointA = new Point(0, 183);
pointB = new Point(183, 0);
pointC = new Point(366, 183);
pointD = new Point(183, 366);
Edit :
Finally got solution from Luksprog. Its based on checking touched point pixel color. If color is 0 means, you touched transparent layer else you touched some colored part of the image. Simple, but very effective. Have a look at it here.
AFAIK you can not implement this with onclick listener or my any other direct way .You will have to use onTouchListener .
Firstly set your view dynamically at a specific (x,y) position using this How can I dynamically set the position of view in Android?
Calculate the region your diamond will occupy (you should khow the size of image inorder to calculate area of diamond)
3.Trigger a action in onTouchListener only when x, y fall in the required region. Use How to get the Touch position in android?
check this link to calculate if a given point lies in the required square
EDIT
To understand the coordinate system of android refer to this link How do android screen coordinates work?
Display mdisp = getWindowManager().getDefaultDisplay();
int maxX= mdisp.getWidth();
int maxY= mdisp.getHeight();
(x,y) :-
1) (0,0) is top left corner.
2) (maxX,0) is top right corner
3) (0,maxY) is bottom left corner
4) (maxX,maxY) is bottom right corner
here maxX and maxY are screen maximum height and width in pixels, which we have retrieved in above given code.
Remember if you want to support multiple devices with different screen sizes,make sure you use a relative value for x,y ie some ratio of screen height or width ,as different devices have different ppi
Check if touched point lies in the required polygon
I thinks these link might help you determining if the point touched (you can get x,y from onTouch event eg.event.getX()) lies in the required polygon whose points you have mentioned in the question . determine if a given point is inside the polygon and How can I determine whether a 2D Point is within a Polygon?
I am trying to animate cards across the screen.
My code looks like this:
private void animate(ImageView animationSource, ImageView animationTarget, int animationDuration, int animationDelay) {
int[] animationSourcePosition = {0,0};
int[] animationTargetPosition = {0,0};
animationSource.getLocationInWindow(animationSourcePosition);
animationTarget.getLocationInWindow(animationTargetPosition);
TranslateAnimation cardDealingAnimation = new TranslateAnimation(
Animation.ABSOLUTE,animationSourcePosition[0],
Animation.ABSOLUTE,animationTargetPosition[0],
Animation.ABSOLUTE,animationSourcePosition[1],
Animation.ABSOLUTE,animationTargetPosition[1]);
cardDealingAnimation.setDuration(animationDuration);
cardDealingAnimation.setStartOffset(animationDelay);
animationTarget.startAnimation(cardDealingAnimation);
}
What happens is that it just pops up in the new place without showing the places in-between.
Funnily enough, on one of my targets it does sometimes show up.
There are two problems I see here.
One problem is that you're getting the position of your objects in the Window, where you should just use the position of the objects in their parent container. It's easier, faster, and more what you're looking for - where the objects live in their layout. If they do not live in the same container, then you may need to get the position in the window or the screen, and then just deal with delta values (the difference in their locations, not the absolute locations themselves).
You can get these simple container positions from the getLeft() and getTop() methods on View.
The second problem is that the TranslateAnimation parameters don't do what you think they do. The numeric values (the second, fourth, sixth, and eighth values) specify the starting and ending locations of the target object as offsets from its current location. That's why they have the word 'delta' in them in the method declaration. So you should not send in the absolute coordinates of the object positions their, but, rather, the deltas that they should have.
Let's suppose you have calculated an xDelta and yDelta as the difference in x and y between the source and target positions. If you're animating the source to the target position, then you would use something like 0, xDelta, 0, yDelta for these values.
Note that TranslateAnimation() does not physically move the object - it just draws it in a different place. So as soon as the animation is complete, the object will snap back to its original location. You may want to set the fillAfter property to maintain its end location on the screen when the animation completes.