Android: Need to use onSizeChanged for View.getWidth/Height() in class extending Activity
Asked Answered
A

5

18

I want to use getWidth()/getHeight() to get width/height of my XML-Layout. I read I have to do it in the method onSizeChanged() otherwise I will get 0 ( Android: Get the screen resolution / pixels as integer values ).

But I want to do it in a class already extending Activity. So I think it's not possible let the same class extending View.

public class MyClass extends Activity {

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        ViewGroup xml_layout = (ViewGroup) findViewById(R.id.layout_id);  
        TextView tv = new TextView(this);  
        tv = (TextView) findViewById(R.id.text_view);  
        int layout_height = xml_layout.getHeight();  
        int layout_width = xml_layout.getWidth();
    }  

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        //Error, because I need to use extends View for class, but I can't do it because I also need extends Activity to use onCreate
    }
}

If I use MyClass extends Activity I can use onCreate but not onSizeChanged.
If I use MyClass extends View I can use onSizeChangedbut not onCreate.

How can I solve the problem?

Ardithardme answered 3/2, 2011 at 16:15 Comment(0)
S
37

You dont have to create a customView to get its height and width. You can add an OnLayoutChangedListener (description here) to the view whose width/height you want, and then essentially get the values in the onLayoutChanged method, like so

View myView = findViewById(R.id.my_view);
myView.addOnLayoutChangeListener(new OnLayoutChangeListener() {

        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight,
                int oldBottom) {
            // its possible that the layout is not complete in which case
            // we will get all zero values for the positions, so ignore the event
            if (left == 0 && top == 0 && right == 0 && bottom == 0) {
                return;
            }

           // Do what you need to do with the height/width since they are now set
        }
    });

The reason for this is because views are drawn only after the layout is complete. The system then walks down the view heirarchy tree to measure the width/height of each view before drawing them.

Sadi answered 25/5, 2011 at 20:20 Comment(3)
OnLayoutChangeListener assumes your target is API 11+Tangelatangelo
Thanks for pointing that out, @CarlWhalley ! I realized that when trying to use it in API 10 :). I actually found that if the height/width of your layout is not dependent on being determined by any other layout (being used in a relative layout or using layout weights) you can even force the View to be measured as follows: view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED) and then using getMeasuredHeight/Width to get the valuesSadi
@Sadi Does that work onCreate? I was trying to get dimensions when activity starts up, and i thought .measure would count the nav bar in the screens height/width measurements...Prodigy
G
22

What I would recommend doing is extending ListView in your own custom class. Define a class called MyListView, or something similar, and make sure you define all three constructors. Then, override the onSizeChanged method to call something externally - much like an OnClickListener or OnTouchListener. You could define a method in MyListView to accept a listener, instantiate a listener in your activity, and then when onSizeChanged is called, pass it on through to the listener. This is really hard to explain in English. Here is some sample code:

Custom ListView:

public class MyListView extends ListView
{
    public MyListView(Context context)
    {
        super(context);
    }
    public MyListView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    public MyListView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    public void SetOnResizeListener(MyOnResizeListener orlExt)
    {
        orl = orlExt;
    }

    @Override
    protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld)
    {
        super.onSizeChanged(xNew, yNew, xOld, yOld);

        if(orl != null)
        {
            orl.OnResize(this.getId(), xNew, yNew, xOld, yOld);
        }
    }

    MyOnResizeListener orl = null;
 }

Custom listener:

public class MyOnResizeListener
 {
    public MyOnResizeListener(){}

    public void OnResize(int id, int xNew, int yNew, int xOld, int yOld){}
 }

You instantiate the listener like:

Class MyActivity extends Activity
{
      /***Stuff***/

     MyOnResizeListener orlResized = new MyOnResizeListener()
     {
          @Override
          public void OnResize(int id, int xNew, int yNew, int xOld, int yOld)
          {
           /***Handle resize event****/
          }
     };
}

And don't forget to pass your listener to your custom view:

 /***Probably in your activity's onCreate***/
 ((MyListView)findViewById(R.id.MyList)).SetOnResizeListener(orlResized);

Finally, you can add your custom list to an XML layout by doing something like:

 <com.myapplication.whatever.MyListView>
      <!-- Attributes -->
 <com.myapplication.whatever.MyListView/>
Garton answered 23/2, 2011 at 7:9 Comment(1)
Thank man! However I noticed a flaw when using this with a fragment. I had to pass the listener in the onStart() method as the fragments view wasn't handled by the Activity in onCreate (hence what onCreateView is for).Shiah
I
4

I had a similar problem (ie. calculating View sizes in an Activity after it was finished drawing).

I overrode the Activity method : public void onWindowFocusChanged(boolean hasFocus) and it worked fine.

Incomprehension answered 16/8, 2011 at 4:20 Comment(1)
onWindowFocusChanged doesn't seem to work very well. I have an Activity that extends ExpandableListActivity. I overrode the onWindowFocusChanged method to call the ExpandableListView:mListView.setIndicatorBounds in order to align the group indicator to the right side of the view instead of the left. What I see happening is that all the children are created with the group indicator aligned on the left and then another redraw happens with the group indicator on the right. I can see this realignment happening indicating that this might not be the best place to do view layout.Olszewski
E
1

Just add a method to your custom view that you call when onSizeChanged takes place in the Activity. Pass the new values to the view as parameters of the called method. Then execute whatever operations need to take place when your custom view changes size.

Exedra answered 3/2, 2011 at 16:50 Comment(1)
Sorry, but I don't understand really what to do. I can't call my custom view when onSizeChanged takes place in the Activity because my activity class extends Activity and not View. But I have to extend view to use method onSizeChanged. Would be great if you could give a little code example.Ardithardme
W
0

i think i know what you want to know........... i just wrote a new blog post on that right now........... how to get width and height dimensions of a customView (extends View) in Android http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html

Whyte answered 27/2, 2011 at 20:2 Comment(1)
Please don't use URL shorteners. meta.stackexchange.com/questions/99136/…Gerenuk

© 2022 - 2024 — McMap. All rights reserved.