How can I determine the dimensions of my Scaled ImageView? I tried using getWidth() & getHeight it always returns 0. My xml layout for the ImageView is as follows:
<ImageView
android:id="#+id/imgView"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#drawable/my_image" />
Please suggest something.
You are probably calling getWidth() method too early. The width and height of your ImageView will not be available until the View has been rendered on the screen. Try getting them within onWindowFocusChanged:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
int width = iv.getWidth();
int height = iv.getHeight();
// ...
}
You won't get those dimensions in onCreate. The view isn't measured yet and the hierarchy is not set. Those will work but you need to use them somewhere after the app has drawn the screen or the alternative is to set a ViewTreeObserver to notify you when the layout is set.ViewTreeObserver
Here is how its done:
call getVieeTreeObserver() to get a reference to the viewTreeObserver in your activity.
then add a onGlobalLayoutListener:
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
ViewTreeObserver obs = MyActivity.this.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
}
});
Inside this onGlobalLayout method you can use your view and get its width and height and do whatever with them.
Related
<RelativeLayout
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/book_mark"
android:clipChildren="false"
custom:layoutBackground="#00000000"
android:gravity="center">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:id="#+id/book_mark_image"
android:src="#drawable/icon_bookmark"/>
</RelativeLayout>
My layout xml above. when I call imageview.getY() ,I get 0 for result. When I run this application, ImageView actually center in RelativeLayout. but getY() return 0. According to the size of layout, the distance of imageView to relativeLayout should be 9dp, so getY() should return (9dp -> px). Anyone knows what happened?
please first make sure your image visibility is not gone
else this is because most probably you are calling getY() in on create or on resume
the problem is that your image is not yet loaded to know the exact position of image view now you can use observer
ViewTreeObserver viewTreeObserver = image1.getViewTreeObserver();
viewTreeObserver
.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//now get width or position
//and don't forget to remove listener
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
image1.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
else
image1.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
});
For a dropdown animation, I need to get the actual dp height of a view that has been set to wrap_content, thus depending on the number and sizes of its contained views.
The code sample shows the LinearLayout that I need to know the height of, inside a relative layout with a height of 0. The animation is supposed to increase the RelativeLayout's height to the height value of the inner LinearLayout:
<RelativeLayout
android:id="#+id/new_device_wrpr"
android:layout_width="wrap_content"
android:layout_height="#dimen/zero_size"
android:layout_alignLeft="#id/new_device_dd_button_knob"
android:layout_below="#id/new_device_dd_button_knob" >
<LinearLayout
android:id="#+id/new_device_spawn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/holo_orange_light"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
An implementation like the following only returns 0:
LinearLayout lL = (LinearLayout) findViewById(R.id.new_device_knob_spawn);
lL.getHeight();
As Christian stated you need to wait for layout to occur before you can retrieve the size of the view. If you're attempting to do this in onCreate I would recommend using a global layout listener to execute a callback once layout is complete.
final LinearLayout lL = (LinearLayout) findViewById(R.id.new_device_knob_spawn);
lL.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int h = lL.getHeight();
// Do whatever you want with h
// Remove the listener so it is not called repeatedly
ViewHelper.removeOnGlobalLayoutListener(lL, this);
}
});
In order not to use a deprecated method I have this static helper method to remove global layout listeners. This is due to a renamed method in Jellybean.
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener victim) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
removeLayoutListenerJB(v, victim);
} else removeLayoutListener(v, victim);
}
#SuppressWarnings("deprecation")
private static void removeLayoutListenerJB(View v, ViewTreeObserver.OnGlobalLayoutListener victim) {
v.getViewTreeObserver().removeGlobalOnLayoutListener(victim);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static void removeLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener victim) {
v.getViewTreeObserver().removeOnGlobalLayoutListener(victim);
}
getWidth() or getHeight() will work , but it depends "WHEN" you call it!
It always return 0 if you're calling it in "onCreate" event (that's because the view was not measured yet).
I inflate a layout containing an ImageView and a RelativeLayout. The layout has its width set to match_parent and its height set to wrap_content. The height is determined by the ImageView, but the image set to the ImageView is loaded dynamically from the internet.
Since I know the image ratio, I'd like to set the size of the ImageView before it's displayed to avoid a jump in the UI due to the change in the layout height when the image is set.
To set the size I need the layout width, to compute the ImageView height.
I tried
int width = header.getMeasuredWidth();
but since the layout is not drawn yet it returns 0
I also tried to use measure before, as suggested here
header.measure(0, 0);
int width = header.getMeasuredWidth();
but measure returns a NullPointerException
How can I do that?
list_header.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/pic"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="#+id/header_text_container"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#789987">
</RelativeLayout>
</RelativeLayout>
MyListFragment.java
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mListView = (ListView) getView().findViewById(R.id.listview);
View header = getActivity().getLayoutInflater().inflate(R.layout.list_header, null);
int width = header.getMeasuredWidth(); // 0 because not drawn yet
ImageView pic = (ImageView) header.findViewById(R.id.pic);
pic.setLayoutParams(new LayoutParams(width, (int) (width/imgRatio)));
pic.invalidate();
header.invalidate();
/* ... */
}
You could try with a ViewTreeObserver.
Your Fragment/Activity should implement OnGlobalLayoutListener, in OnActivityCreate declare handler
ViewGroup container = (ViewGroup) findViewById(R.id.header_text_container)
ViewTreeObserver vto = container.getViewTreeObserver();
vto.addOnGlobalLayoutListener(this);
and put your width logic in listener when size are available
#Override
public void onGlobalLayout() {
// Remember to remove handler
container.getViewTreeObserver().removeGlobalOnLayoutListener(this);
View header = getActivity().getLayoutInflater().inflate(R.layout.list_header, null);
int width = header.getMeasuredWidth(); // 0 because not drawn yet
...
}
you can get the size in Activity's onWindowFocusChanged(boolean hasFocus) method.
You can get the width and height of a view in onGlobalLayout, wich is a method to Callback method wich is invoked when the global layout state or the visibility of views within the view tree changes (thus as soon as the view is drawn and the size is known).
ViewTreeObserver vto = header.getViewTreeObserver();
if(vto!=null){
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
header.getWidth();
header.getHeight();
}
});
}
I create my hierarchy of views by code, and then I do setContentView()in the Activity with my root view like argument.
I need know width and height of one view in runtime but if i do getWidth() or getHeight(), i get 0. If i wait a few seconds i get the correct width or height.
I only want to know in what moment android calculate width / height of views. My code isn't outstanding
Thanks!
This is because in onCreate() the layouts haven't been calculated yet. So you need to add a GlobalLayoutListener to know when layouts has been calculated and placed in screen.
final View view = findViewById(R.id.root);
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
ViewTreeObserver vto = view.getViewTreeObserver();
vto.removeGlobalOnLayoutListener(this);
}
});
Where root is the root layout (LinearLayout, RelativeLayout i.e). Assign your root layout with the #+id/root.
You don't say where you are trying to measure the view but my guess is it's in onCreate() or onResume()>
Try this in your onCreate().
// set a global layout listener which will be called when the layout pass is completed and the view is drawn
mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
// measure your views here
}
}
Here, mainLayout is a reference to the root view group of the layout.
This will also be called if the layout is resized after it's first drawn (views added in code, orientation changes etc) so you will always get the correct values.
You can use some View class. add this :
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super(w,h,oldw,oldh);
if(oldw == 0 && w !=0){
...
// w and h is what you want
}
For clarity, according to this Android documentation
When an Activity receives focus, it will be requested to draw its
layout.
...and also measure view dimensions.
Focus receives after onResume and lose it after onPause method.
I have this XML code:
<LinearLayout
android:id="#+id/linearLayoutInner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#layout/gallery_image_background"
/>
Then this code:
LinearLayout linearLayoutInner = (LinearLayout) findViewById(R.id.linearLayoutInner);
ImageView imageView = new ImageView(thisActivityContext);
imageView.setImageResource(R.drawable.example);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(lp);
linearLayoutInner.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);
linearLayoutInner.addView(imageView);
I then call an own function that is meant to scale the bitmap image until one of the sides reach the edge (i.e. so if the original bitmat is twice as wide as tall, it will keep the proportion inside the imageview, something that is apparently not supported by any scaletype setting):
SharedCode.sharedUtilScaleImage(imageView);
And here comes the problem. That function needs to know the size of the view containing the bitmap drawable. if imageView behaves correctly, it should use MATCH_PARENT and hence give the width/height of the linearLayoutInner. However, the following code returns zero:
int heightParent = max(imageView.getLayoutParams().height, imageView.getHeight());
int widthParent = max(imageView.getLayoutParams().width, imageView.getWidth());
How do I solve this? And why am I returned 0 instead of the correct height/width?
You're probably calling the code too early, before the View's onMeasure() has been called. Until that happens, its size is unknown.
final ImageView iv....
ViewTreeObserver vto = iv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//Measure
iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
final ImageView imageView = (ImageView )findViewById(R.id.image_test);
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
imageView .getViewTreeObserver().removeGlobalOnLayoutListener(this);
imageView.getHeight(); // This will return actual height.
imageView.getWidth(); // This will return actual width.
}
});
Seem like you might be calling from onCreate(). u need to wait for activity window to attached and then call getWidth() andgetHeight() on imageView.You can try calling getWidth() and getHeight() from onWindowFocusChanged() method of your activity.
Edit
#Override
public void onWindowFocusChanged(boolean hasFocus){
int width=imageView.getWidth();
int height=imageView.getHeight();
}