0

So i have a view which is inflated via Xml. That view has a subView, which i need to set a marginTop with a dynamic value like this:

toolbar.getHeight() - 100

For this reason, i cannot set it to xml. I could do this:

?attr/actionBarSize

but i need specifically toolbar.getHeight() - 100

What is the proper way of accomplish this? I am doing it in the onCreate of the activity, i set a viewTreeObserver.addOnGlobalLayoutListener for that view, get the layoutParameters and add a margin.

Is this the right way to do this? The way i see it, the view is drawn, and when i run some code inside viewTreeObserver of that view, the view must be redrawn again. Is there a way of avoid this double rendering without setting a custom view?

johnny_crq
  • 4,291
  • 5
  • 39
  • 64
  • If the toolbar height is a fixed size, you could look up that size with `getResources().getDimensionPixelSize(...)` and set the margin right away instead of waiting for a layout pass. – Karakuri Aug 18 '16 at 13:53
  • it is not. its attr?actionBarSize – johnny_crq Aug 18 '16 at 14:20
  • You can look that up `obtainStyledAttributes()` in `onCreate()`. And that is a fixed size, it's just a different fixed size for different configurations. – Karakuri Aug 18 '16 at 14:29

1 Answers1

1

Inside of onCreate() you can look up the value for this attribute in the current context:

int[] attrIds = new int[1]{ R.attr.actionBarSize };
TypedArray a = obtainStyledAttributes(attrIds);
// first argument is index in attrIds, second argument is
// a default value to return if not found
int actionBarSize = a.getDimensionPizelSize(0, 0);
a.recycle();
// do something with actionBarSize
Karakuri
  • 38,365
  • 12
  • 84
  • 104
  • it is not a custom view! I can do it programatically with a globalLayout listener. I want to know if there is a way of doing it without the view drawing twice – johnny_crq Aug 18 '16 at 15:01
  • in other words, i would do it this way: android:layout_marginTop="?attr/actionBarSize - xxx" But this is not possible. This view is not a custom view. I want to know if i can do it without making it a custom view, and without the double layout pass – johnny_crq Aug 18 '16 at 15:05
  • let me know if you didn't understood it. – johnny_crq Aug 18 '16 at 15:29
  • @user3806331 You misunderstand. There is nothing here about a custom view. `obtainStyledAttributes(...)` is a method of `Context`, you can do this inside of `onCreate()` of your `Activity`. – Karakuri Aug 18 '16 at 16:00
  • that is not the problem. I know how to get the actionBarSize attr at runtime. My problem is how to add a margin to a view(which will be actionBarSize - xxx), view that was defined via XML, without redrawing the view twice. @Karakuri – johnny_crq Aug 18 '16 at 16:12
  • @user3806331 `findViewById()` and get it's LayoutParams. Those are available as soon as the view is inflated, e.g. after `setContentView()`. The difference is this code looks up an attribute value instead of waiting for the view to be measured and getting its size, that is it doesn't require multiple layout passes. – Karakuri Aug 18 '16 at 16:47
  • ok so basically after setContentView(), the view is inflated but not drawn. I can then add the margin and it wont be rendered twice? But i have no guarantee that the view isn't already drawn does i? (Just asking i don't know) – johnny_crq Aug 18 '16 at 19:17
  • @user3806331 UI changes aren't drawn immediately (e.g. calling `setText(...)` on a `TextView` doesn't show the new text as soon as you've returned from the method). There's a loop that draws the views on a schedule, and if a measure and layout is needed (such as after `setText()`, it does that first. If you run this code just after `setContentView()`, the views will not have been measured or drawn yet. – Karakuri Aug 18 '16 at 20:04