I have a layout where the Gallery height is WRAP_CONTENT (width is FILL_PARENT) with bottom margin of 80dp. This would leave 80dp at bottom of screen for something else.
The problem is how can I find out exactly how many pixels do I have in the height of this Gallery? I need this in order to set the size of the bitmap in Gallery's getView (as I want each image to take up a full Gallery screen) Various devices should give me different height pixels...
Apparently when I query Gallery.getHeight, it returns zero.
Also, if the image itself is smaller than the Gallery view port, I want to scale it up. However setScaleType(FIT_CENTER) seems to only scale down (if image is larger than viewport) yet does not scale up? Am I missing something?
Thanks in advance for your help.
Gallery is just another View, so any method defined for View will work. Use myGalery.getHeight();
From the View API reference page: http://developer.android.com/reference/android/view/View.html
Size, padding and margins
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().
To measure its dimensions, a view takes into account its padding. The padding is expressed in pixels for the left, top, right and bottom parts of the view. Padding can be used to offset the content of the view by a specific amount of pixels. For instance, a left padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding can be set using the setPadding(int, int, int, int) method and queried by calling getPaddingLeft(), getPaddingTop(), getPaddingRight() and getPaddingBottom().
Update
Be careful when are you measuring it. If you use it on the constructor, the it will return zero since it was not drawn yet. Unless you are absolutely sure that the GridView will be visible by the time you measure it, you can measure by adding an View.OnLayoutChangeListener and implementing
public abstract void onLayoutChange (View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
http://developer.android.com/reference/android/view/View.OnLayoutChangeListener.html
or overriding protected void onSizeChanged (int w, int h, int oldw, int oldh)
u can get the total height & delete 80px from it ie(your Gallery height)
get total height by this code
Display display;
display = activity.getWindowManager().getDefaultDisplay();
display.getHeight()
Related
I was going through this http://developer.android.com/guide/topics/ui/declaring-layout.html when i cam across a line stating that the height may, but do not have to, be different from the measured height, I was thinking of how can the measured height be different from height of a layout.
The methods View#getMeasuredWidth() and View#getMeasuredHeight() represents the dimensions the view wants to be, before all views in the layout are calculated and laid in the screen.
After View#onMeasure(int, int) and View#onLayout(boolean, int, int, int, int), views measurements could be change to accommodate everything. These (possible) new values are then accessible through View#getWidth() and View#getHeight().
From the View class reference:
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().
TextView.getMinHeight() appears in API 16. But TextView.setMinHeight() appears in API 1. Where is any possible way to get min height in pre API 16 version without reflection?
Use ViewCompat.getMinimumHeight(view) from support-v4 library.
There's no way to get it without reflection.
The field is called mMaximum. It can hold a value in pixels or in lines of text, that's why it's not called mMaxHeight.
Saving the value in setMaxHeight() is not ideal, because there's also setMaxLines() method, which changes the max mode and effectively clears the max height value. You would have to overload all methods writing mMaximum field.
short answer:
View.getLayoutParams().height
View.getLayoutParams().width
other possibilities :
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().
ways:
using the famous OnGlobalLayoutListener
This is one of the most used mechanisms to get the view dimensions. You attach a Global Layout Listener to the view hierarchy. It helps you actually get the width of all the views in your view heirarchy:
by forcing a measurement of the View
View.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
int widht = View.getMeasuredWidth();
int height = View.getMeasuredHeight();
I've been searching for an alternative for the android.widget.ImageView.setTop# method in android which would work for api's under 11 or Honeycomb. Is such an alternative even available?
For anything below Honeycomb (API Level 11) you'll have to use setLayoutParams(...).
you can dynamically set the position of view in Android. for example if you have an ImageView in LinearLayout of your xml file.So you can set its position through LayoutParams.But make sure to take LayoutParams according to the layout taken in your xml file.There are different LayoutParams according to the layout taken.
Here is the code to set:
FrameLayout.LayoutParams layoutParams=new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);
From android documentations: doc
Sets the top position of this view relative to its parent. This method is meant to be called by the layout system and should not generally be called otherwise, because the property may be changed at any time by the layout.
This method shouldn't be called directly, mainly because different ViewGroups have different approach to layout which makes this method not consistent (framelayout).
as #nitesh goel suggested, use Margin or padding to set the spacing between a child view and its original position in the ViewGroup. doc
Size, padding and margins
The size of a view is expressed with a width and a height. A view actually possess two >pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().
To measure its dimensions, a view takes into account its padding. The padding is expressed in pixels for the left, top, right and bottom parts of the view. Padding can be used to offset the content of the view by a specific amount of pixels. For instance, a left padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding can be set using the setPadding(int, int, int, int) or setPaddingRelative(int, int, int, int) method and queried by calling getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom(), getPaddingStart(), getPaddingEnd().
Even though a view can define a padding, it does not provide any support for margins. However, view groups provide such a support. Refer to ViewGroup and ViewGroup.MarginLayoutParams for further information.
I have made a custom View with onDraw() overridden that draws a bitmap on the canvas. When I specify that I want it wrap_content in the layout file it still fills up the entire screen. onMeasure() says this:
The base class implementation of measure defaults to the background size, unless a larger size is allowed by the MeasureSpec. Subclasses should override onMeasure(int, int) to provide better measurements of their content.
Ok cool so I know I need to override onMeasure() and work with MeasureSpec. According to this answer
UNSPECIFIED means the layout_width or layout_height value was set to wrap_content. You can be whatever size you would like.
Now I get to my problem, how do I at onMeasure() measure my bitmap that is not created yet and measure/wrap it? I know the other Android views MUST do something because they do not block out the entire screen if set to wrap_content. Thanks in advance!
This is the order that these commonly used view methods are run in:
1. Constructor // choose your desired size
2. onMeasure // parent will determine if your desired size is acceptable
3. onSizeChanged
4. onLayout
5. onDraw // draw your view content at the size specified by the parent
Choosing a desired size
If your view could be any size it wanted, what size would it choose? This will be your wrap_content size and will depend on the content of your custom view. Examples:
If your custom view is an image, then your desired size would probably be the pixel dimensions of the bitmap plus any padding. (It is your responsibility to figure padding into your calculations when choosing a size and drawing the content.)
If you custom view is an analog clock, then the desired size could be some default size that it would look good at. (You can always get the the dp to px size for the device.)
If your desired size uses heavy calculations, then do that in your constructor. Otherwise, you can just assign it in onMeasure. (onMeasure, onLayout, and onDraw may be called multiple times so that is why it isn't good to do heavy work here.)
Negotiating the final size
onMeasure is the place where the child tells the parent how big it would like to be and the parent decides if that is acceptable. This method often gets called a few times, each time passing in different size requirements, seeing if some compromise can be reached. In the end, though, the child needs to respect to the parent's size requirements.
I always go back to this answer when I need a refresher on how to set up my onMeasure:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
In the example above the desired width and height were just set to some defaults. You could instead calculate them beforehand and set them here using a class member variable.
Using the chosen size
After onMeasure, the size of your view is known. This size may or may not be what you requested, but it is what you have to work with now. Use that size to draw the content on your view in onDraw.
Notes
Any time that you make a change to your view that affects the appearance but not the size, then call invalidate(). This will cause onDraw to be called again (but not all of those other previous methods).
Any time that you make a change to your view that would affect the size, then call requestLayout(). This will start the process of measuring and drawing all over again from onMeasure. It is usually combined with a call to invalidate().
If for some reason you really can't determine an appropriate desired size beforehand, then I suppose you can do as #nmw suggests and just request zero width, zero height. Then request a layout (not just invalidate()) after everything has been loaded. This seems like a bit of a waste though, because you are requiring the entire view hierarchy to be laid out twice in a row.
If you can't measure the bitmap prior to the onMeasure call, then you could return a size of zero until the Bitmap is loaded. Once it is loaded, invalidate the parent ViewGroup to force another measure (can't remember if invalidate() on the View itself will force an onMeasure).
I want to create a layout that contains an image on top of which I want to place many images and TextViews. I know how to place images on top of one another using RelativeLayout, but how to align them in a desired way? Eg I want an image to be exactly in a place where my “background” image has a specific black circle. Playing with values like android:layout_marginTop etc does not seem to do the effect in every screen.
So which is the proper way to handle these issues?
EDIT:
I cannot upload the images, but I uploaded a very simple sketch of what I want here:
http://imageshack.us/photo/my-images/715/buttonlayout.png/
all the buttons have also Icons and text (which must be a textview so that I can change it programmatically if need be)
You have to create a custom layout that places the image specifically where you want them relative to the size of the parent view. If you choose, you can override the LayoutParams and apply custom attributes to them for your custom view to read.
Anyway, to specifically place an item, say 30% down from the top and 20% from the left, you would overwrite onLayout().
#Override
public void onLayout(boolean c, int left, int top, int right, int bottom) {
super.onLayout(c, left, top, right, bottom);
int width = right - left;
int height = bottom - top;
View v = getTheChildView();
int viewL = left + (int)(width * .2f); // The left pixel is 20% down the total width of the parent view
int viewR = viewL + v.getWidth(); // The right pixel is the left pixel plus the measured width of the child view itself
int viewT = top + (int)(height * .3f); // The top pixel is 30% down the total height of the parent view
int viewB = top + v.getHeight(); // The bottom pixel is the top pixel plus the measured height of the child view itself
v.layout(viewL, viewT, viewR, viewB);
}