본문 바로가기

프로그래밍/안드로이드

[안드로이드] 항목 뷰

※ 저는 안드로이드 프로그래밍 정복(김상형 著, 한빛미디어) 책을 이용해 공부하고 있으며

예제와 코드는 이 책을 통해 공부중임을 밝힙니다.

개인적인 공부를 하면서 정리한 형식이기 때문에 심각한 오류가 있을 수 있습니다. 피드백 주시면 정말 감사하겠습니다.


※ 안드로이드 프로그래밍 정복(5689p~567p) 참조



1. 커스텀 항목 뷰


말 그대로 커스터마이징(Customizing) 한다는 뜻이다.

내가 원하는 형태로 항목 뷰(list 형태)를 구성할 수 있다.

렐러티브 레이아웃(Relative Layout)으로 위와 같은 형태로 꾸며보자.

위와 같은 형태가 하나의 객체를 구성하며, 우리는 리스트(항목) 뷰 상태로 계속 추가해나갈 수 있다.


먼저 두개의 .xml 파일을 만-들어야 한다.

하나는 리스트뷰 형태로 보이기 위한 List 또 하나는 위 배치를 구성하는 레이아웃을 작성해야 한다.


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>

한 개는 단순히 리스트 뷰만 정의하고 있는 xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dip"
android:padding="5dip">
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#00ff00"
android:textSize="26sp"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/img" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:text="주문" />
</RelativeLayout>

위 예제는 하나하나 리스트뷰를 구성할 레이아웃 (즉, 아이템 하나에 대한 레이아웃)

아래 내용은 자바 코드이다.


public class ExerciseExam extends AppCompatActivity {

ArrayList<MyItem> arItem;

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

arItem = new ArrayList<MyItem>(); // 항목 배열 초기화
MyItem mi;
mi = new MyItem(R.drawable.b, "삼성 노트북");arItem.add(mi);
mi = new MyItem(R.drawable.b, "LG 세탁기");arItem.add(mi);
mi = new MyItem(R.drawable.b, "대우 마티즈");arItem.add(mi);

MyListAdapter MyAdapter = new MyListAdapter(this, R.layout.activity_excercise_exam, arItem);

// 커스텀 어댑터 객체 생성 ( 액티비티 자신 , XML에 정의한 레이아웃 전달, 리스트뷰에 출력할 arItem )



ListView MyList;
MyList = (ListView)findViewById(R.id.list);


MyList.setAdapter(MyAdapter); // 리스트뷰와 어댑터를 연결
}
}

//리스트 뷰에 출력할 항목
class MyItem{

int icon;     // 뷰에 출력할 이미지
String name; // 뷰에 출력할 문자열

MyItem(int aIcon, String aName){
icon = aIcon;
name = aName;
}
}



//어댑터 클래스 (리스트뷰에게 항목의 집합을 제공하는 어댑터 클래스)
class MyListAdapter extends BaseAdapter { // 어댑터로 동작하려면 BaseAdapter로부터 상속받아 기본 기능 상속


Context maincon;
LayoutInflater Inflater;
ArrayList<MyItem> arSrc;
int layout;

public MyListAdapter(Context context, int alayout, ArrayList<MyItem> aarSrc) {
maincon = context;
Inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
arSrc = aarSrc;
layout = alayout;
}

public int getCount() { // 어어댑터에 몇 개의 항목이 있는지 조사해라! (배열의 크기 리턴)
return arSrc.size();
}

public String getItem(int position) { // 배열의 position(위치) 정보를 구해라!
return arSrc.get(position).name;
}

public long getItemId(int position) { // 배열의 position(위치) 위치의 항목 ID를 리턴해라!
return position;
}

// 각 항목의 뷰 생성

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


// 뷰 요청후 리턴된 뷰를 해당된 위치에 배치한다.

// position : 생성할 항목의 순서 값

// convertVIew : 이전에 생성된 차일드 뷰. 최초 호출시에는 null이 전달되며 커스텀 뷰를 새로 생성후 리턴

// parent : 생성되는 뷰의 부모 (즉, 리스트뷰)


final int pos = position;
if (convertView == null) {
convertView = Inflater.inflate(layout, parent, false);
}

ImageView img = (ImageView) convertView.findViewById(R.id.img);
img.setImageResource(arSrc.get(position).icon);

TextView txt = (TextView) convertView.findViewById(R.id.text);
txt.setText(arSrc.get(position).name);

Button btn = (Button) convertView.findViewById(R.id.btn);
btn.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
String str = arSrc.get(pos).name + "를 주문합니다.";
Toast.makeText(maincon, str, Toast.LENGTH_SHORT).show();
}
});

return convertView;
}
}




2. 확장 리스트뷰


ListView는 1차원 배열 형태로

ExpandableListView는 2차원 형태로 항목을 표시할 수 있다.




위를 구현하는 코드는 다음과 같다.


package lkcompany.exercise;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExerciseExam extends AppCompatActivity {

ExpandableListView mList;
String[] category = new String[]{
"상의", "하의", "아우터"
};

String[][] details = new String[][]{
{"셔츠", "반팔", "긴팔"},
{"슬랙스", "청바지", "반바지"},
{"패딩", "코트", "야상"}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_excercise_exam);

mList = (ExpandableListView)findViewById(R.id.list);

List<Map<String, String>> categoryData = new ArrayList<Map<String, String>>();
List<List<Map<String, String>>> detailsData = new ArrayList<List<Map<String, String>>>();

for (int i = 0; i < category.length; i++) {
Map<String, String> Category = new HashMap<String, String>();
Category.put("CATEGORY", category[i]); // Map에 value 객체 (category[i])를 key객체에 연결(mapping)하여 저장
categoryData.add(Category);

List<Map<String, String>> children = new ArrayList<Map<String, String>>();
for (int j = 0; j < details[i].length; j++) {
Map<String, String> Details = new HashMap<String, String>();
Details.put("DETAIL", details[i][j]); / Map에 value객체(details[i][j])를 key객체에 연결(mapping)하여 저장
children.add(Details);
}
detailsData.add(children);

}

ExpandableListAdapter adapter = new SimpleExpandableListAdapter(
this,
categoryData, // categoryData의 해시맵 배열의 정보를 읽어

android.R.layout.simple_expandable_list_item_1, // 해당 레이아웃을 출력하되

new String[]{"CATEGORY"},                       // CATEGORY 키로 정의된 정보를

new int[]{android.R.id.text1},                  // text 1 위젯에 출력하라.


detailsData, // detailData의 해시맵 배열의 정보를 읽어

android.R.layout.simple_expandable_list_item_1, // 해당 레이아웃을 출력하되

new String[]{"DETAIL"},                         // DETAIL 키로 정의된 정보를

new int[]{android.R.id.text1}                 // text 1 위젯에 출력하라

);
mList.setAdapter(adapter);
}
}


자바 공부가 필요한 대목이다.

List<Map<String, String>> categoryData = new ArrayList<Map<String, String>>();

이 부분은 큰 가지에 해당하는 "상의", "하의", "아우터"를 담는 대목이며


List<List<Map<String, String>>> detailsData = new ArrayList<List<Map<String, String>>>();

이 부분은 작은 가지에 해당하는 "셔츠", "반팔", "긴팔" 등 세부 디테일한 항목을 담는 부분이다.


1. JAVA의 "다형성" 파트


        1.        List list = new ArrayList();

        2. ArrayList list = new ArrayList();


     위 List는 "인터페이스" 이다. 옷을 "상의", "하의", "신발" 로만 나눈다면

     1번 예제는 " 옷 list    = new 상의 ( ) ;  "

     2번 예제는 " 상의 list = new 상의 ( ) ;  " 로 나눈 것이다.


     1번의 경우에는 "옷" 타입으로 생성했으니 "하의", "신발"을 구현한 클래스에서 사용할 수 있다.

     2번의 경우에는 "상의" 타입으로 생성했으니 "하의", "신발"을 구현한 클래스에서 사용할 수 없다.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

2. JAVA의 다형성 파트


      1.   List<Student> list = new ArrayList<Student>();

      2.                 List list = new ArrayList<Student>(); 


    1번 예제의 경우 List에 담겨질 객체의 타입을 정해준 것이다.

    타입을 정해준 경우, Student 객체가 아닌 다른 타입은 add할 수 없기 때문에 오류 예방이 된다. 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

3. List<Map<String, String>> = new ArrayList<Map<String, String>>();






3. 오버 스크롤



리스트뷰일때 스크롤 범위 끝에 닿았을 때 특별한 표식을 출력하는 것이다.


속성값 

상수 ( OVER_SCROLL_ ) 

설명 

always 

ALWAYS 

오버 스크롤을 항상 허가 

never 

NEVER 

오버 스크롤을 허가하지 않음 

ifContentScrolls 

IF_CONTENT_SCROLLS 

내용물이 스크롤할만큼 클 때만 허용 


디폴트값은 ifContentScrolls이다.


int getOverScrollMode()

void setOverScrollMode (int overScrollMode)