Manually inflating custom view yields different layouts for ActionBar custom view
Asked Answered
R

2

6

Custom view from resource:

// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setCustomView(R.layout.custom_action_bar);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);

the result is:
enter image description here

Custom view manually inflated:

// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
LayoutInflater inflater = (LayoutInflater) this .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.custom_action_bar, null);
actionBar.setCustomView(view);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);

the result is:
enter image description here

custom_action_bar.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" 
    android:weightSum="3">

    <TextView 
        android:id="@+id/bar_title1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:textColor="@color/White"
        android:text="title1"/>
    <TextView 
        android:id="@+id/bar_title2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:textColor="@color/White"
        android:text="title2"/>
    <TextView 
        android:id="@+id/bar_title3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:textColor="@color/White"
        android:text="title3"/>

</LinearLayout>

The first layout shown here is the correct one, because it has weights on its widgets. The second attempt should produce the same result, but it does not.

Ratal answered 8/7, 2013 at 8:7 Comment(2)
can you change in custom_action_bar.xml i have chnaged android:layout_width = fill_parent and removed android:weightSum=3 <LinearLayout xmlns:android="schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="match_parent" android:orientation="horizontal" > Can you share the result if it works for you ?Sod
@Rollno1 I tried it. Your solution works, the fill_parent part is not needed (fill_parent is equivalent to match_parent). Removing the weightsum attribute does the trick.Ratal
E
13

Actually, the issue here is that in second case ActionBar needs additonal layout parameters:

    final ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.custom_action_bar, null);
    actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);

So, it covers all ActionBar area. Looks like by default WRAP_CONTENT llayout parameters get applied to custom view.

Enthronement answered 8/7, 2013 at 8:20 Comment(3)
Interesting. I tried your code and you are right. Even though the custom layout has match_parent already defined for width and height.Ratal
Right, but in order to be applied parent ViewGroup should be passed to inflate(). Actually, ActionBarImpl uses internal ViewGroup during inflation in method setCustomView(int resId) - e.g. setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId, mActionView, false));Enthronement
I was getting absolutely crazy to match all the space with my custon action bar. Finally I did it adding the LayoutParams as sandrstar said.Sunshade
B
9

Another options is to let the ActionBar do the work for you (in this case I'm showing how to do it with the support version).

// Set your custom view
getSupportActionBar().setCustomView(R.layout.custom_action_bar);

// Get the inflated view
View view = getSupportActionBar().getCustomView();

// Do what you want with the view (set the title, custom font etc.)
TextView actionBarTitle = (TextView) view.findViewById(R.id.action_bar_title);
...

// set the custom flag
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM)
Bellamy answered 3/2, 2014 at 22:57 Comment(4)
Smart move Mr.! IMHO this should be the accepted answer. Using Layout Inflater with a 'null' as the root view is the 'root of all evil' for many layout problems as layout_* params that are parent related are ignored upon inflation.Frown
Great answer! Solved my layout problem immediately.Turnheim
@MaciejPigulski 'null' in root is not root-cause, root-cause is in missed understanding of why 'root' is needed in the first place, Only way to fix it - RTFM.Enthronement
@sandrstar, thanks for your valuable insight, especially for the RTFM part, so helpful!Frown

© 2022 - 2024 — McMap. All rights reserved.