안드로이드 Expandable Recycler View
프로그래밍/Android 관련2018. 2. 22. 20:41
안녕하세요. 개발자 드리머즈입니다.
Expandable ListView(RecyclerView)가 필요해서 인터넷을 찾아보다 괜찮은 예제를 발견했습니다.
(이것을 한글로 뭐라고 불러야 할 지 잘 모르겠네요. 펼치기/접기 가능한 리스트뷰/리싸이클러뷰? 2레벨 리스트뷰?리싸이클러뷰?)
데모 영상
소스 복붙해서 직접 테스트한 데모 영상입니다.
소스코드
소스를 보면 java파일은 단 2개로 아주 간단하며 안드로이드 기본 라이브러리만 사용하고 있기때문에 찝찝하지 않습니다. 개인마다 원하는 동작이 약간씩 다를 수 있기 때문에 소스를 조금 수정해서 사용하면 될 것 같습니다.
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public class MainActivity extends AppCompatActivity { private RecyclerView recyclerview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerview = findViewById(R.id.recyclerview); recyclerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); List<ExpandableListAdapter.Item> data = new ArrayList<>(); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.HEADER, "Fruits")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Apple")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Orange")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Banana")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.HEADER, "Cars")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Audi")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Aston Martin")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "BMW")); data.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Cadillac")); ExpandableListAdapter.Item places = new ExpandableListAdapter.Item(ExpandableListAdapter.HEADER, "Places"); places.invisibleChildren = new ArrayList<>(); places.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Kerala")); places.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Tamil Nadu")); places.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Karnataka")); places.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "Maharashtra")); data.add(places); recyclerview.setAdapter(new ExpandableListAdapter(data)); } } | cs |
ExpandableListAdapter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | public class ExpandableListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public static final int HEADER = 0; public static final int CHILD = 1; private List<Item> data; public ExpandableListAdapter(List<Item> data) { this.data = data; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) { View view = null; Context context = parent.getContext(); float dp = context.getResources().getDisplayMetrics().density; int subItemPaddingLeft = (int) (18 * dp); int subItemPaddingTopAndBottom = (int) (5 * dp); switch (type) { case HEADER: LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.list_header, parent, false); ListHeaderViewHolder header = new ListHeaderViewHolder(view); return header; case CHILD: TextView itemTextView = new TextView(context); itemTextView.setPadding(subItemPaddingLeft, subItemPaddingTopAndBottom, 0, subItemPaddingTopAndBottom); itemTextView.setTextColor(0x88000000); itemTextView.setLayoutParams( new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); return new RecyclerView.ViewHolder(itemTextView) { }; } return null; } public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { final Item item = data.get(position); switch (item.type) { case HEADER: final ListHeaderViewHolder itemController = (ListHeaderViewHolder) holder; itemController.refferalItem = item; itemController.header_title.setText(item.text); if (item.invisibleChildren == null) { itemController.btn_expand_toggle.setImageResource(R.drawable.circle_minus); } else { itemController.btn_expand_toggle.setImageResource(R.drawable.circle_plus); } itemController.btn_expand_toggle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (item.invisibleChildren == null) { item.invisibleChildren = new ArrayList<Item>(); int count = 0; int pos = data.indexOf(itemController.refferalItem); while (data.size() > pos + 1 && data.get(pos + 1).type == CHILD) { item.invisibleChildren.add(data.remove(pos + 1)); count++; } notifyItemRangeRemoved(pos + 1, count); itemController.btn_expand_toggle.setImageResource(R.drawable.circle_plus); } else { int pos = data.indexOf(itemController.refferalItem); int index = pos + 1; for (Item i : item.invisibleChildren) { data.add(index, i); index++; } notifyItemRangeInserted(pos + 1, index - pos - 1); itemController.btn_expand_toggle.setImageResource(R.drawable.circle_minus); item.invisibleChildren = null; } } }); break; case CHILD: TextView itemTextView = (TextView) holder.itemView; itemTextView.setText(data.get(position).text); break; } } @Override public int getItemViewType(int position) { return data.get(position).type; } @Override public int getItemCount() { return data.size(); } private static class ListHeaderViewHolder extends RecyclerView.ViewHolder { public TextView header_title; public ImageView btn_expand_toggle; public Item refferalItem; public ListHeaderViewHolder(View itemView) { super(itemView); header_title = (TextView) itemView.findViewById(R.id.header_title); btn_expand_toggle = (ImageView) itemView.findViewById(R.id.btn_expand_toggle); } } public static class Item { public int type; public String text; public List<Item> invisibleChildren; public Item() { } public Item(int type, String text) { this.type = type; this.text = text; } } } | cs |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="16dp" android:paddingBottom="16dp" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> | cs |
list_header.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:paddingLeft="13dp" android:paddingStart="13dp" android:paddingRight="10dp" android:paddingEnd="10dp" android:paddingTop="5dp" android:paddingBottom="5dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/header_title" android:textColor="#045CB1" android:textSize="18sp" android:gravity="center_vertical" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <ImageView android:id="@+id/btn_expand_toggle" android:src="@drawable/circle_plus" android:layout_width="30dp" android:layout_height="30dp" android:layout_weight="0"/> </LinearLayout> | cs |
circle_plus(res/drawable-hdpi에 넣으세요)
circle_minus(res/drawable-hdpi에 넣으세요)
다운로드
https://github.com/anandbose/ExpandableListViewDemo
위의 깃헙에서 소스를 다운 받을 수 있습니다.
댓글 영역