Ответ 1
Отвечая на мой собственный вопрос, поскольку мы реализовали это много месяцев назад.
Наша реализация в проекте с открытым исходным кодом.
Я знаю, что есть ExpandableListView, но он поддерживает только до двух уровней. Мне нужен верный вертикальный список дерева, по крайней мере, до 5 уровней (лучше).
Любые предложения?
изменить:
Я вижу разговор об использовании пользовательского адаптера и настройке дополнения на основе уровня элементов.
У меня есть несортированный ArrayList объектов, у которых есть идентификатор и родительский идентификатор, и я динамически добавляю элементы в этот массив.
Может ли кто-нибудь дать мне несколько примеров того, как я могу это сделать?
Отвечая на мой собственный вопрос, поскольку мы реализовали это много месяцев назад.
Наша реализация в проекте с открытым исходным кодом.
У меня была такая же проблема. Вы можете проверить мою реализацию AndroidTreeView.
Его дерево уровня N.
Пользовательский стиль для узлов
Наша компания также открыла для этого решение. Он доступен как библиотека, поэтому очень проста в использовании: http://code.google.com/p/tree-view-list-android/
я решил это для меня, разместив в подобной теме: другой поток
Я нашел ссылку ниже очень, очень полезную. Он описывает альтернативные способы хранения древовидных структур в двухмерных структурах данных (обычно это таблица базы данных).
Я думаю, вы найдете, что парадигму легко понять и реализовать.
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
Как визуализировать это в Android - это еще один вопрос. Я бы, возможно, написал свой собственный виджет с нуля, если решение "заполненных" элементов списка недостаточно.
Я думаю, что если многоуровневый расширяемый список будет выполнен правильно, он действительно работает и отлично выглядит. Вот еще один пример http://code.google.com/p/tree-view-list-android/
Я нашел решение проще для этой проблемы, так как сам я немного промежуточен в своих навыках кодирования. В моей ситуации мне понадобился Windows-themed Tree View, который после мозгового штурма идей я смог реализовать с почти никакой кодировкой!
Вот трюк: используйте WebView и встроенную HTML-страницу, чтобы отобразить пользовательский Tree View, и используйте Android-интерфейс с удобной поддержкой JavaScript для получения выбора и кликов: Доказательство концептуального примера в блоге Android-er
С помощью этой возможности мы можем воспользоваться большой коллекцией фрагментов управления JS/CSS по всему Интернету. Тематический элемент управления jQuery TreeView для Windows7 - jsTree
Множество возможностей и мощности с Android там, счастливое кодирование!
Я согласен с pjv, по крайней мере, для устройств с размером телефона. Было бы лучше организовать виджет, чтобы показывать одну группу братьев и сестер за раз в ListView. Это можно сделать в одном действии, которое отслеживает его положение в дереве. Он может отображать заголовок с панировочными сухарями, показывающий путь к родительскому элементу, отображаемому в настоящее время.
Многоуровневое древовидное представление может быть подходящим для планшетного устройства, но на телефоне недостаточно недвижимости для поддержки предлагаемых 5 уровней (при этом все должно быть достаточно большим для пальцев).
Тем не менее, если вы настроены на древовидное представление, не смотрите на подклассу ExpandableListView. Он работает внутренне, упаковывая родительский и дочерний индексы (каждый int) в один длинный. Это внутреннее представление делает невозможным выходить за пределы двух уровней.
Я бы начал с того, что структура данных более представила то, что она должна была содержать. Поскольку у вас есть массив элементов, и каждый ребенок может иметь собственный массив элементов, каждый со своим собственным массивом и т.д. Я бы подумал об использовании класса с двумя членами: объекта, который представляет данные для этого конкретного элемента и массива в котором содержатся предметы. Каждый ребенок сам будет экземпляром класса, так что у него тоже могут быть дети.
частный класс ParentAndKids { Object parent; Массив детей; }
Затем ваш адаптер будет иметь массив объектов ParentAndKids, который представляет верхний слой. Вы должны добавлять и удалять элементы списка, основываясь на том, какие родители были расширены.
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;
}
}
}