본문 바로가기
Back-end/Android

[Android] ListView

by JiGyeong 2016. 6. 13.


항상 저 칸은 유지하고 있고

들어가는 아이템만 바꿔끼는 형식으로 구현






activity_main


<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ktds.jgbaek.project0613.MainActivity">

<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</RelativeLayout>


list_item.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ktds.jgbaek.project0613.MainActivity">

<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="Hello World!" />
</LinearLayout>


MainActiviry.java



package com.ktds.jgbaek.project0613;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.listView);
        listView.setAdapter(new MyListAdapter(this));
    }

    private class MyListAdapter extends BaseAdapter {

        private List list;
        private Context context;

        public MyListAdapter(Context context){
            this.context = context;

            list = new ArrayList<>();
            list.add("첫 번째");
            list.add("두 번째");
            list.add("세 번째");
            list.add("네 번째");
            list.add("다섯 번째");
            list.add("여섯 번째");
            list.add("일곱 번째");
            list.add("여덟 번째");
        }

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Object getItem(int position) {
            return list.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null){
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                        context.LAYOUT_INFLATER_SERVICE
                );
                convertView = inflater.inflate(R.layout.list_item, parent, false);
            }

            TextView textView = (TextView) convertView.findViewById(R.id.textView);
            textView.setText((String)getItem(position));

            textView.setOnClickListener(new TextView.OnClickListener(){

                @Override
                public void onClick(View v) {
                    Toast.makeText(v.getContext(), ((TextView)v).getText() + "선택됨", Toast.LENGTH_SHORT).show();
                }
            });
            return convertView;
        }
    }
}





1. Layout Gravity : 하위 View( Widget )들을 정렬함

2. Gravity : 내용물을 정렬함




view 안에 여러 정보를 담아보자




getView method에서 convertView를 이용해 화면에 view를 추가해준다.

list 화면을 아래로 내릴경우

위에있던 칸이 아래로 내려와 채우며 보여주는 방식이다.

처음 내렸을 경우 LayoutInflater를 이용해 새로운 레이아웃을 가져와준다.


하지만 이방식은 TextView를 계속 생성해줘서 자원의 낭비가 심하다. 더 좋은 방법을 알아보자.






ItemHolder를 만들어 textView를 계속 생성해 주지 않고 공간을 미리 생성해둔다.

그 공간에 데이터를 가져와 셋팅 시킨다.


전체코드:



package com.ktds.jgbaek.customlistview;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private ListView lvArticleList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lvArticleList = (ListView) findViewById(R.id.lvArticleList);

        final List articleList = new ArrayList();
        for (int i = 0; i < 300; i++){
            articleList.add(new ArticleVO("제목입니다."+i, "글쓴이입니다." , new Random().nextInt(9999)+""));
        }
        lvArticleList.setAdapter((new ArticleListViewAdapter(this, articleList)));
        lvArticleList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                Toast.makeText(MainActivity.this, id + "", Toast.LENGTH_SHORT).show();
                ArticleVO article = articleList.get(position);
                Toast.makeText(MainActivity.this, article.getSubject(), Toast.LENGTH_SHORT).show();

                Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(""));
                intent.putExtra("article", article);


            }
        });
    }
    private class ArticleListViewAdapter extends BaseAdapter {

        /**
         *  ListView에 Item을 셋팅할 요청자의 객체가 들어감
         */
        private Context context;

        /**
         * ListView 셋팅할 Item 정보들
         */
        private List articleList;

        private ArticleVO article;

        public ArticleListViewAdapter(Context context, List articleList) {
            this.context = context;
            this.articleList = articleList;
        }

        /**
         * ListView에 셋팅할 아이템의 개수
         * @return
         */
        @Override
        public int getCount() {
            return this.articleList.size();
        }

        /**
         * position 번째 Item정보를 가져옴
         * @param position
         * @return
         */
        @Override
        public Object getItem(int position) {
            return this.articleList.get(position);
        }

        /**
         * Item Index를 가져옴
         * Item Index == position
         *
         * @param position
         * @return
         */
        @Override
        public long getItemId(int position) {
            return position;
        }

        /**
         * ListView에 Item들을 셋팅함
         *
         * @param convertView - 현재 보여질 Item의 Index 0부터 getCount()를 실행함
         * @param parent
         * @return
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            // 가장 간단한 방법
            // 사용자가 처음으로 Flicking을 할때 아래쪽에 만들어지는 셀은 null이다.
//            if (convertView == null) {
//                // Item cell에 Layout을 적용 시킬 Inflater
//                LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
//                //  Item Cell에 Layout을 적용시킨다.
//                convertView = inflater.inflate(R.layout.list_item, parent, false);
//            }
//
//            TextView tvSubject = (TextView) convertView.findViewById(R.id.tvSubject);
//            TextView tvAuthor = (TextView) convertView.findViewById(R.id.tvAuthor);
//            TextView tvHitCount = (TextView) convertView.findViewById(R.id.tvHitCount);
//
//            ArticleVO article = (ArticleVO) getItem(position);
//            tvSubject.setText(article.getSubject());
//            tvAuthor.setText(article.getAuthor());
//            tvHitCount.setText(article.getHitCount());

            ItemHolder holder = null;

            // 가장 효율적인 방법
            if (convertView == null) {
                // Item cell에 Layout을 적용 시킬 Inflater
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
                //  Item Cell에 Layout을 적용시킨다.
                convertView = inflater.inflate(R.layout.list_item, parent, false);

                holder = new ItemHolder();
                holder.tvSubject = (TextView) convertView.findViewById(R.id.tvSubject);
                holder.tvAuthor = (TextView) convertView.findViewById(R.id.tvAuthor);
                holder.tvHitCount = (TextView) convertView.findViewById(R.id.tvHitCount);

                convertView.setTag(holder);
            }
            else {
                holder = (ItemHolder) convertView.getTag();
            }

            article = (ArticleVO) getItem(position);
            holder.tvSubject.setText(article.getSubject());
            holder.tvAuthor.setText(article.getAuthor());
            holder.tvHitCount.setText(article.getHitCount());

            return convertView;

        }
    }

    private class ItemHolder {
        public TextView tvSubject;
        public TextView tvAuthor;
        public TextView tvHitCount;
    }

}