web-dev-qa-db-fra.com

Ajouter des icônes au tiroir de navigation Android?

J'ai parcouru le Web pour trouver une réponse à cette question, mais je n'arrive pas à en trouver une, même dans la documentation officielle d'Android.

Je suis en train de créer une application qui implémente la nouvelle disposition du tiroir de navigation d'Android. La documentation de cette mise en page peut être trouvée ici et ici .

Dans la documentation de conception ainsi que dans un certain nombre d'applications populaires telles que Facebook et Google Currents, les éléments du tiroir sont précédés d'icônes.

La documentation de conception elle-même les mentionne, sous "Contenu du tiroir de navigation".

Les cibles de navigation peuvent avoir des icônes principales facultatives ainsi que des compteurs de fin. Utilisez les compteurs pour informer les utilisateurs d’un changement d’état des données dans la vue correspondante.

Malheureusement, la documentation pour les développeurs ne mentionne pas comment implémenter des icônes dans cette configuration. Il décrit comment implémenter la liste d'éléments de la manière suivante:

public class MainActivity extends Activity {
private String[] mPlanetTitles;
private ListView mDrawerList;
...

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

    mPlanetTitles = getResources().getStringArray(R.array.planets_array);
    mDrawerList = (ListView) findViewById(R.id.left_drawer);

    // Set the adapter for the list view
    mDrawerList.setAdapter(new ArrayAdapter<String>(this,
            R.layout.drawer_list_item, mPlanetTitles));
    // Set the list's click listener
    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

    ...
}
}

Étant donné que leur implémentation utilise getStringArray (), je ne peux en aucun cas penser à modifier le xml de l'élément de ligne pour inclure une icône.

Cela est déconcertant, car de nombreuses applications semblent implémenter les icônes avant chaque élément de texte, et la documentation de Design fait même référence à l'ajout d'icônes. Je pense qu’il doit exister un simple appel d’API pour pouvoir ajouter ces icônes, mais la seule implémentation que j’ai trouvée jusqu’à présent semble ridiculement compliquée.

Est-ce que quelqu'un sait comment ajouter des icônes aux éléments du tiroir de navigation? Y a-t-il un moyen de faire cela avec un simple appel d'API ou faut-il que toutes ces sociétés (Facebook, Google, etc.) aient dû trouver des moyens de contourner le problème?

Merci tout le monde.

17
bean

Étant donné que leur implémentation utilise getStringArray (), je ne peux en aucun cas penser à modifier le xml de l'élément de ligne pour inclure une icône.

Le choix des données de modèle pour une ListAdapter n'a aucun impact sur le fait que les lignes créées par cette ListAdapter peuvent avoir des icônes.

Est-ce que quelqu'un sait comment ajouter des icônes aux éléments du tiroir de navigation?

Mettez une ImageView dans votre disposition de ligne pour la ListAdapter. Remplissez cette ImageView via votre ListAdapter, par exemple en remplaçant getView() par votre ArrayAdapter. IOW, vous le faites de la même manière que pour n'importe quel autre ListView, comme cela se fait depuis des années.

Est-il possible de faire cela avec un simple appel d'API

Cela dépend de vos définitions de "simple" et "appel API".

7
CommonsWare

Créez une classe d'adaptateur comme .. 

public class AdapterClass  extends ArrayAdapter<String> {
Context context;
private ArrayList<String> TextValue = new ArrayList<String>();

public AdapterClass(Context context, ArrayList<String> TextValue) {
    super(context, R.layout.row_of_drawer, TextValue);
    this.context = context;
    this.TextValue= TextValue;

}


@Override
public View getView(int position, View coverView, ViewGroup parent) {
    // TODO Auto-generated method stub

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.row_of_drawer,
            parent, false);

    TextView text1 = (TextView)rowView.findViewById(R.id.text1);
    text1.setText(TextValue.get(position));

    return rowView;

}

}

Et créez un changement de votre activité principale.

utilisation 

   AdapterClass adClass = new AdapterClass(MainActivity.this, name_of_arrayList);

    mDrawerList.setAdapter(adClass);

au lieu de 

 mDrawerList.setAdapter(new ArrayAdapter<String>(this,
        R.layout.drawer_list_item, mPlanetTitles));
4
TKumar

Pour structurer cela clairement, j'ai créé quelques lignes de code supplémentaires pour une implémentation orientée objet qui génère tout d'un tableau NavigationItems - une classe Java contenant des champs pour le texte, l'icône et le fragment d'un élément de menu:

Dans MainActivity, ma navigation est simplement définie par le tableau:

NavigationAdapter navigationMenuAdapter;
NavigationItem[] navigationMenuItems = {
    new NavigationItem(R.string.menu_home, R.drawable.ic_menu_home, new MainFragment()),
    new NavigationItem(R.string.menu_statistics, R.drawable.ic_statistics, new StatisticsFragment()),
    new NavigationItem(R.string.menu_settings, R.drawable.ic_settings, new SettingsFragment()),
};

protected void onCreate(Bundle savedInstanceState) {
    ...
    navigationMenuAdapter = new NavigationAdapter(this, navigationMenuItems);
    mDrawerList.setAdapter(navigationMenuAdapter);
}

...
private void selectItem(int position) {
    // Insert the fragment by replacing any existing fragment
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
                   .replace(R.id.content_frame, navigationMenuItems[position].fragment)
                   .commit();

    mDrawerList.setItemChecked(position, true);
    setTitle(navigationMenuItems[position].stringTitle);
    mDrawerLayout.closeDrawer(mDrawerList);
}

La classe NavigationItem:

public class NavigationItem
{
    /**
     * 
     * @param stringTitle The id of the string resource of the text of the item.
     * @param drawableIcon The id of the drawable resource of icon of the item.
     * @param fragment The Fragment to be loaded upon selecting the item.
     */
    public NavigationItem(int stringTitle, int drawableIcon, Fragment fragment)
    {
        this.stringTitle = stringTitle;
        this.drawableIcon = drawableIcon;
        this.fragment = fragment;
    }

    /**
     * The id of the string resource of the text of the item.
     */
    public int stringTitle;

    /**
     * The id of the drawable resource of icon of the item.
     */
    public int drawableIcon;

    /**
     * The Fragment to be loaded upon selecting the item.
     */
    public Fragment fragment;
}

Et l'adaptateur de navigation:

public class NavigationAdapter extends BaseAdapter {
    private Context context;
    private NavigationItem[] navigationItems;

    public NavigationAdapter(Context context, NavigationItem[] items) {
        this.context = context;
        navigationItems = items;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = null;
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.list_item_navigation, parent, false);
        } else {
            row = convertView;
        }

        TextView tvTitle = (TextView) row.findViewById(R.id.textView);
        ImageView ivIcon = (ImageView) row.findViewById(R.id.imageView);

        tvTitle.setText(navigationItems[position].stringTitle);
        ivIcon.setImageResource(navigationItems[position].drawableIcon);
        return row;
    }
}

qui utilise une structure XML très basique, list_item_navigation, qui ne contient que ImageView et TextView.

2
Cibes

Le tableau de chaînes n'est pas la disposition des lignes. Votre R.layout.drawer_list_item représente la disposition de chaque ligne de la liste. Si vous souhaitez inclure une image (ou même une autre disposition de ligne compliquée), vous devez inclure la vue de l'image dans cette disposition personnalisée xml en remplaçant R.layout.drawer_list_item xml. 

En ce qui concerne la définition de l'image ou du texte dans chaque ligne différente, tout est fait dans la méthode getView() de l'adaptateur de matrice. Voici un exemple approximatif (en supposant qu'il y ait une vue texte et une vue image dans la ligne):

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.revise_listview, parent,false);

    TextView tv = (TextView)convertView.findViewById(R.id.text);
    ImageView iv = (ImageView)convertView.findViewById(R.id.image);

    tv1.setText(stringArray.get(i));
    if(//condition) {
        iv.setImageResource(R.drawable.imagexx);
    }
    return convertView;
}

Un moyen plus efficace d'implémenter les vues pour chaque ligne consiste à utiliser le modèle de titulaire de vue. Vous trouverez des exemples parmi d’autres exemples here .

2
Neoh