web-dev-qa-db-fra.com

Android Treeview

Je sais qu'il y a ExpandableListView mais il ne prend en charge que 2 niveaux. J'ai besoin d'une véritable liste verticale en treeview avec au moins jusqu'à ~ 5 niveaux (plus c'est mieux).

Aucune suggestion?

éditer:

Je vois parler de l'utilisation d'un adaptateur personnalisé et de la définition du rembourrage en fonction du niveau des éléments.

J'ai une ArrayList non triée d'objets qui ont un ID et un ID parent, et j'ajoute dynamiquement des éléments à ce tableau également.

Quelqu'un peut-il me donner des exemples de la façon dont je peux procéder?

40
Daniel Sloof

Répondre à ma propre question, puisque nous l'avons mis en œuvre il y a plusieurs mois.

Notre implémentation dans un projet open-source.

6
Daniel Sloof

J'ai eu le même problème. Vous pouvez consulter mon implémentation AndroidTreeView .

  • Son arbre de niveau N.

  • Style personnalisé pour les nœuds

  • Enregistrer l'état après rotation

AndroidTreeView

17
bmelnychuk

Notre entreprise a également opté pour une solution open source. Il est disponible en bibliothèque, donc très facile à utiliser: http://code.google.com/p/tree-view-list-Android/

enter image description here

14
Jarek Potiuk

je l'ai résolu pour moi, en postant dans un fil similaire: autre fil

enter image description here

10
2red13

J'ai trouvé une solution plus facile à ce problème, car je suis moi-même quelque peu intermédiaire dans mes compétences en codage. Dans ma situation, j'avais besoin d'un sur le thème Windows Tree View, que, après des idées de brainstorming, j'ai pu implémenter avec pratiquement aucun codage!

Voici l'astuce: utilisez une WebView et une page HTML intégrée pour afficher une arborescence personnalisée, et utilisez l'interface de communication JavaScript super pratique d'Android pour recevoir les sélections et les clics : Exemple de preuve de concept sur le blog Android-er

Avec cette puissance, nous pouvons tirer parti d'une large collection d'extraits de contrôle JS/CSS sur le Web. Themeable Windows7-Style jQuery TreeView control - jsTree

Beaucoup de possibilités et de puissance avec Android là-bas, codage heureux!

4
Aaron Gillion

J'ai trouvé le lien ci-dessous très, très utile. Il décrit des méthodes alternatives de stockage des structures arborescentes dans des structures de données bidimensionnelles (généralement une table de base de données).

Je pense que vous trouverez le paradigme facile à comprendre et à mettre en œuvre.

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Pour savoir comment visualiser cela dans Android est une autre question. J'écrirais peut-être mon propre widget à partir de zéro si la solution des éléments de liste "rembourrés" n'est pas suffisante.

3
dbm

Je pense que si la liste extensible à plusieurs niveaux est effectuée correctement, cela fonctionne et a fière allure. Voici un autre exemple de http://code.google.com/p/tree-view-list-Android/

enter image description here

3
dotsa

Je suis d'accord avec pjv, au moins pour les appareils de la taille d'un téléphone. Il serait préférable d'organiser le widget pour afficher un groupe de frères et sœurs à la fois dans un ListView. Cela pourrait être fait en une seule activité qui garde une trace de sa position dans l'arbre. Il pourrait afficher un en-tête avec du fil d'Ariane indiquant le chemin d'accès au parent des éléments actuellement affichés.

Une vue arborescente à plusieurs niveaux peut être appropriée pour une tablette, mais un téléphone ne dispose pas de suffisamment d'espace pour prendre en charge les 5 niveaux proposés (tout doit être suffisamment grand pour les doigts).

Néanmoins, si vous êtes défini sur une arborescence, ne regardez pas le sous-classement de ExpandableListView. Il fonctionne en interne en regroupant les indices parent et enfant (chacun un int) dans un seul long. Cette représentation interne rend pratiquement impossible d'étendre au-delà de 2 niveaux.

2
Ted Hopp
package com.expand.search;

import Android.app.ExpandableListActivity;
import Android.os.Bundle;
import Android.view.ContextMenu;
import Android.view.Gravity;
import Android.view.MenuItem;
import Android.view.View;
import Android.view.ViewGroup;
import Android.view.ContextMenu.ContextMenuInfo;
import Android.widget.AbsListView;
import Android.widget.BaseExpandableListAdapter;
import Android.widget.ExpandableListAdapter;
import Android.widget.ExpandableListView;
import Android.widget.TextView;
import Android.widget.Toast;
import Android.widget.ExpandableListView.ExpandableListContextMenuInfo;

   /** Demonstrates expandable lists using a custom {@link ExpandableListAdapter}
    * from {@link BaseExpandableListAdapter}.
   */
public class expands extends ExpandableListActivity {

ExpandableListAdapter mAdapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set up our adapter
    mAdapter = new MyExpandableListAdapter();
    setListAdapter(mAdapter);
    registerForContextMenu(getExpandableListView());
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    menu.setHeaderTitle("Sample menu");
    menu.add(0, 0, 0, R.string.expandable_list_sample_action);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();

    String title = ((TextView) info.targetView).getText().toString();

    int type = ExpandableListView.getPackedPositionType(info.packedPosition);
    if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
        int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
        int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition); 
        Toast.makeText(this, title + ": Child " + childPos + " clicked in group " + groupPos,   
                Toast.LENGTH_SHORT).show();
        return true;
    } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
        int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition); 
        Toast.makeText(this, title + ": Group " + groupPos + " clicked", Toast.LENGTH_SHORT).show();
        return true;
    }

    return false;
}

/** A simple adapter which maintains an ArrayList of photo resource Ids. 
 * Each photo is displayed as an image. This adapter supports clearing the
 * list of photos and adding a new photo.
 */
public class MyExpandableListAdapter extends BaseExpandableListAdapter {
    // Sample data set.  children[i] contains the children (String[]) for groups[i].
    private String[] groups = { "Category1", "Category2", "Category3", "Category4" };
    private String[][] children = {
            { "Charity1", "Charity2", "Charity3", "Charity4" },
            { "Charity5", "Charity6", "Charity7", "Charity8" },
            { "Charity9", "Charity10" },
            { "Charity11", "Charity12" }
    };

    public Object getChild(int groupPosition, int childPosition) {
        return children[groupPosition][childPosition];
    }

    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    public int getChildrenCount(int groupPosition) {
        return children[groupPosition].length;
    }

    public TextView getGenericView() {
        // Layout parameters for the ExpandableListView
        AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, 64);

        TextView textView = new TextView(expands.this);
        textView.setLayoutParams(lp);
        // Center the text vertically
        textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
        // Set the text starting position
        textView.setPadding(36, 0, 0, 0);
        return textView;
    }

    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
            View convertView, ViewGroup parent) {
        TextView textView = getGenericView();
        textView.setText(getChild(groupPosition, childPosition).toString());
        return textView;
    }

    public Object getGroup(int groupPosition) {
        return groups[groupPosition];
    }

    public int getGroupCount() {
        return groups.length;
    }

    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
            ViewGroup parent) {
        TextView textView = getGenericView();
        textView.setText(getGroup(groupPosition).toString());
        return textView;
    }

    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

    public boolean hasStableIds() {
        return true;
    }
}

}

2
Arun

Je commencerais par rendre la structure de données plus représentative de ce qu'elle est censée contenir. Puisque vous avez un tableau d'éléments et que chaque enfant peut avoir son propre tableau d'éléments, chacun avec son propre tableau, etc. J'envisagerais d'utiliser une classe avec deux membres: un objet qui représente les données de cet élément particulier et un tableau qui détient les enfants de l'article. Chaque enfant serait lui-même une instance de la classe afin qu'il puisse, lui aussi, avoir des enfants.

classe privée ParentAndKids {Object parent; Array enfants; }

Votre adaptateur aurait alors un tableau d'objets ParentAndKids qui représente la couche supérieure. Vous devez ajouter et supprimer des éléments de liste en fonction des parents qui ont été développés.

1
Ginger McMurray