개발 - 안드로이드

안드로이드 ListView 멀티 아이템

개미v 2023. 10. 3. 09:54

안드로이드 ListView에서 여러 종류의 아이템을 출력하는 방법입니다.

처음에는  ListView를 3개 만들어서 처리하려고 했는데, 스크롤시 전체가 움직이지 않고 하나만 움직여서 문제가 되었습니다.
이런 경우 ListView 멀티 아이템을 사용해야 합니다.

 

 

타입 종류
위 그림을 보면 아이템 타입은 3개가 존재 합니다.

1. 타이틀
2. 구분선
3. 사용자 정보

 

먼저 3개의 layout.xml을 먼저 만들어 줍니다.


타입 1 : item_title.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:orientation="horizontal">

    <TextView
        android:id="@+id/textViewTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

 

타입2 : item_line.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="wrap_content">

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/gray" />
</LinearLayout>

 

타입3 : item_user.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <!-- 사진 -->
    <LinearLayout
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:gravity="center_vertical|left">
        .
        .
        .
    </LinearLayout>

    <!-- 별명, 성별, 나이, 지역, 자기소개 -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_weight="1"
        android:gravity="center_vertical|left"
        android:orientation="vertical">
        .
        .
        .
    </LinearLayout>
</LinearLayout>

 

MultiUserItem.java
3가지 타입을 처리할 수 있는 Item 클래스를 만들어 줍니다.
각 타입을 구분할 수 있는 type 변수가 있어야 하고, 각 타입의 생성자가 필요 합니다.

public class MultiUserItem {
    // 타입
    private int type;
    
    private String title;
    
    private String userId;
    private String userNickname;
    private String userSex;
    private String userAge;
    private URL userPictureUrl;

    // 타입1 : 타이틀
    public MultiUserItem(int type, String title) {
        this.type = type;
        this.title = title;
    }
    
    // 타입2 : 구분선
    public MultiUserItem(int type) {
        this.type = type;
    }
    
    // 타입 3 : 사용자
    public MultiUserItem(int type, String userId, String userNickname, String userSex, String userAge, URL userPictureUrl) {
        this.type = type;
        this.userId = userId;
        this.userNickname = userNickname;
        this.userSex = userSex;
        this.userAge = userAge;
        this.userPictureUrl = userPictureUrl;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserNickname() {
        return userNickname;
    }

    public void setUserNickname(String userNickname) {
        this.userNickname = userNickname;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserAge() {
        return userAge;
    }

    public void setUserAge(String userAge) {
        this.userAge = userAge;
    }

    public URL getUserPictureUrl() {
        return userPictureUrl;
    }

    public void setUserPictureUrl(URL userPictureUrl) {
        this.userPictureUrl = userPictureUrl;
    }
}

 

MultiUserAdapter.java
getView 메소드에서 각 타입에 맞게 화면 처리해줍니다.

public class MultiUserAdapter extends BaseAdapter {

    // 타입 종류
    public static final int ITEM_VIEW_TYPE_TITLE = 0;
    public static final int ITEM_VIEW_TYPE_LINE = 1;
    public static final int ITEM_VIEW_TYPE_USER = 2;

    private Context context;
    private LayoutInflater layoutInflater;
    private ArrayList<MultiUserItem> multiUserList;

    public MultiUserAdapter(Context context, ArrayList<MultiUserItem> data) {
        this.context = context;
        this.multiUserList = data;
        this.layoutInflater = LayoutInflater.from(context);
    }

    View view = null;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        int type = multiUserList.get(position).getType();

        // 타입1 : 타이틀
        if (type == ITEM_VIEW_TYPE_TITLE) {
            view = layoutInflater.inflate(R.layout.item_title, null);
            ((TextView) view.findViewById(R.id.textViewTitle)).setText(multiUserList.get(position).getTitle());
            return view;
        }

        // 타입2 : 구분선
        else if (type == ITEM_VIEW_TYPE_LINE) {
            view = layoutInflater.inflate(R.layout.item_line, null);
            return view;
        }

        // 타입3 : 사용자
        else if (type == ITEM_VIEW_TYPE_USER) {
            view = layoutInflater.inflate(R.layout.item_user, null);

            // 사진, 별명, 성별, 나이, 지역, 거리, 자기소개
            .
            .
            .

            return view;
        }

        // 에러
        return null;
    }
}

 

UserFragment.java
각 타입의 데이터를 리스트에 순서대로 넣어서 생성해 줍니다.

public class UserFragment extends Fragment {

    // 사용자 목록 배열
    private ArrayList<MultiUserItem> multiUserList;

    private MultiUserAdapter multiUserAdapter;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_user, container, false);

        // 사용자 목록 ListView 어댑터 설정
        multiUserAdapter = new MultiUserAdapter(rootView.getContext(), multiUserList);
        listViewUser.setAdapter(multiUserAdapter);

		// 나 생성
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_TITLE, "나"));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_LINE));
		
		// 친구 생성
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_TITLE, "친구"));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_LINE));
		
		// 근처 사용자 생성
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_TITLE, "근처 사용자"));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));		
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		multiUserList.add(new MultiUserItem(MultiUserAdapter.ITEM_VIEW_TYPE_USER, userId, userNickname, userSex, userAge, userIntro, userArea, distance, userPictureUrl));
		
        return rootView;
    }
}