728x90

ListViewAdapter 를 만드는 과정이다.

Android Studio 가 제공하는 자동완성 기능을 이용하여 기본적인 골격을 만들어보자.




private class ListViewAdapter extends BaseAdapter {

    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

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

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        return null;
    }
}


기본 코드가 만들어진다. 

연결된 정보들이 없어서 return null, return 0 를 반환하는 걸로 기본 코드가 만들어진 것을 확인할 수 있다.

이 코드에 살을 붙여서 완성된 코드를 만들어야 한다.


리스트뷰는 일반 위젯(TextView등)이 아니라 선택 위젯이기 때문에 직접 데이터를 설정할수가 없다.
Adapter를 이용해야 하고, 이 Adapter에서 만들어주는 getView()를 이용해서 아이템을 표시한다.
리스트뷰는 어댑터를 사용하여 데이터를 표시하는 View이다.




먼저 MainActivity Class 전역변수를 선언한다.

private ArrayList<PesonData> personDataItem = null; // 데이터 리스트
private ListViewAdapter listViewAdapter = null; // 리스트뷰에 사용되는 ListViewAdapter


class ViewHolder {
    public LinearLayout child_layout;
    public ImageView personal_imageView;
    public TextView tv_name;
    public TextView tv_mobileNO;
    public TextView tv_officeNO;
    public Button chid_btn;
}

private class ListViewAdapter extends BaseAdapter {

    public ListViewAdapter() {
    }

    @Override
    public int getCount() {
        return personDataItem.size(); // 데이터 개수 리턴
    }

    @Override
    public Object getItem(int position) {
        return personDataItem.get(position); // 지정한 위치(position)에 있는 데이터를 리턴
    }
   
    @Override
    public long getItemId(int position) {
        return position; 
// 지정한 위치(position)에 있는 데이터 리턴
    }

    // position에 위치한 데이터를 화면에 출력하는데 사용될 View를 리턴
    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;
        final Context context = viewGroup.getContext();

        // 화면에 표시될 View
        if(view == null){
            viewHolder = new ViewHolder();

            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.person_item,viewGroup,false);

            view.setBackgroundColor(0x00FFFFFF);
            view.invalidate();

            // 화면에 표시될 View 로부터 위젯에 대한 참조 획득
            viewHolder.personal_imageView = (ImageView) view.findViewById(R.id.personal_Image);
            viewHolder.tv_name = (TextView) view.findViewById(R.id.child_name);
            viewHolder.tv_mobileNO = (TextView) view.findViewById(R.id.child_mobileNO);
            viewHolder.tv_officeNO = (TextView) view.findViewById(R.id.child_officeNO);
            viewHolder.chid_btn = (Button) view.findViewById(R.id.child_Btn);

            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }

        // PersonData 에서 position 에 위치한 데이터 참조 획득
        PesonData pesonData = personDataItem.get(position);

        // 아이템 내 각 위젯에 데이터 반영
        viewHolder.personal_imageView.setImageDrawable(pesonData.getIcon());
        viewHolder.tv_name.setText(pesonData.getName());
        viewHolder.tv_mobileNO.setText(PhoneNumberUtils.formatNumber(pesonData.getMobileNO()));
        viewHolder.tv_officeNO.setText(PhoneNumberUtils.formatNumber(pesonData.getOfficeNO()));

        viewHolder.chid_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });

        return view;
    }

    // 아이템 데이터 추가를 위한 메소드
    public void addItem(Drawable icon, String uid, String name, String mobileNO, String officeNO){
        PesonData item = new PesonData();
        item.setIcon(icon);
        item.setUid(uid);
        item.setName(name);
        item.setMobileNO(mobileNO);
        item.setOfficeNO(officeNO);

        personDataItem.add(item);
    }
}
 


이제 전체 코드를 보자.

안드로이드가 기본 제공하는 getView() 와 비교할 수 있는 부분은 별도 색상으로 표기를 했다.


import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.telephony.PhoneNumberUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    public SharedPreferences settings;
    private ListView listView; // 리스트뷰
    private EditText editText;
    private Button btn_search;

    private ArrayList<PesonData> personDataItem = null; // 데이터 리스트
    private ListViewAdapter listViewAdapter = null; // 리스트뷰에 사용되는 ListViewAdapter

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

        listView = (ListView) findViewById(R.id.my_listView);
        editText = (EditText) findViewById(R.id.et_text01);

        // Adapter에 추가 데이터를 저장하기 위한 ArrayList
        personDataItem = new ArrayList<PesonData>(); // ArrayList 생성

        // Adapter 생성
        listViewAdapter = new ListViewAdapter();

        listView.setAdapter(listViewAdapter); // 어댑터를 리스트뷰에 세팅
       
        btn_search = (Button) findViewById(R.id.btn_search);
        btn_search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                settings = getSharedPreferences("settings", Activity.MODE_PRIVATE);
                Uri.Builder builder = new Uri.Builder()
                        .appendQueryParameter("search", editText.getText().toString().trim())
                        .appendQueryParameter("idx", "2"); // settings.getString("idx","")
                String postParams = builder.build().getEncodedQuery();
                new getJSONData().execute(Value.IPADDRESS + "/get_json.php",postParams);
            }
        });
    }
   
    class getJSONData extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            try {
                return PHPComm.getJson(params[0],params[1]);
            } catch (Exception e) {
                return new String("Exception: " + e.getMessage());
            }
        }

        protected void onPostExecute(String result){
            searchJSON=result;
            showList();
        }
    }

    // 서버 정보를 파싱하기 위한 변수 선언
    String searchJSON;
    private static final String TAG_RESULTS="result";
    private static final String TAG_UID = "uid"; // 서버 테이블의 실제 필드명
    private static final String TAG_NAME = "name";
    private static final String TAG_MobileNO ="mobileNO";
    private static final String TAG_OfficeNO ="officeNO";
    JSONArray peoples = null;

    protected void showList() {
        try {
            JSONObject jsonObj = new JSONObject(searchJSON);
            peoples = jsonObj.getJSONArray(TAG_RESULTS);

            personDataItem.clear(); // 서버에서 가져온 데이터 초기화
            for(int i=0;i<peoples.length();i++){
                JSONObject c = peoples.getJSONObject(i);
                String uid = c.getString(TAG_UID);
                String name = c.getString(TAG_NAME);
                String mobileNO = c.getString(TAG_MobileNO);
                String officeNO = c.getString(TAG_OfficeNO);
                Drawable myIcon = getResources().getDrawable(R.mipmap.ic_launcher); // 이미지는 임시처리

                // 서버에서 가져온 데이터 저장
                listViewAdapter.addItem(myIcon,uid,name,mobileNO,officeNO);
            }

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // 갱신된 데이터 내역을 어댑터에 알려줌
                    listViewAdapter.notifyDataSetChanged();
                }
            });

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    class ViewHolder {
        public LinearLayout child_layout;
        public ImageView personal_imageView;
        public TextView tv_name;
        public TextView tv_mobileNO;
        public TextView tv_officeNO;
        public Button chid_btn;
    }

    private class ListViewAdapter extends BaseAdapter {

        public ListViewAdapter() {
        }

        @Override
        public int getCount() {
            return personDataItem.size(); // 데이터 개수 리턴
        }

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

        // 지정한 위치(position)에 있는 데이터 리턴
        @Override
        public long getItemId(int position) {
            return position;
        }

        // position에 위치한 데이터를 화면에 출력하는데 사용될 View를 리턴
        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {
            ViewHolder viewHolder;
            final Context context = viewGroup.getContext();

            // 화면에 표시될 View
            if(view == null){
                viewHolder = new ViewHolder();

                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.person_item,viewGroup,false);

                view.setBackgroundColor(0x00FFFFFF);
                view.invalidate();

                // 화면에 표시될 View 로부터 위젯에 대한 참조 획득
                viewHolder.personal_imageView = (ImageView) view.findViewById(R.id.personal_Image);
                viewHolder.tv_name = (TextView) view.findViewById(R.id.child_name);
                viewHolder.tv_mobileNO = (TextView) view.findViewById(R.id.child_mobileNO);
                viewHolder.tv_officeNO = (TextView) view.findViewById(R.id.child_officeNO);
                viewHolder.chid_btn = (Button) view.findViewById(R.id.child_Btn);

                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }

            // PersonData 에서 position 에 위치한 데이터 참조 획득
            PesonData pesonData = personDataItem.get(position);

            // 아이템 내 각 위젯에 데이터 반영
            viewHolder.personal_imageView.setImageDrawable(pesonData.getIcon());
            viewHolder.tv_name.setText(pesonData.getName());
            viewHolder.tv_mobileNO.setText(PhoneNumberUtils.formatNumber(pesonData.getMobileNO()));
            viewHolder.tv_officeNO.setText(PhoneNumberUtils.formatNumber(pesonData.getOfficeNO()));

            viewHolder.chid_btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });

            return view;
        }

        // 아이템 데이터 추가를 위한 메소드
        public void addItem(Drawable icon, String uid, String name, String mobileNO, String officeNO){
            PesonData item = new PesonData();
            item.setIcon(icon);
            item.setUid(uid);
            item.setName(name);
            item.setMobileNO(mobileNO);
            item.setOfficeNO(officeNO);

            personDataItem.add(item);
        }
    }

}
 


잘 정리된 블로그를 참조하면서 테스트 해보고 내 스타일로 수정하고 컴파일 하면서 완성도를 높여가며 테스트중이다. 실제 서버와 연동하여 실제 활용할 수 있는 코드 중심으로 작성해보는 중이다.


ListViewAdapter 를 Activity Class 단위로 생성해서 사용하는 것이 다른 Class 파일을 만드는 것보다 이해도가 좋은 거 같다.


추가 테스트가 필요한 사항

- 사진 이미지를 가져와서 보여주는 것 해결사항

- 버튼 이미지 또는 이미지를 누르면 Event 처리하는 기능


첨부 코드는 http://link2me.tistory.com/1250 파일에서 달라진 파일만 첨부했다.


json_demo_customListView.zip


블로그 이미지

Link2Me

,
728x90

simple_list_item_1 arrayAdapter는 아이템이 TextView만으로 구성되고 데이터가 String 배열이기 때문에 ArrayAdapter 만으로 그 기능을 제공할 수 있다.

Custom ListView 를 제공하기 위해서는 xml 을 정의하고 ArrayAdapter 기능을 확장해야 한다.


사용자 정의형 ListView 에 뿌려질 xml 를 정의하고, Inflation 해주어야 한다.

 item 을 위한 xml 정의(Layout)
 사용자에게 보여질 xml 를 만들고 나서, 실제 Data를 연결할 Class 를 정의한다.
 person_item.xml 과 PersonData.java 파일을 생성한다. 


먼저, layout 폴더에 person_item.xml 파일을 추가한다.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/child_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp" >

    <ImageView
        android:id="@+id/mImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@mipmap/ic_launcher"
        android:layout_weight="1"
        />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_weight="4"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="2dip"
            android:text="이름"
            android:textSize="20sp"
            android:textStyle="bold"
            />

        <TextView
        android:id="@+id/mobileNO"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:text="휴대폰번호"
        android:textStyle="bold"
        />

        <TextView
            android:id="@+id/officeNO"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="left"
            android:text="휴대폰번호"
            android:textStyle="bold"
            />

    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_weight="1"
        android:orientation="vertical" >

        <Button
            android:id="@+id/childListBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center_horizontal|center_vertical"
            android:text="Btn"
            android:textAllCaps="false"
            />
    </LinearLayout>
</LinearLayout>



PersonData.java Class 파일을 생성한다.

그리고 변수를 추가한다.

public class PesonData {
    // PersonData 정보를 담고 있는 객체 생성
    private int profile_image;
    private String uid;
    private String name;
    private String mobile;

    public PesonData(){  // 생성자
    }


변수가 private으로 되어있으므로 외부에서 접근할수있도록 메소드를 만들어주어야 한다.

데이터 없는 생성자 다음 빈공간에서 Alt + Insert 키를 누르고, Gatter and Setter 를 선택하면 자동으로 코드가 추가된다.

다음으로 Generator 를 생성하기 위해 Alt + Insert 키를 누르고 아래 그림처럼 따라 한다.


추가하면 위와 같이 나온다.

이 파일에 대한 전체 코드는 아래와 같다.


public class PesonData {
    // PersonData 정보를 담고 있는 객체 생성
    private int profile_image;
    private String uid;
    private String name;
    private String mobile;

    public PesonData(){  // 생성자
    }

    public PesonData(int profile_image, String uid, String name, String mobile) {
        this.profile_image = profile_image;
        this.uid = uid;
        this.name = name;
        this.mobile = mobile;
    }

    public int getProfile_image() {
        return profile_image;
    }

    public void setProfile_image(int profile_image) {
        this.profile_image = profile_image;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
}
 


내용을 구성하는 PersonData Class까지 작성했다.

코드는 컴파일하면서 에러가 발생하면 다시 수정하면서 작성해서 명칭 등이 약간 변경되었다.

실제 코드를 ListViewAdapter 만드는 방법 게시글(http://link2me.tistory.com/1252)에 올려두었다.


블로그 이미지

Link2Me

,