How setbounds of drawable works in Android? - android

I am confused with setbounds method of drawable in Android. I know it is used with drawable and it set where drawable and how large it is. Briefly, it defines, bounding rectangle for drawable. But I am confused: does it set border or padding or its width or height?
This is how we use setbounds
drawableInstance.setBounds(L,T,R,B);
First scenario
So in above case, If I set 5,5,5,5 for L,T,R,B respectively, L,T,R,B of drawable will be always from its parent respectively? I mean will it be like setting hidden 5px border to every side?Besides, if image is not large enough to meets that border width to its parent, will image be bigger?
Second scenario
I set 5,5,100,100 for L,T,R,B respectively. What I am confusing is, it will starts drawing from away from parent 5px to the top and 5px to the left. That will be the start point. Then image with will be 100px because I set 100 for right. So it goes to the right 100px. Same to bottom with right.
But I tested it. I think both is not as what I think. How does it work, especially in relation to each parameter of setBounds?

The bounds values are absolute, not relative. That is, width == right - left, and height == bottom - top.
Your first example will have the top left corner of the Drawable at (5, 5), but the width and height will both be 0.
The second example will also have the top left corner at (5, 5), and the width and height will both be 95.
The bounds are not dependent on the dimensions of the Canvas to which the Drawable is drawn. For instance, if you draw a Drawable with the bounds of your second example onto a View that is only 50 by 50, its left and top sides will be inset by 5, but it will get cut off at the right and bottom borders.

Related

AppCompatImageView displaying big image using ScaleType.CENTER and the use of padding

I have an image 3264x1836 and I display it in a custom AppCompatImageView having dimensions 1280x720. I want to preserve the image size so I use ScaleType.CENTER, but I also want that its top-left corner is positioned at the coordinates 0,0 of my custom view, so I set the padding left and top accordingly.
Now, to achieve that I had to use 3264-1280 (the difference between the widths) as left padding and 1836-720 (the difference between the heights) as top padding while, in my opinion, these values should be both divided by 2.
Can somebody explain why?
It is likely that you are breaking the AppCompatImageView code by asking it to do something that wasn't anticipated or tested.
While the above could still be true, the padding that you are applying is correct. Here are the calculations:
For simplicity, let's take a look at the left padding needed to shift the graphic. The same sort of calculations will work for the top padding.
The width of the graphic is greater than the width of the ImageView.
d = wgraphic - wimageview
If the graphic is centered in the ImageView, then the overhang on the left and right sides will be 1/2 the difference in widths.
s = d / 2
The graphic is centered within the padding of the ImageView. The amount of padding that has to be specified must be just enough to shift the center of the graphic by the amount s.
The initial center of the ImageView without padding is
ci = wimageview / 2
The shifted center with left padding ( p ) is
cs = p + (wimageview - p) / 2
So,
s = cs - ci = p + (wimageview - p) / 2 - (wimageview / 2)
Solving for the padding needed for a shift of s we get p = 2s = d. In other words, the padding we need is twice the shift required which is what you are seeing.
A fix that doesn't involve padding would be to specify
android:scaleType="matrix"
You should remove the padding. The new scale type will apply the identity matrix to the image and place it in the top/left corner without resizing.

Get size of 9-patch content area

In my app, I have a feature where you can put a frame around an image.
I use setBackground(Drawable) to apply the image of the frame to an ImageView. When the ImageView is clicked, I want to blow the content area (the image contained in the frame) up to the size of the screen. For this, I need to know the difference between the entire view and the content area, i.e. the thickness of the border.
Is there a way to get the size of the content area? (Accessing View.getWidth() for the ImageView gives content + border. I'm trying to get the border / padding.)
You can use:
Rect padding = new Rect();
view.getBackground().getPadding(padding);
int contentWidth = view.getWidth() - padding.left - padding.right;
int contentHeight = view.getHeight() - padding.top - padding.bottom;
If your background is a nine patch, the getPadding method will return the insets of the drawable
Here's an alternative approach:
The horizontal and vertical borders of the 9patch frame should not be stretched vertically and horizontally, respectively. Therefore you have constant width of the vertical border and height of the horizontal border. You can open the 9patch with any image editor that supports measuring and measure those lengths.
Use those values as margin or padding of the content view. Providing a single 9patch for all DPIs should work as the system would stretch it for higher DPIs but your padding/margin would be in DPs, so it should be the same size as the frame.

How to achieve a "pan out" animation on Android

Let's say the following coordinates are relative to (0, 0) being the top left corner of the phone's screen with increasing positive x values going to the right and increasing positive y values going down as diagrammed here: http://t.cyol.com/cache/temp/img/2011/02/1000/119/img/img_1297675862_0.jpg
I'd like to do a "pan out" animation where there is a little box whose top left corner is at (x, y), and it has width w and height h where x, y, w, and h are greater than 0. Everywhere inside that box is some content. Everywhere outside that box is black.
Over 500 milliseconds, the box's top left corner should move to (0, 0) and its width and height will grow to fill the entire screen. That is, over half a second, the box pans out to fullscreen.
The content inside the box is a WebView.
How do I achieve this animation? I tried scaling, but that's not what I want to achieve, because the content inside the box shouldn't get squished. Translating only works if the box starts out in a corner.
In order to achieve this effect, the whole view must be relayouted at each frame of the animation. You'll need to change the layout params of the view and call requestLayout(). Check this link:
Android Animate Scale Image to fit screen width and height

How to set absolute (not %) position for the center of a shape drawable gradient?

I've got a shape drawable with a radial gradient inside it. The shape is a rectangle, and I'm trying to position the center of the radial gradient near the bottom right corner. I can get it in the general vicinity using the centerX and centerY attributes set to values like 0.98, but I'm dealing with rectangles of different heights (same width), so the taller the rectangle is, the higher the center position is, relative to the bottom right corner.
It seems I can only position the center as a percentage of the view width/height, contrary to the documentation. That is, even without the "%" in the value, it is treated as a percentage.
What I'd like to do is somehow say "put the center 5dp up and to the left of the bottom right corner". Any ideas on how to accomplish that?
You might try use a Layer-List, there you can specify margins of overlaying layer items, which can be drawables.

What is android:layout_gravity="clip_vertical" exactly

The property android:layout_gravity="clip_vertical|horizontal" does the following as mentioned in the SDK documentation:
Additional option that can be set to
have the top and/or bottom edges of
the child clipped to its container's
bounds. The clip will be based on the
vertical gravity: a top gravity will
clip the bottom edge, a bottom gravity
will clip the top edge, and neither
will clip both edges.
But I can't see anything of this in my applications,
so what is the purpose of this property exactly ?
thanks
Short version:
clip_horizontal and clip_vertical apply to the measurements of the view itself, before any contents (such as the image in a BitmapDrawable) are rendered.
Long version:
I've run into some similar confusion over clip_horizontal and clip_vertical. (In my case, it was related to android:gravity for a BitmapDrawable, but it's similar enough to be applicable.)
From the documentation I thought that something like android:gravity="top|left|clip_vertical" on a bitmap would cause the image's top left corner to be positioned at the view's top left corner, and that, if the bitmap was taller than the view, it would be "clipped" at the bottom edge of the view. In other words, show only as much of the bitmap that the view is tall enough to reveal; do not stretch the bitmap, but instead only show whatever will fit, letting the rest extend below the bottom edge.
However, the opposite happened: when I set clip_vertical, a large bitmap was squished vertically to fit within the height of the view.
After examining the applyDisplay() method in platform/frameworks/core/java/android/view/Gravity.java, I realized my mistake:
It isn't the bitmap image that was going to be clipped, but the view -- the actual size of the container the image is ultimately rendered into.
Setting clip_vertical in my case didn't mean "clip the image at the bottom edge," it meant "clip the BitmapDrawable's view itself so its height matches the height of its parent container"...which then caused the image to be "squished" as it filled that shorter height.
So, the important thing to remember with android:gravity and android:layout_gravity is that clip_horizontal and clip_vertical apply to the measurements of the view itself, before any contents (such as my BitmapDrawable) are rendered.
Maybe there is no effect because horizontal is not defined in the android:layout_gravity. clip_vertical is just an additional property that is used in addition to a base property.
Flag to clip the edges of the object to its container along the horizontal axis.
check this

Categories

Resources