19

I would like to position a view below an action bar with overlay. Is there a way of doing this via XML layout?

I would like to avoid using constants as there are already at least 4 possible values and that number is likely to grow.

Compatibility with ActionBarSherlock is a plus.

Community
  • 1
  • 1
hpique
  • 119,096
  • 131
  • 338
  • 476

3 Answers3

46

android:layout_marginTop="?attr/actionBarSize"

This will account for changes in size based on screen configuration automatically. You can see a demo of its use in the "Overlay" example of the 'Demos' sample that comes with ActionBarSherlock.

Muhammed Fasil
  • 7,909
  • 2
  • 19
  • 28
Jake Wharton
  • 75,598
  • 23
  • 223
  • 230
  • Thanks! Are you sure the margin changes if the configuration changes? – hpique Jul 10 '12 at 18:41
  • 1
    As long as you're not handling configuration changes in the manifest it certainly will. – Jake Wharton Jul 10 '12 at 18:50
  • Well it should still work relatively well regardless. Handling configuration changes prevents ABS from fully recreating its views which means you may see some inconsistency with how things are displayed. It's also declared as a last-resort by Google in the documentation. – Jake Wharton Jul 10 '12 at 19:31
  • After further inspecting the ActionBarSherlock code ?attr/actionBarSize is defined with constants for each known screen/height combination. This approach is not forward-compatible. +1 for helping, though. – hpique Jul 21 '12 at 09:37
  • It is forward compatible. It works on all API levels and with all themes. If you wanted to do this natively (API 11+) you could use `?android:attr/actionBarSize`. – Jake Wharton Jul 22 '12 at 01:44
  • You're right. But why isn't ?android:attr/actionBarSize in res/values-v11 of ActionBarSherlock? BTW, thanks for making the library! You're awesome. – hpique Jul 22 '12 at 11:33
  • Because it's present in `Theme.Sherlock` in `values/` which then would extend from the themes in `values-v11/` when run on APIs 11-13. You can see this in use in the 'Overlay' example in the Demos sample. – Jake Wharton Jul 22 '12 at 21:50
7

Jake Wharton's answer does not work if you're handling configuration changes.

This is how I solved this problem by code, in case it helps anyone:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    layoutTheView();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    layoutTheView();
}

private void layoutTheView() {
    ActionBar actionBar = this.getSupportActionBar();
    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mTheView.getLayoutParams();
    int actionBarHeight = actionBar.getHeight();
    params.setMargins(0, actionBarHeight, 0, 0);
    mTheView.setLayoutParams(params);
    mTheView.requestLayout();
}
Community
  • 1
  • 1
hpique
  • 119,096
  • 131
  • 338
  • 476
  • +1. Interesting. This works for me, but replacing `params.setMargins(0, actionBarHeight, 0, 0);` with `params.topMargin = actionBarHeight;` does not. (4.2.1) Also, `setLayoutParams` calls `requestLayout`, so it works without that last line. – dokkaebi Dec 18 '12 at 04:31
-1

use padding top

android:paddingTop="50dp"

Hitesh
  • 56
  • 1
  • 5