web-dev-qa-db-fra.com

ActionBar - vue personnalisée avec ImageView centrée, éléments d'action sur les côtés

J'ai besoin de centrer un logo personnalisé (à l'aide d'une ImageView) dans la barre d'actions pour l'activité "Accueil". J'utilise ABS pour ce projet. Ceci est très similaire à une autre question publiée sur S.O. ( logo ActionBar centré et éléments d'action sur les côtés ), mais je ne sais pas si ImageView ou le menu de recherche fait une différence, car je n'obtiens pas les résultats que je recherche (un centré image), ou si je me trompe. Fondamentalement, j'ai défini une icône à gauche, inséré la vue personnalisée au centre et j'ai une icône de recherche à droite (Menu Options). L'image apparaît un peu à droite de l'icône, mais elle est toujours à gauche du centre. Tout pointeur sur la façon de centrer une ImageView dans la barre d'action serait grandement apprécié.

Home.Java:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
            .getSystemService(LAYOUT_INFLATER_SERVICE);

    final View customActionBarView = inflater.inflate(
            R.layout.actionbar_custom_view_home, null);

    /* Show the custom action bar view and hide the normal Home icon and title */
    final ActionBar actionBar = getSupportActionBar();
    actionBar.setHomeButtonEnabled(true);
    actionBar.setDisplayHomeAsUpEnabled(false);
    actionBar.setDisplayShowTitleEnabled(false);
    actionBar.setIcon(R.drawable.ic_ab_som);
    actionBar.setCustomView(customActionBarView);
    actionBar.setDisplayShowCustomEnabled(true);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = new MenuInflater(this);
    inflater.inflate(R.menu.search, menu);
    return true;
}

res/layout/actionbar_custom_view_home.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:layout_gravity="center">

<ImageView
    Android:id="@+id/actionBarLogo"
    Android:contentDescription="@string/application_name"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:clickable="false"
    Android:duplicateParentState="false"
    Android:focusable="false"
    Android:longClickable="false"
    Android:padding="@dimen/padding_small"
    Android:src="@drawable/logo_horizontal" />

</LinearLayout>

res/menu/search.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item 
        Android:id="@id/search_item"
        Android:icon="?attr/action_search"
        Android:title="@string/search_label"
        Android:showAsAction="ifRoom|collapseActionView">
    </item>
</menu>
41
Doug Sparling

Expliqué:

enter image description here

Le conteneur rose, est le véritable espace où vous ajouterez la vue.

L'astuce consiste à faire quelques calculs, pour centrer la vue (peu importe) au milieu.

Dans mon cas, la vue était une TextView. Voici ma méthode complète:

public void addTextToActionBar( String textToSet )
{
    mActionbar.setDisplayShowCustomEnabled( true );

    // Inflate the custom view
    LayoutInflater inflater = LayoutInflater.from( this );
    View header = inflater.inflate( R.layout.actionbar_header, null );

    //Here do whatever you need to do with the view (set text if it's a textview or whatever)
    TextView tv = (TextView) header.findViewById( R.id.program_title );
    tv.setText( textToSet );

    // Magic happens to center it.
    int actionBarWidth = DeviceHelper.getDeviceWidth( this ); //Google for this method. Kinda easy.

    tv.measure( 0, 0 );
    int tvSize = tv.getMeasuredWidth();

    try
    {
        int leftSpace = 0;

        View homeButton = findViewById( Android.R.id.home );
        final ViewGroup holder = (ViewGroup) homeButton.getParent();

        View firstChild =  holder.getChildAt( 0 );
        View secondChild =  holder.getChildAt( 1 );

        leftSpace = firstChild.getWidth()+secondChild.getWidth();
    }
    catch ( Exception ignored )
    {}

    mActionbar.setCustomView( header );

    if ( null != header )
    {
        ActionBar.LayoutParams params = (ActionBar.LayoutParams) header.getLayoutParams();

        if ( null != params )
        {
            int leftMargin =  ( actionBarWidth / 2 - ( leftSpace ) ) - ( tvSize / 2 ) ;

            params.leftMargin = 0 >= leftMargin ? 0 : leftMargin;
        }
    }
}

Disposition:

<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:gravity="center_horizontal|center_vertical|center"
    Android:orientation="horizontal" >

<TextView
    Android:id="@+id/program_title"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:textColor="@Android:color/white"
    Android:contentDescription="@string/content_description_program_title"
    Android:ellipsize="end"
    Android:maxLines="1"
    Android:textSize="22sp"/>

</RelativeLayout>

Prendre plaisir.

18
Reinherd

Si vous voulez voir l'image dans Center of ActionBar, utilisez:

enter image description here

remplacez simplement getActionBar(); par getSupportActionBar(); dans le code ci-dessous

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ActionBar actionBar = getActionBar();
        actionBar.setCustomView(R.layout.actionbar_custom_view_home);
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setDisplayShowCustomEnabled(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

votre actionbar_custom_view_home.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    Android:gravity="center"
    Android:orientation="horizontal" >

    <ImageView
        Android:id="@+id/actionBarLogo"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:clickable="false"
        Android:focusable="false"
        Android:longClickable="false"
        Android:src="@drawable/ic_launcher" />

</LinearLayout>

Masquer l'icône de la barre d'action

enter image description here

final ActionBar actionBar = getActionBar();
actionBar.setCustomView(R.layout.actionbar_custom_view_home);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);

Remarque: pour <11 API, utilisez getSupportActionBar () et> 11 API, utilisez getActionBar ()


MODIFIÉ: 02/03/16 pour Barre d'outils

<Android.support.v7.widget.Toolbar
   style="@style/ToolBarStyle"
   xmlns:Android="http://schemas.Android.com/apk/res/Android"
   Android:layout_width="match_parent"
   Android:layout_height="wrap_content"
   Android:background="?attr/colorPrimary"
   Android:minHeight="@dimen/abc_action_bar_default_height_material">

    <ImageView
        Android:layout_width="wrap_content"
        Android:contentDescription="@string/logo"
        Android:layout_height="wrap_content"
        Android:layout_gravity="center"
        Android:src="@drawable/ic_launcher"/>

 </Android.support.v7.widget.Toolbar>
66
Dhaval Parmar

J'ai rencontré ce problème, voici ma solution:

   ActionBar.LayoutParams layoutParams = new  ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, 
ActionBar.LayoutParams.MATCH_PARENT);
   layoutParams.gravity = Gravity.CENTER_HORIZONTAL|Gravity.CENTER_HORIZONTAL;
    actionBar.setCustomView(yourCustomView,layoutParams);
6
jeason_tse

L'imageView de votre code est centrée par rapport à LinearLayout et non à la barre d'actions. Vous pouvez ajouter une marge gauche (Android: layout_marginLeft) à la mise en page pour ajuster la position de l'image.

Une autre façon de le faire n'est pas d'ajouter une icône et des éléments d'action à la barre d'actions, mais d'utiliser une disposition personnalisée avec une icône et des boutons à l'intérieur. Mais vous devrez gérer les éléments d'action vous-même dans ce cas.

3
Const

La seule chose que j'ai trouvé fonctionnait est de mettre (mettre à droite ou à gauche au besoin, ou les deux):

Android:layout_marginLeft|Right="?attr/actionBarSize"

que j'ai trouvé ici: http://sourcey.com/Android-custom-centered-actionbar-with-material-design/

2
walla

Je suis confronté au même problème et je suggère la solution suivante:

  1. dans votre res/layout/actionbar_custom_view_home.xml changez la largeur de la mise en page en wrap_content:

    Android:layout_width="wrap_content"
    
  2. Obtenez la largeur de la barre d'action comme ceci:

    Display display = getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    //width of action bar is the same as width of whole screen
    final int actionBarWidth = size.x;
    
  3. Ajoutez layoutListener à votre customActionBarView:

    customActionBarView.addOnLayoutChangeListener(
      new OnLayoutChangeListener() {
    
        @Override
        public void onGlobalLayout() {
          float x = customActionBarView.getX();
          int logoImageWidth = imageLogo.getWidth();
          int logoPosition = actionBarWidth / 2 - logoImageWidth / 2;
          if (x != logoPosition) {
            customActionBarView.setX(logoPosition);
            customActionBarView.requestLayout();
          } else {
            customActionBarView.removeOnLayoutChangeListener(this);
          }
        }
      }
    );
    
2
Alexey Osminin

Tard dans la soirée, mais au cas où cela aiderait quelqu'un d'autre - utilisez une liste de calques et définissez-la comme arrière-plan. Sinon, le logo sera centré en fonction de l'espace restant, et non de la barre d'outils entière comme le mentionne Reinherd.

Vous pouvez utiliser une liste de calques avec une couleur d'arrière-plan statique et une image dont la gravité est réglée au centre comme ci-dessous. J'espère que ça aide!

toolbar.axml

<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/toolbar"
    Android:layout_width="match_parent"
    Android:layout_height="?attr/actionBarSize"
    Android:background="@drawable/toolbar_background"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    app:layout_scrollFlags="scroll|enterAlways"
    app:layout_collapseMode="pin">
</Android.support.v7.widget.Toolbar>

toolbar_background.xml

<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item>
    <shape Android:shape="rectangle">
      <solid Android:color="@color/colorPrimary" />
    </shape>
  </item>
  <item>
    <bitmap Android:src="@drawable/logo" Android:gravity="center" />
  </item>
</layer-list>
2
Blueberry