Is there a way to manually scale a view while making sure the position translates properly? The only way I can scale it right now is to update the LayoutParams by essentially multiplying the width and height my a scale factor. This works okay but I'm not sure about how to translate the position properly. Further, I want to scale the view with the pivot being the center as well. I'm actually able to perform the behavior I want with by using the ScaleAnimation like so,
ScaleAnimation anim = new ScaleAnimation(fromX, toX,
fromY, toY, ScaleAnimation.RELATIVE_TO_SELF,
0.5f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
However, the actual view's bounds are not adjusted. The majority of scaling implementations and help always deal with an ImageView so I figured it's worth asking for a View only. I'd be greatly appreciative if any has any ideas on this matter.
It sounds like you want to scale a View, but scale it from the center of the View. This is tricky because the View is positioned based on it's top and left offset from the top left corner of it's parent.
So -- if you have a view that is 100px from the top, and 100px from the left, and the size is 50px by 50px - and you want to scale it by +10%:
width = 50px * 1.1 = 55px;
height = 50px * 1.1 = 55px;
but those extra 5px will be added to the right and bottom of the View, right? so we need to change the offset of the View to adjust:
top = 100px - ((100px * .1) / 2) = 97.5px
(same for the left, obviously).
using this pattern, you can scale the view in a way that keeps the center point consistent.
Related
I'm trying to create the control, that allows moving view with the finger. To do this, I follow recommendations from this post.
But presented method needs some modification, to prevent my view from being moved beyond the screen. I found out how to get maxY and maxY coordinates - for my Samsung Galaxy A6 it's 1080x1920. But the problem is, that my maxY is deep beyond the visible bottom edge of the device.
So my control almost disappears, when reaches Y about 1650. What 300 more pixels go for. I can suppose, that this is NavigationBar height + my control view height, but this also doesn't place my control as expected.
I define max coordinates with this method.
private void setMaxCoordinates(int viewWidth, int viewHeight) {
Display display = getWindowManager().getDefaultDisplay();
Point displaySize = new Point();
display.getSize(displaySize);
maxX = displaySize.x - viewWidth;
maxY = displaySize.y - viewHeight;
}
Please, help me to define the correct formula to detect bottom edge coordinate.
I've found a solution. First of all I was wrong with getting bottom coordinates with the help of WindowManager. This just gives you height of your screen in pixels, that is not related to the container. So to detect your bottom coordinate this way, you have to consider:
StatusBar height.
NavigationBar height.
Height of all views that lokated higher, then your container.
Height of your own control view (ImageView in my case).
So formula will look like this.
maxY = windowHeight - (statusBarHeight + navBarheight + allUpperViewsHeight + yourViewHeight)
The correct way to define the bootom of your container, is to get the container's height and deduct your control height.
maxY = containerHeight - yourViewHeight;
This more of a conceptual Android question
Say I have this static image that I want to load into an ImageView -
Say the image is 600px by 200px.(width by height)
Say my image view I try fitting it into is 300 px by 200px(width by height)
I just want to scale by height and cut off the left end of the image so that the image can fit into the imageview. Also if no cuts need to take place(fits already), I don't want to cut any of it off.
So in the end the ImageView(if it was 300 px by 200px) would hold this image
(basically so the F doesn't get distorted)
I've looked Scale To Fit but none of the scale types seems to achieve this custom effect. Does anyone know of how I would go about this? In my case, I wouldn't want to maintain the original aspect ratio.
You should crop the Bitmap so that it always fits into your ImageView. If you want the bottom-right corner cropped, you could do something similar to this:
if (needsCropping()) {
int startWidth = originalImage.getWidth() - 300;
int startHeight = originalImage.getHeight() - 200;
Bitmap croppedBitmap = Bitmap.createBitmap(originalImage, startWidth, startHeight, width, height);
// TODO set imageview
}
FIT_END would do this:
Compute a scale that will maintain the original src aspect ratio, but will also ensure that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. END aligns the result to the right and bottom edges of dst.
You can use ScaleType.CENTER_CROP BUT this will not rescale the image in any way.
Any combinations of those is impossible, for that you must have your own scale method (subclassing ImageView).
Or, the easy way would have .9PNGs as the source of the image, it would fit any space without distorcing.
I have the next question:
Im developing an app that when i move a imageView and drop it, if the view drops under the half height of the screen goes to a (X,Y) position and if is over the half height screen, goes to another position.
I need to calculate the half of the screen generic, so i use the next code:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
halfHeight = displaymetrics.heightPixels / 2;
This works great, im trying in a screen 1920x1080, the code returns 540.
But when im going to see if when i drop the view is under or over the half, here is what i dont understand. i get the Y position of the view and is ok, what i dont understand is why the Y = 0 is not on the TOP of the screen, if i move the view to the top, i get a negative Y position like -260.
Someone can explain me why this happen?
Is there i way that the (0,0) position starts in the top left of the screen?
Greets, hope you understand
If you call getX() or getY() then you are getting relative values for x and y (relative to the view that the call was dispatched from). If you call getRawX() or getRawY() it will give you the absolute position of the view relative to the device's screen.
Most likely you are getting negative values of -260 because you are dragging the ImageView 260 away from the view in which the call was made (perhaps the view on the top of the screen has a height of 260). If you are trying to use getX() or getY() to calculate the middle of the screen then you would have to take all sizes of all views into consideration but I think you want to use getRawX() and getRawY()
An angle of 0 degrees correspond to the geometric angle of 0 degrees (3 o'clock on a watch.)
try using translate to translate the co-ordinates to top of the screen.
http://developer.android.com/reference/android/graphics/Canvas.html#translate(float, float)
I've an implementation of a translucent to opaque ActionBar effect (Google Play's App Pages, Google Music) in an app I'm developing, I've made a ScrollView that notifies when the scrolling changes, my listener then calculates a ratio of opacity for the ActionBar relative to some max height. This is working great, but now I've implemented something like this in my scroll change listener.
float ratio = (float) Math.min(Math.max(t, 0), limitHeight) / limitHeight;
toolBarDrawableAlpha = (int) (ratio * 255);
toolBarTypeColorDrawable.setAlpha(toolBarDrawableAlpha);
int dexEntryPictureNewSize = Math
.max(dexEntryPictureMinSize, (int) ((1 - ratio / 2) * dexEntryPictureSize));
dexEntryPicture.getLayoutParams().height = dexEntryPictureNewSize;
dexEntryPicture.getLayoutParams().width = dexEntryPictureNewSize;
dexEntryPicture.requestLayout();
int dexEntryPictureNewBottomMargin = Math.max(dexEntryPictureMarginBottom,
Math.min(dexEntryPictureMaxMarginBottom,
(int) ((ratio * 1.5) * dexEntryPictureMaxMarginBottom)));
((FrameLayout.LayoutParams) dexEntryPicture
.getLayoutParams()).bottomMargin = dexEntryPictureNewBottomMargin;
dexEntryPicture.requestLayout();
int dexEntryNameNewTopPadding = Math.max(dexEntryNamePaddingTop,
Math.min(dexEntryNameMaxPaddingTop, (int) ((ratio) * dexEntryNameMaxPaddingTop)));
dexEntryName.setPadding(dexEntryName.getPaddingLeft(), dexEntryNameNewTopPadding,
dexEntryName.getPaddingRight(), dexEntryName.getPaddingBottom());
As you can see, I use the same ratio calculated for the opacity to change some height, width, margin, padding values in my views, this is working great too, but I've been wondering if there's a way to accomplish this in a more efficient way or if I'm making some horrible performance mistakes, I only have one device to test this and it's running fairly snappy, really smooth but would like to know if lesser devices won't whine about it.
If you are wondering what's the final effect that I'm going for, it's some sort of parallax (?) scrolling where a fixed background view has another centered view in it (like a profile image circle) and this centered view shrink and expands relative to the opacity ratio, also some paddings are moved so the view seems to be pushed to top.
This may sound really obvious but how can I find the points along the edge of the screen in order to know if a moving object has hit the edge of the screen.
Thankyou
Given you have orthographic projection, you can easily know where your edges are by knowing the values you've passed into the glOrtho() function.
For example, consider this line:
glOrtho(0.0f, width, 0.0f, height, 0.0f, 1.0f);
Here you can decide how big influence a single float will have in your program. You can find more information about this here.
However, in this scenario your left edge is 0.0 and your bottom edge is 0.0. Your top edge is defined by height and your right edge is defined by width.
In this way you don't have to rely on a specific screen size since your world will always be as big as you define. For example, you don't need to define the orthographical width and height by the width and height parameters, but instead use some data telling your application how big your world should be.
Just do this:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();