내가 XML(Layout)을 공부하면서 기록한 내용들이다. 그냥 공부하면서 적은거라 다른 사람들처럼 그림으로 쉽게 설명하거나 그런것은 없다..
✔️1.레이아웃의 종류와 상관없이 공통으로 사용되는 속성✔️
◼️ Layout 또는 View 위젯의 크기 ◼️
layout_width : Layout 또는 자식(Children) View 위젯의 너비 지정
layout_height : Layout 또는 자식(Children) View 위젯의 높이 지정
layout_width 및 layout_height 속성에 크기를 지정할 때의 값 (match_parent, wrap_content)
match_parent : Layout 또는 View 위젯을 상위 Layout이 허용하는 최대 크기에 맞게 늘릴 때 사용되는 값
wrap_content : Layout 또는 View 위젯이 가진 내용에 맞는 크기를 갖게 하고자 할 때 사용되는 값
◼️Layout 또는 자식(Children) View 위젯 요소 간 여백◼️
layout_margin : View 위젯과 상위 Layout 사이에 주어지는 공간을 의미, View 위젯의 영역에 포함되지 않음
padding : View 위젯의 실제 내용(텍스트, 이미지 등)과 View 위젯 경계 사이의 추가적인 공간
(쉽게 말해서 margin은 실제 내용과 그 경계사이의 공간을 조정하는 것이고 padding은 실제 내용의 공간을 조정하는것이다.)
◼️Layout 내의 View 위젯의 위치 정렬◼️
(Layout에 위치 정렬과 관련된 어떠한 속성도 사용되지 않은 경우, 기본적인 정렬 방향이 수평(horizontal) 방향으로 왼쪽에, 수직(vertical) 방향으로 위쪽으로 된다.)
layout_gravity : 자신이 속한 부모 Layout내 자신의 정렬 위치 값 지정
-. top (0x30) : 부모 Layout 안에서, 위쪽에 위치.
-. bottom (0x50) : 부모 Layout 안에서, 아래쪽에 위치.
-. left (0x03) : 부모 Layout 안에서, 왼쪽에 위치.
-. right (0x05) : 부모 Layout 안에서, 오른쪽에 위치.
-. center_vertical (0x10) : 세로 기준으로 가운데 위치.
-. fill_vertical (0x70) : 세로 방향으로 가득 채움.
-. center_horizontal (0x01) : 가로 기준으로 가운데 위치.
-. fill_horizontal (0x07) : 가로 방향으로 가득 채움.
-. center (0x11) : 가로, 세로 기준으로 가운데 정렬.
-. fill (0x77) : 가로, 세로 방향으로 가득 채움.
-. clip_vertical (0x80) : 세로 기준으로 Layout을 넘어서는 영역 자르기.
-. clip_horizontal (0x08) : 가로 기준으로 Layout를 넘어서는 영역 자르기.
-. start (0x00800003) : 부모 Layout 안에서, 시작 위치에 정렬.
-. end (0x00800005) : 부모 Layout 안에서, 끝 위치에 정렬.
>> 부모 Layout이 RelativeLayout인 경우, 적용되지 않음.
◼️ layout_gravity 와 gravity 가 있는데 둘의 차이점은 내가 쉽게 말로하자면 layout_gravity은 부모 Layout 내에서 View가 정렬되는 위치를 결정하는 속성 gravity은 부모 Layout과는 관계없이, View 위젯 내에 표시되는 내용이 정렬되는 위치를 정하기 위한 속성
(쉽게 말해서 layout_gravity은 부모 레이아웃 속 안에 있는 뷰의 위치를 조정하는것이고 gravity은 자신의 view 안에 있는 내용의 위치를 조정하는것이다.)
✔️2.LinearLayout✔️
LinearLayout : Linear(선형, 선으로 된)라는 단어가 포함하는 의미대로, 자식(Children) 여러 View 위젯들을 가로 또는 세로 방향으로 나열할 때 사용하는 Layout 클래스 이다. (Vertical, Horizon 형식)
◼️LinearLayout의 orientation 속성을 사용하여 자식(Children) View 위젯의 배치 방향(가로/세로) 바꾸기◼️
- android:orientation="vertical" 형식-
>>말 그대로 버티컬 형식이고 일렬로 순차적으로 위에서 아래로 위젯을 형성하는 방식
- android:orientation="horizon" 형식-
>>말 그대로 호리즌 형식이고 일렬로 순차적으로 왼쪽에서 오른쪽으로 위젯을 형성하는 방식
◼️< 가중치(weight)를 이용한 영역 분할 >◼️
* android:layout_weight - 자식(Children) View 위젯이 차지하는 가중치(weight) 지정.
> 소수점 단위 사용 가능. (예. 1.2)
> 특정 단위가 아닌 전체에 대한 비율의 개념으로 사용.
> 지정하지 않았을 때의 기본 값은 0. (내용만큼의 크기 차지.)
> 가중치가 적용되는 방향(width 또는 height)의 값이 "0dp"이어야 한다.
◼️View 위젯들이 같은 비율을 가지도록 만들기◼️
LinearLayout의 자식(Children) View 위젯들이 같은 비율을 가지도록 만드려면 모든 자식(Children) View 위젯의
layout_weight 속성 값에 "1"을 지정한다. 즉, 모든 자식(Children) View 위젯을 같은 값의 layout_weight의 속성 값을
같게 준다.
◼️특정 View 위젯만 화면의 남는 공간 차지하도록 만들기◼️
LinearLayout의 자식(Children) 특정 View 위젯만 화면의 남는 공간 차지하도록 만드려면 먼저 layout_weight 속성 값이
지정되지 않게 View 위젯들을 자신의 영역 값에 지정된 wrap_content, match_parent 또는 고정 치수(dp, px, ...) 만큼
의 영역을 할당해주고, 나머지 영역에서 가중치 계산(weight설정)을 통해 view 위젯을 할당한다.
◼️LinearLayout의 일부 영역을 공백으로 만들기◼️
LinearLayout의 일부 영역을 공백으로 만들기 위해선 LinearLayout 전체 영역 비율을 값을 고정시켜 버리고 거기에
LinearLayout의 자식(Children) View 위젯들의 비율을 알맞게 할당시키는 것이다.
* android:weightSum - LinearLayout의 최대 가중치(weight) 값 지정.
> 소수점 단위 사용 가능. (예. 1.2)
> 지정되지 않을 시, 합산된(sum) 가중치는 자식(Children) View들의 모든 layout_weight값을 더하여 계산.
✔️3.RelativeLayout✔️
RelativeLayout : RelativeLayout은 자식(Children) View 위젯들이 서로 간의 상대적 배치 관계에 따라 화면에 표시될 위치가 결정되도록 만들어주는 Layout 클래스이다.
하지만 "Relative"라는 단어의 사전적 의미대로 "상대적인" 위치를 지정할 수 있지만, 그 대상이 반드시 RelativeLayout에 포함된 View 위젯이어야만 하는 것은 아니다. 또한 View 위젯들을 포함하는 RelativeLayout(View 위젯 입장에서는 부모(Parent)) 자체가 상대적 위치의 기준점으로 사용될 수도 있다.
(즉, 자식(Children) View 위젯들 A,B가 있다면 B의 위치를 A의 기준으로 삼아서 위치를 지정할 수 있는것이고 또한 부모 RelativeLaout을 기준으로 삼아서 자식(Children) View 위젯의 위치를 지정할 수 있는 것이다.)
>> 다수의 중첩 LinearLayout들로 구성된 사용자 인터페이스를 하나의 RelativeLayout으로 대체 가능할 정도로 RelativeLayout은 매우 효율적이고 강력한 활용성을 제공하지만, 개발자가 원하는 결과물을 만들기가 다소 어려운 것 또한 사실이므로 RelativeLayout 하나로만 구성하려 하지 말고, 상황에 맞게 다른 종류의 Layout을 섞어쓰는 것이 개발 시간을 단축시키는 하나의 방법이 될 수 있다.
일단 RelativeLayout에 배치 관련 속성을 지정하지 않은 뷰(View) 위젯을 추가하면, 추가된 자식(Children) 뷰(View) 위젯은 RelativeLayout의 왼쪽 위(Left, Top)에 표시된다. 자식 뷰 위젯은 각각 이루어져 있기 때문에 지정을 하지 않으면 왼쪽 위에 계속 겹쳐 (오버랩) 있는다.
◼️ RelativeLayout에서 사용 가능한 속성의 종류 ◼️
--------------------------------------------------------------
layout_toLeftOf 뷰(View)를 기준 뷰(Anchor View)의 왼쪽(Left)에 배치.
layout_above 뷰(View)를 기준 뷰(Anchor View)의 위(Above)에 배치.
layout_toRightOf 뷰(View)를 기준 뷰(Anchor View)의 오른쪽(Right)에 배치. >>> 뷰에 대한 기준들
layout_below 뷰(View)를 기준 뷰(Anchor View)의 아래(Below)에 배치.
layout_toStartOf 뷰(View)를 기준 뷰(Anchor View)의 시작(Start)에 배치.
layout_toEndOf 뷰(View)를 기준 뷰(Anchor View)의 끝(End)에 배치.
--------------------------------------------------------------
layout_alignParentLeft 뷰(View)를 부모(Parent) 영역 내에서 왼쪽(Left)에 배치.
layout_alignParentTop 뷰(View)를 부모(Parent) 영역 내에서 위쪽(Top)에 배치.
layout_alignParentRight 뷰(View)를 부모(Parent) 영역 내에서 오른쪽(Right)에 배치.
layout_alignParentBottom 뷰(View)를 부모(Parent) 영역 내에서 아래쪽(Bottom)에 배치.
layout_centerHorizontal 뷰(View)를 부모(Parent) 영역의 가로 방향 가운데 배치. >>> 부모 영역에 대한 기준들
layout_centerVertical 뷰(View)를 부모(Parent) 영역의 세로 방향 가운데 배치.
layout_centerInParent 뷰(View)를 부모(Parent) 영역의 정 중앙(center)에 배치.
layout_alignParentStart 뷰(View)를 부모(Parent) 영역의 시작 지점(Start)에 배치.
layout_alignParentEnd 뷰(View)를 부모(Parent) 영역의 끝 지점(End)에 배치.
----------------------------------------------------------------
layout_alignLeft 뷰(View)의 왼쪽(Left)을 기준 뷰(View)의 왼쪽(Left)에 맞춤.
layout_alignTop 뷰(View)의 위(Top)를 기준 뷰(View)의 위(Top)에 맞춤. >>> 뷰에 대해서 뷰의 기준점에 대한 기준들
layout_alignRight 뷰(View)의 오른쪽(Right)를 기준 뷰(View)의 오른쪽(Right)에 맞춤.
layout_alignBottom 뷰(View)의 아래(Bottom)를 기준 뷰(View)의 아래(Bottom)에 맞춤.
layout_alignBaseline 뷰(View)의 폰트 기준선(Baseline)을 기준 뷰(View)의 폰트 기준선(Baseline)에 맞춤.
----------------------------------------------------------------
◼️ RelativeLayout을 하면서 느낀것인데 부모 RelativeLayout 안에 있는 자식(Children) 뷰(View) 위젯은 각각 독립적이라고 생각을 하고 부모에 대한 위치를 맞추던지 뷰에 대한 기준들을 한 개 맞추고 나서 뷰에 대한 뷰의 기준점(align~) 속성으로 맞춘다.
즉, 가로 세로를 각각 생각해주고 둘 다 설정을 해줘야 한다는것이다.
✔️4.FrameLaout✔️
FrameLayout : FrameLayout은 주로 하나의 자식 View 위젯만 표시할 때 사용하는 Layout 클래스이다. 하지만 오직 하나의 자식 View 위젯을 가질 수 있다는 의미가 아니다. 즉, FrameLayout에 여러 View 위젯을 자식으로 추가하면 겹쳐진 형태로 표시되며, 가장 최근에 추가된 View 위젯이 가장 상위(on top)에 표시된다. 이러한 특징을 이용해 가장 상위의 View 위젯만 표시하고 나머지는 보이지 않게 만듦으로써 하나의 자식 View만 표시되도록 만드는 것이다.
(리니어레이아웃과 렐러티브레이아웃은 자신들에게 포함된 다양한 뷰 위젯을 화면에 정렬할 때 사용하곤 하지만 화면에 뷰 위젯을 표시함에 있어 주 목적이 다른 클래스(자식으로 추가된 여러 뷰 위젯들 중 하나를 Layout의 전면에 표시함)가 FrameLayout 이다.)
>> 가장 많이 사용되는 예 중 한가지는 Fragment를 사용하는 경우이다. 특히 여러 Fragment를 동일한 위치 내에서 교체하여 표시하고자 할 때, Fragment의 컨테이너 역할로써 FrameLayout을 주로 사용한다.
◼️FrameLayout 내 자식(Children) 뷰 위젯의 위치 조절◼️
* android:layout_gravity - 자신이 속한 부모 Layout내 자신의 정렬 위치 값 지정.
> 부모 Layout 내에서 x축(좌/우)과 y축(상/하)을 기준으로 정렬.
> 아래 값들 중에서 하나 이상의 값을 '|' 기호로 혼합하여 사용.
-. top (0x30) : 부모 Layout 안에서, 위쪽에 위치.
-. bottom (0x50) : 부모 Layout 안에서, 아래쪽에 위치.
-. left (0x03) : 부모 Layout 안에서, 왼쪽에 위치.
-. right (0x05) : 부모 Layout 안에서, 오른쪽에 위치.
-. center_vertical (0x10) : 세로 기준으로 가운데 위치.
-. fill_vertical (0x70) : 세로 방향으로 가득 채움.
-. center_horizontal (0x01) : 가로 기준으로 가운데 위치.
-. fill_horizontal (0x07) : 가로 방향으로 가득 채움.
-. center (0x11) : 가로, 세로 기준으로 가운데 정렬.
-. fill (0x77) : 가로, 세로 방향으로 가득 채움.
-. clip_vertical (0x80) : 세로 기준으로 Layout을 넘어서는 영역 자르기.
-. clip_horizontal (0x08) : 가로 기준으로 Layout를 넘어서는 영역 자르기.
-. start (0x00800003) : 부모 Layout 안에서, 시작 위치에 정렬.
-. end (0x00800005) : 부모 Layout 안에서, 끝 위치에 정렬.
> 기본 정렬은 가로 방향 start, 세로 방향 top.
(여기서 볼 점은 가로 세로를 두 개 다 지정해 줘야 한다. 예를 들어 가운데 위의 위치를 하기 위해선 layout_gravity=center_horizontall|top 이렇게 지정을 하는데 가로 세로를 or 로 합쳐서 지정한다.)
FrameLayout에 여러 개의 자식(Children)을 추가하면, 기본적으로 가장 마지막에 추가된 뷰(View)가 가장 전면에 표시된다.
◼️XML) FrameLayout에 추가된 자식(Children) 뷰의 보이기(Visibility) 속성 사용 ◼️
최초 화면에 표시될 뷰(View)만 visibility 속성 값을 "visible"로 지정하고, 나머지 뷰(View)는 "invisible"로 지정하게 되면 visible로 지정된 뷰만 화면에 뜨고 invisible로 지정된 뷰는 화면에 뜨지 않는다. Ex) android:visibility="visible"
◼️java) 자바 코드에서는, 뷰(View)의 참조를 가져온 다음, 뷰의 setVisibility() 함수를 사용하여 화면 표시 여부를 결정◼️
Ex) private void changeView(int index) {
TextView textView1 = (TextView) findViewById(R.id.text1) ;
TextView textView2 = (TextView) findViewById(R.id.text2) ;
switch (index) {
case 0 :
textView1.setVisibility(View.VISIBLE) ;
textView2.setVisibility(View.INVISIBLE) ;
break ;
case 1 :
textView1.setVisibility(View.INVISIBLE) ;
textView2.setVisibility(View.VISIBLE) ;
break ;
}
}
◼️ 프레임 레이아웃을 사용하는 방법에는 2가지가 있다.
- 1번째 방법은 레이아웃 리소스 XML에서 FrameLayout의 자식(Children) 뷰 위젯들을 미리 추가 해놓고, 앱 시작 시 화면에 표시할 뷰(View)를 제외한 모든 뷰를 removeView() 함수로 제거한다. 그리고 나서 버튼 클릭 이벤트에 따라 removeView()와 addView() 함수를 호출하여 뷰(View)를 바꿔 표시하는 방법이다. 즉 이 방법인 하나의 레이아웃 리소스 XML의 FrameLayout 아래에 모든 자식(Children) 뷰 위젯들을 선언하는 방법은 좋지 않은 방법이다. 왜냐하면 자식(Children) 뷰 위젯의 갯수가 많아지고 구조가 복잡해지면, 그에 따라 레이아웃 리소스 XML의 내용도 늘어나므로, 소스를 작성하고 수정하는 작업이 매우 번거로워 질 수 있기 때문이다. 그래서 나온 방법이 2번째다.
- 2번째 방법은 코드 작성 및 관리를 편하게 수행하기 위해 개발자가 취할 수 있는 방법으로, FrameLayout에 표시될 자식(Children) 뷰를 각각 별도의 레이아웃 리소스 XML로 분리하여 작성한 다음, LayoutInflater를 사용하여 View로 변환하는 것이다.
- 3번째 방법은 JAVA코드에서 setVisibility() 함수를 사용해서 뷰(View)의 보이기(visibility) 설정을 하는것이다.
setVisibility(View.GONE) : View가 보이지 않음. 레이아웃 영역 차지 안함. setVisibility(View.INVISIBLE) : View가 보이지 않음. 하지만 레이아웃을 위한 영역 차지함. setVisibility(View.VISIBLE) : View가 화면에 보임.
LayoutInflater : 리소스 XML 파일에 선언된 레이아웃을 자바 코드 상에서 View 객체로 변환할 때 사용하는 클래스
-LayoutInflater 참조 방법 2가지-
// 방법 1.
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 방법 2.
LayoutInflater inflater = getLayoutInflater() ;
>> LayoutInflater의 참조를 획득하면 inflate() 함수를 사용할 수 있는데 이것을 이용하여 리소스 XML 파일에 선언된 레이아웃을 View 객체로 변환 할 수 있다.
◼️inflate(resource: Int, root: ViewGroup?, attachToRoot: Boolean) 함수의 매개변수◼️
resource: View를 만들고 싶은 레이아웃 파일의 id입니다. R.layout.my_view
root: 생성될 View의 parent를 명시해줍니다. null일 경우에는 LayoutParams값을 설정 할 수 없기 때문에 XML내의 최상위 android:layout_xxxxx값들이 무시되고 merge tag를 사용 할 수 없습니다.
attachToRoot: true 로 설정해 줄 경우 root의 자식 View로 자동으로 추가됩니다. 이때 root는 null 일 수 없습니다.
return: attachToRoot에 따라서 리턴값이 달라집니다. true일 경우 root가, false일 경우 XML내 최상위 뷰가 리턴됩니다.
Ex) LayoutInflater의 inflater()함수를 이용한 예
package com.example.sample;
import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
@RequiresApi(api = Build.VERSION_CODES.M)
public class MainActivity<index> extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.framelayout);
changeView(0); //첫번째 뷰가 표시되도록 하기 위해 index 0 값을 준다.
Button button1 = (Button) findViewById(R.id.button1); //버튼1에 대한 객체 생성
button1.setOnClickListener(new View.OnClickListener() { // 버튼1 클릭을 했을때
@Override
public void onClick(View view) {
changeView(0); //index 0의 값 첫번째 뷰 표시
}
});
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
changeView(1);
}
});
Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
changeView(2);
}
});
}
private void changeView(int index) {
/*LayoutInflater는 리소스 XML 파일에 선언된 레이아웃을 자바 코드 상에서 View 객체로 변환할 때 사용하는 클래스이다.
>> LayoutInflater를 통해 획득된 View 객체는 리소스 XML에 작성된 모든 뷰 그룹(ViewGroup) 및 뷰(View)를
포함하므로, findViewById() 함수를 통해 뷰에 포함된 위젯에 대한 참조를 획득 */
// LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = getLayoutInflater() ; // LayoutInflater의 참조 획득
// >> inflate()함수 호출하여 리소스 XML 파일에 선언된 레이아웃을 View 객체로 변환 가능
FrameLayout frame = (FrameLayout) findViewById(R.id.frame) ; // FrameLayout 의 frame 참조 획득
if (frame.getChildCount() > 0) {
// FrameLayout에서 뷰 삭제.
frame.removeViewAt(0);
}
// XML에 작성된 레이아웃을 View 객체로 변환.
View view = null ;
switch (index) {
case 0 :
view = inflater.inflate(R.layout.page1, frame, false) ; // inflater 함수 이용
break ;
case 1 :
view = inflater.inflate(R.layout.page2, frame, false) ; // inflater 함수 이용
break ;
case 2 :
view = inflater.inflate(R.layout.page3, frame, false) ; // inflater 함수 이용
break ;
}
// FrameLayout에 뷰 추가.
if (view != null) {
frame.addView(view) ;
}
}
}
✔️5.TableLayout✔️
TableLayout : TableLayout은 자식(Children) View 위젯들을 테이블(행과 열로 구성)표로 나누어 표시하는 Layout 클래스이다.
TableLayout에 View 위젯을 추가하기 위해서는
1. TableRow 클래스를 사용하여 하나의 행을 추가해야 한다.
2. 추가된 각 행에 View 위젯을 추가하면 테이블 형태로 정렬되어 표시된다.
TableLayout의 전체 열(Column) 개수는 Ta'''bleRow 중 가장 많은 열(Column)의 개수에 맞춰진다.
(사용 예로는 계산기를 만들때 버튼 누르는 형식 이라던지 열과 행을 구분 지을 수 있는곳에 사용된다.)
(TableLayout은 행을 추가하는 요소는 <TableRow>를 이용하고 열을 추가하는 요소는 따로 없다. 그래서 <TableRow>에서 자식 뷰 위젯을 추가하는 것만으로도 열을 자동으로 추가하는 결과를 얻을 수 있다.)
LinearLayout이 TableLayout의 부모이고 TableLayout는 TableRow의 부모이다.(LinearLayout>TableLayout>TableRow)
◼️TableLayout의 속성◼️
<TableRow>를 이용하여 행을 계속 추가하여 표를 만든다.
TableLayout의 최대 열(Column)의 갯수 : 가장 많은 자식(Chilren)을 가진 TableRow에 맞춰진다.
TableLayout 열(Column)의 너비 : 가장 넓은 열(Column)의 너비에 맞춰짐(열의 개수가 같다는 가정)
TableLayout 행(Row)의 높이 : 가장 높은 셀(Cell)의 높이에 맞춰진다.
TableLayout 전체 또는 개별 행(Row)의 배경색 지정하기 위해 background를 이용한다.(TableLayout의 전체 배경색을 지정하고 개별 행에 대해서 padding, margin을 이용하여 테두리가 그려진 효과를 나타낼 수 있다.)
* android:stretchColumns - 늘이고자 하는 열(Column)의 인덱스 지정.
> 열(Column)의 인덱스는 0부터 시작. (zero-based)
> 하나 이상의 열(Column)을 ','(comma)로 분리하여 지정. (예. "0,2,4")
> 모든 열(Column)을 지정하려면, '*'기호 사용.
>>즉, 한 행의 열의 너비를 동일하게 맞추기 위해 android:stretchColumns="*" 을 사용한다.
* android:layout_column - 뷰(View)가 추가될 열(Column) 인덱스 지정.
> 열(Column)의 인덱스는 0부터 시작. (zero-based)
> 정수 값 사용. (예. 3)
>>즉, 어디서 부터 추가될 지 열을 지정하기 때문에 띄엄띄엄 표를 만들 수 있다.
* android:layout_span - 합치고자 하는 셀(Cell)의 개수 지정.
> 정수 값 사용. (예. 3)
> 열(Column) 방향으로만 셀(Cell) 합치기 가능.
> 값이 지정된 셀(Cell)의 오른쪽 방향으로 셀(Cell)이 합쳐짐.
> 1이상의 값 사용 가능.
>>즉, 열을 합치는 기능이다.
* android:collapseColumns - 감추고자 하는 열(Column)의 인덱스 지정.
> 열(Column)의 인덱스는 0부터 시작. (zero-based)
> 하나 이상의 열(Column)을 ','(comma)로 분리하여 지정. (예. "0,2,4")
> 모든 열(Column)을 지정하려면, '*'기호 사용.
>>즉, 예를들면 부모 <TableLaout>에서 android:collapseColumns="1,2"을 지정하여서 자식<TableRow>행들의 1,2열을 보이지 않게 만드는 속성이다.
* android:shrinkColumns - 줄이고자 하는 열(Column)의 인덱스 지정.
> 열(Column)의 인덱스는 0부터 시작. (zero-based)
> 하나 이상의 열(Column)을 ','(comma)로 분리하여 지정. (예. "0,2,4")
> 모든 열(Column)을 지정하려면, '*'기호 사용.
>>즉, TableLayout의 내용이 전체 너비를 넘어버리는 경우 우리가 선택할 수 있는 가장 직관적인 방법이다.
◼️ >>>>>>>>>>> 정리 <<<<<<<<<<< ◼️
TableLayout을 정리해서 본다면
일단 부모 TableLayou에 android:stretchColumns="*" , android:shrinkColumns="*" 을 적어놓고 시작하는것이 좋다. 왜냐하면 행의 열을 공정하게 열을 나누고, 전체 너비를 넘어버리는 경우를 대비해서 이기 때문이다.
또한 <TableRow> 행(가로)의 자식들이 동등한 비율의 열을 주기 위해서는 <TableRow> 행(가로)의 자식들을 width=0dp로 주고, weight=1로 각각 주면<TableRow> 행(가로) 들의 자식들이 동등한 비율을 가지는 행을 만들 수 있다.
또한 <TableRow> 행(가로)들을 각각 동등한 비율의 높이를 주기 위해서는 <TableRow> 에서 height=0dp로 주고, weight=1로 각각 주면 <TableRow> 행(가로)들이 동등한 비율의 높이를 가진다.
✔️6.ListView와 GridView✔️
ListView와 GridView : 클래스 이름에 "Layout"이라는 단어가 포함되지 않고 위에서 언급한 보편적인 Layout들과 사용 방법이 달라 Layout이 아닌 것으로 착각 할 수도 있지만, 엄연히 ViewGroup으로부터 상속받은 Layout 클래스의 한 종류 이다.
(사용 예로는 동일한 자식(Children) View 위젯을, 내용만 달리하여 반복적으로 표시해야 하는 경우 ListView와 GridView가 매우 유용하게 사용될 수 있다.)
✔️6-1.ListView✔️
ListView : 사용자가 정의한 데이터 목록을 아이템 단위로 구성하여 화면에 출력하는 ViewGroup의 한 종류이다. ListView의 아이템들은 세로 방향으로 나열되며, 아이템의 개수가 많아짐에 따라 ListView에 표시될 내용이 ListView의 크기(width,height)를 넘어서게 되면 스크롤 기능을 사용해 ListView의 표시 기준 위치를 이동시킬 수 있다.
ListView에 표시되는 아이템은 단순히 Text만 출력하는 구조가 될 수 있고, Image, Button, CheckBox 등 여러 View의 조합으로 구성되는 좀 더 복잡한 형태(Custom)가 될 수도 있다.
ListView는 UI(User Interface)를 구성함에 있어 가장 많이 사용되는 컴포넌트 중 하나이다.
Ex) 안드로이드 시스템의 연락처, 환경설정 등이 ListView의 대표적인 예이다.
◼️View vs ViewGroup◼️
- View : 사용자에게 어떤 내용을 보여주거나 입력을 받아들이기 위해 화면에 그려지는 기본 객체를 말한다. TextView, Button, CheckBox 등이 대표적이다.
- ViewGroup : 이름 그대로 View들이 모인 Group을 말합니다. 즉, 화면에 표시할 하나 이상의 View를 포함하는 컨테이너 역할을 수행하는 것이죠. Layout, ListView 등이 ViewGroup에 속하며 View뿐만 아니라 ViewGroup 또한 포함할 수 있다.
ListView는 ViewGroup에 속합니다. 즉, 데이터를 화면에 표시하기 위해서는 View(또는 ViewGroup) 객체가 ListView에 추가되어야 하며, 하나의 View(또는 ViewGroup)는 하나의 아이템 정보를 표시하게 된다.
즉, ViewGroup은 View 객체(버튼,TextView)들이 모인 그룹이다.
◼️ ListView에 데이터를 추가하여 화면에 표시하기 위해서는 Adapter를 사용해야한다.
Adapter는 적합하지 않은 두 개의 부분을 전기적 또는 기계적으로 접속하기 위한 장치 또는 도구를 말한다.
즉, 여기에서는 Adapter란 사용자가 정의한 데이터를 ListView에 출력하기 위해 사용하는 객체로, 사용자 데이터와 화면 출력 View로 이루어진 두 개의 부분을 이어주는 객체이다. 더 쉽게 말해서 Adapter가 하는 역할은 사용자 데이터를 입력받아 View를 생성하는 것이며 Adapter에서 생성되는 View는 ListView 내 하나의 아이템 영역에 표시되는 것이다.
[ 참고 : https://recipes4dev.tistory.com/42 ]
다양한 컴포넌트(TextView,ImageView,Button)들로 구성된 ListView를 만들기 위해서는 조금 번거로운(?) 작업을 해줘야 한다. 예를들어 ListView 아이템에 대한 Layout을 구성해야 하고, Layout에 출력될 데이터에 대한 새로운 클래스를 정의해야 하며, 사용자 데이터를 Layout에 정의된 형태의 View로 변환하기 위한 Adapter 클래스도 상속받아 필요한 함수를 채워줘야 한다. 이렇게 기본 ListView로부터 확장된 기능을 가지는 ListView를 Custom ListView라고 말한다.
Custom ListView : 일반적으로 안드로이드 앱에 사용하는 ListView는 단순히 문자열만 표시하기보단 이미지나 버튼 또는 크기가 다른 문자열 등으로 구성하는 경우가 더 많은데 이렇게 단순 문자열만이 아닌 여러 종류의 위젯을 하나의 아이템으로 구성한 ListView를 Custom ListView라고 하며, 안드로이드 앱을 만들 때 가장 많이 사용하는 컴포넌트 중 하나이다.
◼️일반적인 ListView를 사용하기 위한 순서◼️
1.ListView가 표시될 위치 결정.(Layout 리소스 XML 작성)에 대한 방법은 XML파일에 ListView를 어떤 위치에 넣을지 작성한다.
2.사용자 데이터 정의.(String 타입의 배열 선언)에 대한 방법은 자바코드에서 아이템에 표시될 데이터를 정의하던지 xml에서 아이템에 표시될 데이터를 정의하던지 한다.
[데이터가 수시로 추가되고 삭제되고 변경이 자주 생긴다. --> 자바코드에서 데이터를 만든다.
데이터의 변경 없이 일정하다 --> xml상에 데이터를 만든다.]
3. 데이터가 준비되었으니 해당 데이터를 입력받아 View로 만들어줄 Adapter를 생성한다.
Ex)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState) ;
setContentView(R.layout.viewList) ; //listview를 만든 xml 파일과 연결해준다.
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, LIST_MENU) ;
/*ArrayAdapter 객체를 생성하고 3개의 파라미터에 대해서는 context : 안드로이드 시스템에서 제공되는 어플리케이션 전역 환경 정보에 대한 인터페이스. (Activity를 통해 사용 가능) resource : View로 매핑될 Resource Id. "android.R.layout.simple_list_item_1"은 TextView 위젯으로 구성된 ListView 아이템 리소스 Id.
objects : 배열로 선언된 사용자 데이터.
>> 여기서 resource의 종류로는 simple_list_item_1 : 텍스트뷰 하나로 구성된 레이아웃, simple_list_item_ : 텍스트뷰 두개로 구성된 레이아웃, simple_list_item_checked : 오른쪽에 체크 표시가 됨, simple_list_item_single_choice : 오른쪽에 라디오 버튼이 나옴, simple_list_item_multiple_choice : 오른쪽에 체크버튼이 나옴 */
ListView listview = (ListView) findViewById(R.id.listview1) ; // xml파일에서 만든 listview를 참조한다.
listview.setAdapter(adapter) ;
}
4. ListView가 사용자의 아이템 터치 입력을 받을 수 있도록 만들기 위해선 ListView에 Click 이벤트에 대한 리스너를 설정해준다.
Ex)
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// 코드 계속 ...
@Override
public void onItemClick(AdapterView parent, View v, int position, long id) {
// get TextView's Text.
String strText = (String) parent.getItemAtPosition(position) ;
// TODO : use strText
}
}) ;
◼️일반적인 Custom ListView를 사용하기 위한 순서
1.ListView가 표시될 위치 결정.(Layout 리소스 XML 작성)에 대한 방법은 XML파일에 ListView를 어떤 위치에 넣을지 작성한다.
2.일반 ListView에 대해서는 Layout에 대한 구성을 고민하지 않았지만(하나의 아이템(TextView)으로 만들어짐) 하지만 Adapter를 생성하는 과정에서 "android.R.layout.simple_list_item_1"를 전달함으로써 아이템에 대한 Layout을 지정했다.
Custom ListView는 직접 ListView 아이템 Layout에 대한 구성을 하야한다. 즉, ListView 아이템 XML을 구성(작성)해야한다.
3.ListView 아이템을 위한 Layout 리소스를 정의했다면 아이템에 출력될 데이터를 위한 클래스를 정의해야 하는데, 아이템에 표시될 위젯에 맞게 원하는대로 클래스 멤버를 결정하면 된다.
즉, ListViewItem 이라는 이름으로 새로운 클래스를 생성한다. (ListViewItem.java)
예제에서는 ImageView와 TextView 2개를 사용하므로 Drawable과 String으로 멤버 변수를 정의한다.
Ex)
public class ListViewItem {
private Drawable iconDrawable ;
private String titleStr ;
private String descStr ;
public void setIcon(Drawable icon) {
iconDrawable = icon ;
}
public void setTitle(String title) {
titleStr = title ;
}
public void setDesc(String desc) {
descStr = desc ;
}
public Drawable getIcon() {
return this.iconDrawable ;
}
public String getTitle() {
return this.titleStr ;
}
public String getDesc() {
return this.descStr ;
}
}
4. ListView 아이템 UI를 위한 Layout 리소스도 작성했고 아이템 데이터를 위한 클래스도 만들었으면 이제 할 일은 둘 간을 연결해 줄 Adapter를 구현해야 한다.
일반 ListView에서는 별도의 Adapter를 구현하지 않고 안드로이드 SDK에서 제공하는 ArrayAdapter를 사용했다.( 아이템이 TextView만으로 구성되고(simple_list_item_1) 데이터가 String 배열이기 때문에 ArrayAdapter만으로 그 기능을 제공할 수 있기 때문 )
하지만 Custom ListView는 상황이 다르다. 즉, 데이터도 새로 정의한 클래스로 확장되었고 ListView 아이템도 여러 위젯으로 구성되어서 이에 따라 Adapter 기능도 확장해야 한다.
Adapter를 새롭게 구현할 때 안드로이드 SDK 에서 제공하는 Adapter 중 어떤 Adapter 클래스를 부모로 사용할 지 결정해야하는데 이때 본인이 구현하고자 하는 Adapter의 기능에 적합한 것을 선택하면 되는데 보통 ArrayAdapter 또는 BaseAdapter를 많이 사용한다. 일단 예제에서는 BaseAdapter를 사용하겠다. (public class ListViewAdapter extends BaseAdapter () 클래스(.java)를 만든다.)
5.사용자 데이터를 정의한다.
6. Mainactivity에 ListViewAdapter에서 만든 Adapter를 생성하고 데이터를 추가해준다.
7. 마지막으로 ListView 아이템 클릭 이벤트에 대한 처리를 해줍니다. ListView 아이템이 클릭되었을 때 호출되는 onItemClick() 함수에서 ListView 아이템 정보를 가져오려면 파라미터로 전달되는 변수들을 사용하면 됩니다. 각 파라미터에 대한 설명은 아래와 같습니다.
parent : ListView 자체에 대한 참조.
view : 클릭이 발생한 View에 대한 참조.
position : Adapter에서의 view의 position.
id : 클릭된 아이템의 row id.
여기서 parent를 통해 getItemAtPosition() 함수를 사용하면 position에 해당하는 아이템 데이터를 가져올 수 있다.. 단, getItemAtPosition() 함수의 리턴 타입은 Object 타입이므로 소스에서 정의한 아이템 데이터 타입으로 형변환을 해줘야 한다.
✔️6-2.GridView✔️
그리드뷰(GridView) : 2차원 격자무늬 형태의 레이아웃으로 행과 열의 집합형태로 구성된 레이아웃이다. TableLayout의 단점을 보완한 레이아웃으로 LinearLayout 또는 FrameLayout과 같은 다른 레이아웃의 장점을 포함하는 레이아웃이다. GridLayout을 사용할 시 다른 레이아웃과 중첩으로 사용할 필요가 없어 메모리 사용량을 줄일 수 있다는 장점이 있다.