안드로이드 Expandable Recycler View

안녕하세요. 개발자 드리머즈입니다.


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) (* 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 + && 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


위의 깃헙에서 소스를 다운 받을 수 있습니다.





작성자

Posted by 드리머즈

태그

관련 글

댓글 영역

  • 프로필 사진
    질문있습니당
    2018.10.24 10:52

    안녕하세요 덕분에 좋은 기능 사용하고 있습니다! 적어주신 예제로 기능은 잘 구현하고 있는데요
    처음 액티비티에 들어갔을 때 리사이클러뷰가 펼쳐있는 상태가 기본으로 되있습니다.
    혹시 닫혀있는 상태로 하려면 어디를 변경해야 하는지 여쭤볼 수 있을까요?

    • 프로필 사진
      2018.10.24 11:05 신고

      안녕하세요~

      잘 사용하고 있다니 기쁘네요~
      제가 오래 전에? 사용해서 기억이 좀 가물가물한데요 ㅎㅎ

      제 포스트의
      MainActivity.java의 소스를 보시면
      보여질 데이터를 정의하는 2가지 방법이 있습니다.

      14~22라인의 방법을 사용하면 하위 내용이 펼쳐진 상태로 보이게 될 것이구요

      24~29라인의 방법을 사용하면 하위 내용이 닫혀진 상태로 보일거에요 ㅎㅎ

      한 번 해보시고 결과 알려주세용^^

    • 프로필 사진
      질문있습니다
      2018.10.25 12:02

      감사합니다! 자세히 관찰하지 않은 제 잘못이네요! 저는 핸들러의 위치를 바꿔서 해결했었는데 이미 예제에 있던 부분이네요 감사합니다!

  • 프로필 사진
    11살 아인슈타인
    2019.07.23 15:52

    안녕하세요! 코드를 보고 따라하고 있는데요,
    xml 파일은 없는 건가요?
    계속 해봤는데 id 쪽에서 오류가 나서요 ㅠㅠㅠ
    게다가 밑에 올려주신 깃허브 링크도 사라져버렸네요ㅠㅠ
    xml 파일 좀 보여주실 수 있을까요?

    • 프로필 사진
      2019.07.23 16:44 신고

      안녕하세요~
      정말이네요.. github이 왜 사라졌는지는 모르겠습니다. ㅜㅜ

      어쨋든 요청하신 xml파일을 본문에 추가했습니다. 그리고 필요한 이미지 파일 2개도 추가했으니.. 이 파일도 포함해서 테스트 해보세요 ㅎㅎ

    • 프로필 사진
      11살 아인슈타인
      2019.07.23 17:18

      너무 너무 감사합니다ㅜㅜㅜ!!!
      열심히 코딩 공부 하겠습니다

  • 프로필 사진
    app개발
    2019.08.22 16:43

    안녕하세요, 예제 잘 봤습니다. 3 level까지 들어가려면 어떻게 추가해야하나요?

    • 프로필 사진
      2019.08.22 23:37 신고

      안녕하세요~
      3 level은 저도 만들어보지 않았습니다;;
      위 코드 참고해서 도전해볼 수는 있겠지만 간단할 것 같지는 않네요.. ㅎㅎ;;

      그런데 3레벨을 만들어야 하는 이유가 있나요? 무척 복잡해보일 거에요.

  • 프로필 사진
    개발중
    2019.10.16 17:50

    안녕하세요. 리사이클러뷰에 대해 이 글 보고 도전해보는 중입니다 .ㅠㅠ
    블랙스타일로 어플을 제작하는 중인데 많은 도움을 받았습니다!!
    그런데 HEADER 부분은 노출잘되고 플러스, 마이너 이미지뷰부분은 잘 바뀌는데요!
    CHILD 부분이 아예 노출이 안되는데 이 것은 어떻게 해결해야하나요 ?ㅠㅠ 영역펼치기부터 공간까지는 늘어나는데
    안에 텍스트가 안보여용
    코드 구성은 모두 같습니다!! ㅠ_ㅠ..
    바탕색은 블랙이라 색상관련해서 다 바궈봣는데 무슨 부분에서 문제가 있는지 모르겠네여 ㅠㅠ 좋은 조언 부탁드립니당

    • 프로필 사진
      2019.10.16 18:23 신고

      안녕하세요~ 환영합니다.

      말씀을 들어보니.. child 부분의 텍스트만 문제가 있는 것 같네요.

      onBindViewHolder()함수에서
      case CHILD:에
      디버그 로그 넣어서 text값 출력되도록 하고.. 앱 실행시켜 펼쳤을 때 로그가 잘 발생하는지 보시겠어요? 몇 가지만 테스트 해보면 될 것 같습니다.

    • 프로필 사진
      개발중
      2019.10.17 15:52

      D/ViewRootImpl@423d4a5[AreaSelectActivity]: ViewPostIme pointer 1
      D/TedPark: CHILD구문출력확인
      I/chatty: uid=10337(u0_a337) com.rs.spineertest identical 2 lines
      D/TedPark: CHILD구문출력확인
      D/ScrollView: onsize change changed
      D/ViewRootImpl@423d4a5[AreaSelectActivity]: ViewPostIme pointer 0
      D/ViewRootImpl@423d4a5[AreaSelectActivity]: ViewPostIme pointer 1
      D/TedPark: CHILD구문출력확인
      I/chatty: uid=10337(u0_a337) com.rs.spineertest identical 2 lines
      D/TedPark: CHILD구문출력확인
      D/ScrollView: onsize change changed
      I/zygote64: Compiler allocated 8MB to compile void android.view.ViewRootImpl.performTraversals()
      D/ViewRootImpl@423d4a5[AreaSelectActivity]: ViewPostIme pointer 0
      D/ViewRootImpl@423d4a5[AreaSelectActivity]: ViewPostIme pointer 1
      D/TedPark: CHILD구문출력확인
      I/chatty: uid=10337(u0_a337) com.rs.spineertest identical 2 lines
      D/TedPark: CHILD구문출력확인
      D/ScrollView: onsize change changed

      이렇게 출력됩니다 .ㅠ_ㅠ

    • 프로필 사진
      개발중
      2019.10.17 15:54

      recyclerview = findViewById(R.id.recyclerview);
      recyclerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
      List<ExpandableListAdapter.Item> data = new ArrayList<>();

      ExpandableListAdapter.Item a = new ExpandableListAdapter.Item(ExpandableListAdapter.HEADER, "강원도");
      a.invisibleChildren = new ArrayList<>();
      a.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "속초시"));
      a.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "강릉시"));
      a.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "동해시"));
      a.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "삼척시"));

      ExpandableListAdapter.Item b = new ExpandableListAdapter.Item(ExpandableListAdapter.HEADER, "강원도");
      b.invisibleChildren = new ArrayList<>();
      b.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "속초시"));
      b.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "강릉시"));
      b.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "동해시"));
      b.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "삼척시"));

      ExpandableListAdapter.Item c = new ExpandableListAdapter.Item(ExpandableListAdapter.HEADER, "강원도");
      c.invisibleChildren = new ArrayList<>();
      c.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "속초시"));
      c.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "강릉시"));
      c.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "동해시"));
      c.invisibleChildren.add(new ExpandableListAdapter.Item(ExpandableListAdapter.CHILD, "삼척시"));

      data.add(a);
      data.add(b);
      data.add(c);

      recyclerview.setAdapter(new ExpandableListAdapter(data));

      아 인사가 늦었습니다 빠른 답변 감사드립니다 ㅠㅠ. 이렇게 빠를 줄 모르고 하루 지나고 확인했네요 .ㅠㅠ

      위에 코드가 액티비티 onCreate 부분에 들어가는 부분이거든요. 위에 문의하신 분 덕에 그 닫혀있는 상태로 시작하게 저렇게 바꿔봣는데 이 부분도 같이 좀 봐주실 수 있을까요 ?? 이렇게 변경해도 맞는건지.. 제가 아직 많이 미숙해서..

    • 프로필 사진
      2019.10.17 16:28 신고

      네 onCreate()쪽 코드는.. 별 문제 없어 보입니다. 잘 하신 것 같아요.

      흠.. 아주.. 사소한 부분에서.. 문제가 생긴 것 같습니다.

      onCreateViewHolder()에서 case CHILD: 쪽 코드와
      onBindViewHolder()에서 case CHILD: 쪽 코드.. 좀 보여주시겠어요?

    • 프로필 사진
      개발중
      2019.10.17 16:36

      @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.area_select, parent, false);
      ListHeaderViewHolder header = new ListHeaderViewHolder(view);
      return header;
      case CHILD:
      TextView itemTextView = new TextView(context);
      itemTextView.setPadding(subItemPaddingLeft, subItemPaddingTopAndBottom, 0, subItemPaddingTopAndBottom);
      itemTextView.setTextColor(0x880000);
      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.areaselect_tv_area.setText(item.text);
      if (item.invisibleChildren == null) {
      itemController.areaselect_iv_arrow.setImageResource(R.drawable.arrow_open);
      } else {
      itemController.areaselect_iv_arrow.setImageResource(R.drawable.arrow_close);
      }
      itemController.areaselect_iv_arrow.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.areaselect_iv_arrow.setImageResource(R.drawable.arrow_close);
      } 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.areaselect_iv_arrow.setImageResource(R.drawable.arrow_open);
      item.invisibleChildren = null;
      }
      }
      });
      break;
      case CHILD:
      Log.d("TedPark","CHILD구문출력확인");
      TextView itemTextView = (TextView) holder.itemView;
      itemTextView.setText(data.get(position).text);
      itemTextView.setTextColor(0xffffff);
      break;
      }
      }

      이렇게 작성하였습니다!!

    • 프로필 사진
      2019.10.17 18:10 신고

      Log.d("TedPark","CHILD구문출력확인");
      코드를..
      Log.d("TedPark","CHILD구문출력확인 text = " + data.get(position).text);
      로 변경해서.. 텍스트 값이 잘 찍히나 확인해주세요 ㅎㅎ

      음.. 프로젝트를 확인하면 금방 확인할 것 같은데요 소스 압축해서 dreamaz87@naver.com으로 보내주시겠어요?

    • 프로필 사진
      개발중
      2019.10.21 09:37

      D/ViewRootImpl@a003dc3[AreaSelectActivity]: ViewPostIme pointer 0
      D/ViewRootImpl@a003dc3[AreaSelectActivity]: ViewPostIme pointer 1
      D/TedPark: CHILD구문출력확인 text = 속초시
      D/TedPark: CHILD구문출력확인 text = 강릉시
      D/TedPark: CHILD구문출력확인 text = 동해시
      D/TedPark: CHILD구문출력확인 text = 삼척시
      D/ScrollView: onsize change changed
      D/ViewRootImpl@a003dc3[AreaSelectActivity]: ViewPostIme pointer 0
      D/ViewRootImpl@a003dc3[AreaSelectActivity]: ViewPostIme pointer 1
      D/TedPark: CHILD구문출력확인 text = 속초시
      D/TedPark: CHILD구문출력확인 text = 강릉시
      D/TedPark: CHILD구문출력확인 text = 동해시
      D/TedPark: CHILD구문출력확인 text = 삼척시
      D/ScrollView: onsize change changed
      D/ViewRootImpl@a003dc3[AreaSelectActivity]: ViewPostIme pointer 0
      D/ViewRootImpl@a003dc3[AreaSelectActivity]: ViewPostIme pointer 1
      D/TedPark: CHILD구문출력확인 text = 속초시
      D/TedPark: CHILD구문출력확인 text = 강릉시
      D/TedPark: CHILD구문출력확인 text = 동해시
      D/TedPark: CHILD구문출력확인 text = 삼척시
      D/ScrollView: onsize change changed

      죄송합니다.! 일이 좀 생겨서 답글 달아주신 것을 이제 확인했어요 ㅠㅠ
      알려주신 대로 확인해보니 출력은 위처럼 아주 잘되고 있는것인데 디바이스 상에 노출이 안되는 것을 보니 뭔가 색상의 문제인가요.. 흠.. 일단 압축파일 보내드리겠습니다!!

    • 프로필 사진
      2019.10.21 16:06 신고

      와.. 원인을 찾아보니

      itemTextView.setTextColor(0x880000); 와 같이 사용하신 코드가 문제였습니다.

      저도 저 코드만 봤을 때는 0x다음에 RRGGBB값이 들어가야하는 거라고 생각했는데 찾아보니
      myTextView.setTextColor(0xAARRGGBB); 와 같이 Alpha값이 먼저 들어가야 합니다.

      itemTextView.setTextColor(0xffffffff);
      이렇게 f를 8개 넣어서 사용하시면 흰 색 글자를 보실 수 있을 거에요.

      그리고 위 예제에선.. child를 간단히 보여주기 위해 TextView를 ViewHolder에 넣어서 만들었지만.. Header만든 것처럼 layout 파일을 이용해 좀 더 복잡한 구조로 만드실 수도 있어요~

    • 프로필 사진
      개발중
      2019.10.21 16:28

      드디어 해결했씁니다!!!
      이제야 다음단계로 넘어갈 수 있겠네요 ㅠ_ㅠ 감사합니다!!

  • 프로필 사진
    개발중
    2019.10.22 17:03

    안녕하세요. 하나만 더 도움을 청하게되어습니다!
    이제 노출까지는 모든 것이 완벽한데 제가 지역선택 스피너 처럼 사용해보려고 하는데
    여기서 CHILD를 클릭했을때 HEADER와 CHILD 정보를 결과 페이지로 넘기려면
    어떻게 접근해야할까요??ㅠ_ㅠ 죄송하지만 도움을 청해봅니다. . .

    • 프로필 사진
      2019.10.22 18:56 신고

      안녕하세요~ 다시 오셨군요.
      (onBindViewHolder 함수에서 setOnClickListener구현 시) 클릭된 CHILD와 관련된 index를 구할 수 있으므로 이를이용해서 간단한 조작?을 하면 List<Item> data에 접근하여 HEADER 값도 구할 수 있습니다.

      A 액티비티에서 실행된 B 액티비티가가 종료될 때 B 액티비티에서 A 액티비티로 데이터를 넘기는 것은 아주 흔한 경우입니다. startActivityForResult()와 OnActivityResult()에 대해 찾아보시면 됩니다. (이미 알고 계실지도..)
      intent에 HEADER와 CHILD 관련 값 담아서 보내면 될 것 같네요 ㅎ

  • 프로필 사진
    a
    2019.10.29 01:37

    안녕하세요. 코드 감사합니다. 질문이 있는데 저기 CHILD에 이미지까지 추가로 넣고 싶은데 방법이 없을까요?

    • 프로필 사진
      2019.10.29 09:37 신고

      안녕하세요~
      child에 이미지 넣는 것도 가능합니다.

      위의 코드에서 header쪽 코드를 보시면.. xml에 그 모양을 정해서 사용하고 있습니다.

      child도 xml 하나 만들어서 원하시는 구조? 표현하시고.. header처럼 사용하시면 됩니다. 말로 설명하려니 좀 어렵네요. ㅎㅎ 어쨋든 HEADER쪽 코드를 참고해주세요~

  • 프로필 사진
    2019.11.09 18:07 신고

    코드 감사합니다! 적어주신 코드 보다가 모델 클래스가 어딨지? 하고 찾다가 임의로 만들어 쓰려는데 어댑터 맨 밑에 있더군요 ㅎㅎ
    코드 분석해서 제 것으로 만들겠습니다 좋은 예제 감사합니다

    • 프로필 사진
      2019.11.09 19:05 신고

      네 ㅎㅎ
      제가 만든 코드는 아니고.. 저도 인터넷에서 찾은 코드에요 ㅎㅎ
      계속 쓰다보면 코드가 아주 익숙해지더라구요~ 댓글 감사합니다.

    • 프로필 사진
      2019.11.09 19:38 신고

      헉 빠른 댓글 감사합니다....그런데 분석하다 궁금한 게 하나 있는데요.
      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"));

      이 부분은 글자 크기나 색을 커스텀하려면 어떻게 하면 좋을까요?

    • 프로필 사진
      2019.11.09 20:57 신고

      흠.. 모두 동일한 텍스트 크기나 색으로 변경하시려고 하는 건가요?
      생각해보니.. 단순히 크기와 색만 바꾸려고 하시는거면.. xml까지 만드실 필요도 없고.. onCreateViewHolder()에서 텍스트 크기와 색을 변경하면 되겠네요~