В моем приложении мне захотелось реализовать нечто подобное на примере списка друзей социальной сети. Прочитав эту статью, где используется коллекция коллекций:
private ArrayList<ArrayList<String>> mGroups;
А так же покопавшись в исходниках, я решил объединить и доработать эти примеры и вот что у меня получилось:
Приступаем к реализации. Создаем новый проект с классом ListActivity, который наследуется от ActionBarActivity (можно и от Activity). Отредактируем код нашей активности (activity_list.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_list" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".ListActivity" > <ExpandableListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:indicatorLeft="200dp" /> </LinearLayout>
Ничего сложного — вертикальный LinearLayout, который содержит в себе двухуровневый список ExpandableListView.
Далее необходимо описать пункт списка — item_friend.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/friendLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:id="@+id/photoFriend" android:layout_width="60dp" android:layout_height="60dp" android:contentDescription="@string/todo" android:src="@android:drawable/ic_menu_camera" /> <TextView android:id="@+id/f_s_names" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginLeft="10dp" android:layout_weight="1" android:text="@string/Def_fname" android:textAppearance="?android:attr/textAppearanceMedium" /> <ImageView android:id="@+id/congratuated" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginRight="7dp" android:contentDescription="@string/todo" android:src="@android:drawable/checkbox_on_background" android:visibility="gone" /> </LinearLayout>
Элемент списка содержит фотографию в ImageView, имя и фамилию в TextView, а так же еще один ImageView. Набор элементов может быть абсолютно любым и ограничивается лишь фантазией разработчика.
Опишем меню пункта списка — item_friend_menu.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:layout_marginTop="10dp" android:orientation="vertical" android:background="#E0E0E0" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="25dp" android:orientation="horizontal" > <TextView android:id="@+id/textNick" style="@style/Fm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/nick_" /> <TextView android:id="@+id/m_Nick" style="@style/Fm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="@string/empty" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="25dp" android:orientation="horizontal" > <TextView android:id="@+id/textSex" style="@style/Fm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sex_" /> <TextView android:id="@+id/m_Sex" style="@style/Fm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="@string/man" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="25dp" android:orientation="horizontal" > <TextView android:id="@+id/textBdate" style="@style/Fm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/brithday_" /> <TextView android:id="@+id/m_Bdate" style="@style/Fm" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="5dp" android:layout_weight="1" android:text="@string/_17_2_1985" /> <ImageButton android:id="@+id/imageEditdate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="7dp" android:adjustViewBounds="true" android:background="@android:color/transparent" android:contentDescription="@string/todo" android:scaleType="fitCenter" android:src="@android:drawable/ic_menu_edit" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="25dp" android:orientation="horizontal" > <TextView android:id="@+id/textTemplate" style="@style/Fm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/template_" /> <TextView android:id="@+id/m_Template" style="@style/Fm" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="5dp" android:layout_weight="1" android:text="@string/temp_name" /> <ImageButton android:id="@+id/imageSelectTemp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="7dp" android:adjustViewBounds="true" android:background="@android:color/transparent" android:scaleType="fitCenter" android:src="@android:drawable/ic_menu_edit" android:contentDescription="@string/todo"/> </LinearLayout> </LinearLayout>
С меню элемента все аналогично — описываем то, что хотим увидеть на дисплее.
Все необходимые XML готовы, теперь приступим к кодингу на Java. Нам понадобятся два вспомогательных класса, описывающих содержимое элемента списка и меню этого элемента. Сначала опишем меню в классе FriendMenu.java:
public class FriendMenu { public FriendMenu() { } private String nick, bdate, template_name; private int sex; public String getNick() { return nick; } public void setNick(String nick) { this.nick = nick; } public String getBdate() { return bdate; } public void setBdate(String bdate) { this.bdate = bdate; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public String getTemplate_name() { return template_name; } public void setTemplate_name(String template_name) { this.template_name = template_name; } public int getId() { return user_id; } public void setId(int id) { this.user_id = id; } }
Класс используется скорее не как меню, а как дополнительная информация об элементе списка, которую необходимо отображать по желанию пользователя.
Здесь 4 поля — ник, день рождения, пол и поле template_name, а так же методы get* и set* для работы с полями класса. В качестве поля sex можно использовать тип boolean, но мне пришлось использовать int, т.к. в списке друзей, получаемом с сервера, пол имеет тип целого числа(?).
Теперь опишем класс элемента списка Friend.java:
public class Friend { public Friend() { } private ArrayList<FriendMenu> menu; private Bitmap bmp; private String text; private boolean congratulated; public ArrayList<FriendMenu> getMenu() { return menu; } public void setMenu(ArrayList<FriendMenu> menus) { this.menu = menus; } public boolean isCongratulated() { return congratulated; } public void setCongratulated(boolean congratulated) { this.congratulated = congratulated; } public Bitmap getBmp() { return bmp; } public void setBmp(Bitmap bmp) { this.bmp=bmp; } public String getText() { return text; } public void setText(String text) { this.text = text; } }
Поле bmp хранит изображение для ImageView элемента списка, поле text — имя и фамилию, поле congratulated отвечает за показ галочки в ImageView.
В классе содиржится поле menu — коллекция менюшек для одного элемента списка. Помимо собственной информации внутри себя элемент 1-го уровня содержит информацию о своем меню. В моем случае menu будет состоять только из одного элемента.
Здесь у вас, уважаемые читатели, наверняка возникнет замечание, что можно было бы не цеплять сразу весь Layout в качестве элемента списка второго уровня, а разбить его на составляющие, т.к. внутреннее содержимое примерно одинаковое (горизонтальный LinearLayout, внутри которого 2 TextView [и ImageButton]), а так же добавлять по мере необходимости. Согласен, у меня не оптимальное решение.
Теперь самое главное — создать свой класс, который наследуется от BaseExpandableListAdapter — FriendsAdapted.java.
public class FriendsAdapted extends BaseExpandableListAdapter { private ArrayList<Friend> friends; private LayoutInflater inflater; // каждый друг внутри себя содержит свое меню (доп. информацию). public FriendsAdapted(Context cont, ArrayList<Friend> list) { inflater = LayoutInflater.from(cont); friends = list; } @Override public int getGroupCount() { return friends.size(); } @Override public int getChildrenCount(int groupPosition) { return friends.get(groupPosition).getMenu().size(); } @Override public Object getGroup(int groupPosition) { return friends.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return friends.get(groupPosition).getMenu().get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return true; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { if (convertView == null) { convertView = inflater.inflate(R.layout.item_friend, null); } // получили группу (друга) Friend fr = friends.get(groupPosition); ((TextView) convertView.findViewById(R.id.f_s_names)).setText(fr .getText()); // ((ImageView) // convertView.findViewById(R.id.photoFriend)).setImageBitmap(fr.getBmp()); ((ImageView) convertView.findViewById(R.id.congratuated)) .setVisibility((fr.isCongratulated() ? View.VISIBLE : View.GONE)); return convertView; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { FriendMenu menu = (FriendMenu) getChild(groupPosition, childPosition); convertView = inflater .inflate(R.layout.item_friend_menu, parent, false); ((TextView) convertView.findViewById(R.id.m_Nick)).setText(menu .getNick()); switch (menu.getSex()) { case 1: ((TextView) convertView.findViewById(R.id.m_Sex)) .setText(R.string.sex_man); break; case 0: ((TextView) convertView.findViewById(R.id.m_Sex)) .setText(R.string.sex_fem); break; } ((TextView) convertView.findViewById(R.id.m_Bdate)).setText(menu .getBdate()); ((TextView) convertView.findViewById(R.id.m_Template)).setText(menu .getTemplate_name()); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } }
Класс содержит коллекцию друзей, а в которой каждый друг содержит свое собственное меню. Для заполнения информацией элементов первого и второго уровней необходимо переопределить методы getGroupView и getChildView соответственно. С помощью LayoutInflater можно подключать кастомизированные Layout‘ы.
Каждому View можно задает свои:
- Selector
- ClickListener
- LongClickListener
- и другие обработчики
Теперь осталось отобразись список. Код ListActivity.java:
В моем приложении была предварительно заполненная база данных с таблицей друзей, поэтому список буду заполнять из нее:
public class ListActivity extends ActionBarActivity { ExpandableListView list_w; static private SQLdb data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); list_w = (ExpandableListView) findViewById(R.id.listView1); data = new SQLdb(this, 2); SQLiteDatabase db = data.getReadableDatabase(); Cursor c = db.rawQuery("select * from friends", null); ArrayList<Friend> friends = new ArrayList<Friend>(); if (c.moveToFirst()) { for (int i = 0; i < c.getCount(); ++i) { Friend friend = new Friend(); ArrayList<FriendMenu> menus = new ArrayList<FriendMenu>(); FriendMenu menu = new FriendMenu(); menu.setBdate(c.getString(c.getColumnIndex("bdate"))); menu.setNick(c.getString(c.getColumnIndex("nickname"))); menu.setSex(c.getInt(c.getColumnIndex("sex"))); menus.add(menu); friend.setMenu(menus); friend.setText(c.getString(c.getColumnIndex("fname")) + " " + c.getString(c.getColumnIndex("sname"))); if (i % 2 == 0) { friend.setCongratulated(true); } friends.add(friend); if (!c.moveToNext()) { break; } } } else Toast.makeText(this, "You have not friends!", Toast.LENGTH_SHORT).show(); c.close(); db.close(); FriendsAdapted friendsadapter=new FriendsAdapted(this,friends); list_w.setAdapter(friendsadapter); list_w.setDivider(getResources().getDrawable(R.drawable.line)); list_w.setDividerHeight(2); } }
На этом все. Надеюсь, моя статья поможет начинающим андроид-разработчикам.
ссылка на оригинал статьи http://habrahabr.ru/post/227549/
Добавить комментарий