97

So, I just updated my codebase to Lollipop, and I'm having issues with the Action Bar. I'm using AppCompat and ActionBarActivity, and inflating a custom view. It seems that the custom view no longer takes up the whole width of the screen, leaving a thin strip on the left

Building with 19 Way it used to look

Building with 21 Way it looks now

This is the code I'm using to set up the Action Bar. Anyone have any ideas?

final ActionBar actionBar = getSupportActionBar();
if(actionBar != null) {
    actionBar.setDisplayHomeAsUpEnabled(false);
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setDisplayShowCustomEnabled(true);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setCustomView(R.layout.action_bar_content_search_custom_view);
    actionBar.setBackgroundDrawable(null);
    // actionBar.setStackedBackgroundDrawable(null);
    TextView title = (TextView) actionBar.getCustomView().findViewById(R.id.action_bar_title);
    title.setText(R.string.youtube);
    ImageView back = (ImageView) actionBar.getCustomView().findViewById(R.id.action_bar_back);
    back.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });
}

Edit

Taking out the custom view and changing the background now takes up the whole width. So the issue is, how can we make a CustomView take up the whole width of the ActionBar?

HpTerm
  • 8,151
  • 12
  • 51
  • 67
Stevie Kideckel
  • 1,928
  • 2
  • 17
  • 21
  • If you temporarily comment out the custom view parts, does it behave better? If not, I'd lean towards this perhaps coming from your theme. – CommonsWare Oct 17 '14 at 21:13
  • I removed the custom view, and set it's background as the background drawable of the ActionBar and the background does take up the whole width now – Stevie Kideckel Oct 17 '14 at 21:30
  • You might peek at your activity in Hierarchy View, both with and without the custom view, and see if you can determine what layout rules are shifting as a result of the custom view. It's possible that this is a bug in the new `appcompat-v7`. – CommonsWare Oct 17 '14 at 21:45
  • Looks to me that is the place reserved for up `ImageView`. Try disabling it for starters. – Nikola Despotoski Oct 18 '14 at 02:42
  • I am facing this problem as well. – Ahmed Nawaz Oct 21 '14 at 11:54
  • 1
    Hi, it seems this is a good solution to have the custom view take the whole width. I was experiencing it not expanding, even with layout weights set. see here: http://stackoverflow.com/a/20794736/581574 – ratana Oct 28 '14 at 03:12
  • @StevieKideckel how u resolved your issue i m also facing same ? in actionbar in api level 21 – Erum Aug 18 '15 at 20:27
  • The chosen answer worked for me, have you tried it out? – Stevie Kideckel Aug 24 '15 at 05:06

9 Answers9

111

Looks like this is caused by the latest changes to the ActionBar in the recent appcompat-v7 update. It seems like that there are significant changes to how you should handle action bars.

I faced the same issue and after reading the ActionBar documentation, and especially the following quote I found a solution.

Beginning with Android L (API level 21), the action bar may be represented by any Toolbar widget within the application layout. The application may signal to the Activity which Toolbar should be treated as the Activity's action bar. Activities that use this feature should use one of the supplied .NoActionBar themes, set the windowActionBar attribute to false or otherwise not request the window feature.

The way I see it, the AppCompat themes were changed and on one hand seemed to break a few things but provide much more flexibility on the other. I recommend following these steps:

  1. Use .NoActionBar style in your activity as described in the above quote
  2. Add a android.support.v7.widget.Toolbar to your Activity layout
  3. Set the app:contentInsetStart="0dp" attribute. This is the main issue with the margin that you describe in your question
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/actionBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:contentInsetEnd="0dp"
    app:contentInsetStart="0dp" >
</android.support.v7.widget.Toolbar>

It's usually recommended that you do that in a separate layout file and use include in your activity layout so you will only need to customize the Toolbar in one place if used in multiple activities

<include layout="@layout/view_action_bar" />
  1. Use findViewById and setSupportActionBar in your Activity onCreate to signal to the Activity which Toolbar should be treated as the Activity's action bar
Toolbar actionBar = (Toolbar) findViewById(R.id.actionBar);
setSupportActionBar(actionBar);
  1. Once you do that, all actions added in onCreateOptionsMenu will be added to the toolbar and it will be treated as the activity action bar.
  2. Further customize the Toolbar as desired (Add child views etc.)
Matt Wolfe
  • 8,924
  • 8
  • 60
  • 77
Muzikant
  • 8,070
  • 5
  • 54
  • 88
  • 1
    I am trying to use Toolbar with navigation drawer however I am getting error `Error inflating class fragment` – Ahmed Nawaz Oct 21 '14 at 12:03
  • All the relevant code is shared on the answer. Looks like you should start a new question for your case as it seems like a different problem. – Muzikant Oct 21 '14 at 16:11
  • Thanks. I solved the problem by replacing actionbar with Toolbar. – Ahmed Nawaz Oct 22 '14 at 08:00
  • Thanks so much! You saved my day! But I'm still looking for a way to put the bottom divider of action bars in my toolbar. Actually, I don't know if it is really a divider in the action bar. It is normally bellow the action bar and it is really a shadow over the content. Any idea? – JPMagalhaes Oct 31 '14 at 19:51
  • 9
    You shouldn't use explicit package names in the namespace declarations. Use `xmlns:app="http://schemas.android.com/apk/res-auto"` – Liminal Nov 01 '14 at 22:54
  • Do you add the custom view to the new Toolbar or by using actionbar.setCustomView()? – Matt Wolfe Nov 11 '14 at 00:08
  • 1
    There is no need for `setCustomView`. Just build a layout file with the widgets you want to include in your toolbar (e.g. add child views to the layout file described in section 3 of the answer) – Muzikant Nov 11 '14 at 12:01
  • Not able to get click event in onOptionsItemSelected with setSupportActionBar(actionBar);, can you please provide solution for this. – Chitrang Dec 16 '14 at 06:33
  • I added following in toolbar app:contentInsetEnd="0dp" app:contentInsetStart="0dp" and it is working now! – void Apr 18 '15 at 07:29
  • This only works when extending `AppCompatActivity`, as `setSupportActionBar(ToolBar)` is not available in a regular `Activity`. Any workaround without having to use `AppCompatActivity`? – h_k Dec 17 '15 at 14:55
  • @Muzikant thanks for your answer. when I put my sutom action bar i doesn't have shadow as normal action bar. how or where I can implement it to have shadow? – Mahdi Jan 06 '16 at 13:22
  • I am supporting the 14th API version and sadly it does not work. Minimum supported version is 21. Any work around? – praxmon Jan 21 '16 at 14:18
  • Thanks a lot. You saves my life. The tonic code is app:contentInsetEnd="0dp" app:contentInsetStart="0dp" – Md. Sajedul Karim Mar 20 '16 at 16:22
  • This was killing me: app:contentInsetEnd="0dp" app:contentInsetStart="0dp" 10xs – avluis Apr 27 '16 at 23:26
51

Instead of doing so much of work as mentioned by Muzikant and like this answer

    getSupportActionBar().setDisplayShowHomeEnabled(false);
    getSupportActionBar().setDisplayShowTitleEnabled(false);
    getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
    LayoutInflater mInflater = LayoutInflater.from(this);

    View mCustomView = mInflater.inflate(R.layout.action_bar_home, null);
    getSupportActionBar().setCustomView(mCustomView);
    getSupportActionBar().setDisplayShowCustomEnabled(true);
    Toolbar parent =(Toolbar) mCustomView.getParent();//first get parent toolbar of current action bar 
    parent.setContentInsetsAbsolute(0,0);// set padding programmatically to 0dp

You have to add only the last two lines of code to solve your problem.

I hope this might help you and anyone else.

UPDATE: After making some research on it, i found that this solution will not work in some cases. The left side gap (HOME or BACK) will be removed with this but the right side gap (MENU) will remain as is. Below is the solution in these cases.

View v = getSupportActionBar().getCustomView();
LayoutParams lp = v.getLayoutParams();
lp.width = LayoutParams.MATCH_PARENT;
v.setLayoutParams(lp);

Add these four lines to above code, so that the right side gap is also removed from support action bar.

Community
  • 1
  • 1
Amrut Bidri
  • 6,276
  • 6
  • 38
  • 80
31

I think you can also do that in styles. try this. tested it on kitkat

<style name="AppTheme" parent="Theme.AppCompat">
  <item name="toolbarStyle">@style/AppThemeToolbar</item>
</style>

<style name="AppThemeToolbar" parent="Widget.AppCompat.Toolbar" >
  <item name="contentInsetStart">0dp</item>
</style>
GDA
  • 334
  • 2
  • 7
8

None of the other answers worked for me, so I took a look at the actual AppCompat v7 styles, found here.

If you look at the Base.Widget.AppCompat.ActionBar style, it has:

<item name="contentInsetStart">@dimen/abc_action_bar_content_inset_material</item>
<item name="contentInsetEnd">@dimen/abc_action_bar_content_inset_material</item>

So obviously we just need to override those properties in our own action bar style:

<style name="ActionBar" parent="@style/Base.Widget.AppCompat.ActionBar">
        <item name="contentInsetStart">0dp</item>
        <item name="contentInsetEnd">0dp</item>
</style>

This worked great for me, hope it helps others too.

Justin
  • 17,670
  • 38
  • 132
  • 201
  • Yep, as the chosen answer states, the key is the contentInsetStart and contentInsetEnd attributes of the ActionBar/Toolbar. It's valid to define your own style, but you can also set them to 0dp on the attributes of the Toolbar in your xml – Stevie Kideckel Aug 07 '15 at 21:53
1

After much beating my head against the monitor, this worked for me

 Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
        toolbar.setContentInsetStartWithNavigation(0);
        toolbar.setContentInsetEndWithActions(0);
        toolbar.setContentInsetsAbsolute(0, 0);
        toolbar.setPadding(0, 0, 0, 0);

The getCustomView().getParent() is what did the trick

user330844
  • 872
  • 1
  • 12
  • 12
0

I just encountered this problem today as well, then I found out I was having res/values-v21/styles.xml inside my project which was generated automatically by Android Studio and that's the cause.

Why?

Because my res/values-v21/styles.xml's content was:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>
</resources>

And my res/values/styles.xml contained something like:

<style name="BaseAppTheme" parent="android:Theme.Holo.Light">
    <!-- Customize your theme here. -->
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:soundEffectsEnabled">false</item>
</style>

Then when I ran my app on Lollipop, the res/values-v21/styles.xml was used, and that caused exact problem that OP had. So I came to a simple fix is just deleting:

    <style name="BaseAppTheme" parent="android:Theme.Material.Light">
    </style>

in res/values-v21/styles.xml

Leo
  • 1,433
  • 23
  • 40
0

to the point:

 ActionBar actionBar = getSupportActionBar();
                actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
                actionBar.setCustomView(R.layout.actionbar_layout);
                Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
                    toolbar.setContentInsetsAbsolute(0, 0);
                    toolbar.setPadding(0, 0, 0, 0);

make sure importing the right toolbar - android.support.v7.widget.Toolbar;

olibiaz
  • 2,551
  • 4
  • 29
  • 31
Salman Anjum
  • 333
  • 3
  • 7
0

Write these two line in addition with your code

Toolbar toolbar=(Toolbar)viewActionBar.getParent();
toolbar.setContentInsetsAbsolute(0,0);
Anisuzzaman Babla
  • 6,510
  • 7
  • 36
  • 53
0

For anyone who is still having this issue, along with the setting the insets to 0, also change the padding of the toolbar to 0.

supportActionBar?.customView?.apply {
            (parent as Toolbar?)?.setContentInsetsAbsolute(0,0)
            (parent as Toolbar?)?.setContentInsetsRelative(0,0)
            (parent as Toolbar?)?.setPadding(0)
        }
Gabriel
  • 307
  • 2
  • 8