대표적인 레이아웃 5개 중 일단 3개만 보겠다. 제약(Constraint) 레이아웃, 리니어(Linear) 레이아웃, 프레임(Frame) 레이아웃. +스크롤뷰
나머지 상대(Relative) 레이아웃이랑 테이블(Table) 레이아웃은 잘 사용하지 않는다고 함
LinearLayout은 orientaion을 꼭 설정해줘야함.(vertical 또는 horizontal)
뷰 영역 : Border(뷰의 테두리) / Box(뷰의 영역) / Margin(테두리 바깥쪽 공간) / Padding(테두리 안쪽 공간) / Content(내용물)
<앱 첫 실행 화면 변경>
아래와 같이 manifests의 AndroidManifest.xml 파일에서 <activity 안의 name 부분을 수정해주면,
앱 실행 시 첫 시작 화면이 바뀐다. (MainActivity.java에서 새로 만든 LayoutCode_Activity.java로 변경함)
<xml 말고 java 파일로 뷰 만들기>
화면 레이아웃은 주로 xml로 만들지만 가끔 소스코드에서 만들기도 하기에.. 알아두는 것이 좋다.
이 코드는 MainActivity.java를 복붙한 뒤 super. 아랫줄부터 수정한 코드이다.
아래와 같이 레이아웃으로 만든 객체를 setContentView 메서드의 파라미터로 전달하면 그 레이아웃이 화면에 표시된다.
new 연산자를 사용해서 뷰 객체를 만들 때는 항상 Context 객체가 전달되어야 하는데, AppCompatActivity 클래스는 Context를 상속하므로 this를 Context 객체로 사용할 수 있는 것이다.
(만약 Context를 상속받지 않은 클래스에서 Context 객체를 전달해야 한다면 getApplicationContext라는 메서드를 호출하여 사용 가능하다.)
LayoutParams 객체 : 자바 소스 코드에서 뷰 배치를 위한 속성을 설정할 수 있는 객체. 반드시 뷰의 가로와 세로 속성을 지정해줘야 한다. (MATCH_PARENT 또는 WRAP_CONTENT)
<layout_gravity와 gravity>
버튼 추가 후 오른쪽의 속성 창을 본다. 맨 아래로 스크롤하면 All Attributes 탭이 있는데 그걸 열면 모든 속성이 나온다.
그 중 layout_gravity와 gravity를 바꿀 수 있다.
layout_gravity는 위와 같이 뷰가 어디에 위치할 것인지를 결정하는 것이다.
left / center / right 로 나뉘어진다.
gravity는 뷰 안에 들어있는 내용물의 위치를 결정하는 것이다.
위와 같이 청사진을 보면 Textview는 사실 가로 공간을 전부 차지하고 있지만, 그 안의 내용물이 어디에 위치하는지에 따라 left / center / right에 위치한다.
gravity는 여유 공간 내에서 이동하는 거라, 버튼이나 텍스트뷰의 크기를 wrap_content로 지정할 경우 gravity 속성을 지정해도 변화는 없다.
<baselineAligned로 텍스트 높이 맞추기>
제약 레이아웃의 경우 연결선만 이어주면 텍스트 높이가 알아서 맞춰진다.
리니어 레이아웃은... 사실 기본으로 텍스트 높이가 맞춰져있다. 왜냐면 baselineAligned 속성의 디폴트값이 true이기 때문이다.
최상위 레이아웃인 리니어 레이아웃에서 All Attributes 속성 속 baslineAligned 값을 false로 바꿔주면 위와 같이 text 높이가 제각각 달라지는 것을 확인할 수 있다.
<layout_weight으로 여유 공간 분할하기>
위 사진의 청사진을 보면 모두 layout_weight 속성이 0이 되어서 자기 자신만큼 공간을 차지한다.
만약 위 사진의 뷰들이 모두 layout_weight 속성 1을 가지고 있다면 아래와 같이 된다.
그렇다면 layout_weight가 정확히 뭐냐? 비율이다. 그 값의 비율만큼 여유 공간을 분할한 후 해당 뷰에게 할당하는 것이다.
위 사진의 경우 모두 layout_weight이 1이므로 각각 1:1:1의 비율만큼 차지하는 것이다.
(ex. 만약 1, 2, 3 이렇게 들어간다면 각각 1:2:3의 비율만큼 차지하여 6분의 1 / 6분의 2 / 6분의 3 이렇게 나눠서 할당되는 것이다.)
근데 각각의 뷰의 layout_width(또는 layout_height)가 wrap_content가 되면 안되고 0dp로 설정해줘야 함. (책 133p~134p 참조)
사실 왜 이렇게 해야하는지 이해는 못했는데 일단 넘어가자..
상대 레이아웃이랑 테이블 레이아웃도 간단히 읽어보기는 함. 많이 사용하지는 않는다고 해서 굳이 예제까지 따라하진 않음.
<테이블 레이아웃 - 뷰의 전환>
테이블 레이아웃은 뷰를 중첩한다. 나중에 추가할 수록 위에 쌓이는 형태임.
가시성(Visibility) 속성을 사용해서 특정 뷰를 보이거나 보이지 않게 하는 효과를 만들 수 있다. 이를 이용하여 뷰가 전환되는 효과를 만들어보겠다. (사실 뷰의 전환은 뷰페이저(ViewPager) 위젯을 사용하면 더 쉽게 만들 수 있다.)
1. 먼저 이미지를 넣는 방법. app>res>drawable 폴더에 넣으려는 이미지 파일을 Ctrl+드래그로 복사한다.
넣으면서 이름이 영어 소문자로 시작하는지, 소문자+숫자+_로 이루어져있는지 체크하고 조건에 해당하지 않는 이름이면 넣을 때 이름을 바꾼다.
이렇게 프로젝트의 drawable 폴더 안에 'snow'랑 'blue_snow' 사진 파일을 넣었다.
2. Component Tree에서 최상위 레이아웃을 LinearLayout으로 바꾼다. > 버튼 추가 > 팔레뜨에서 FrameLayout을 추가한다.
3. 팔레뜨에서 ImageView를 2개 추가한다. (ImageView를 추가할 때마다 자동으로 무슨 이미지를 사용할지 화면이 뜬다. 거기서 이전에 추가해놓은 파일로 설정하면 된다.)
ImageView의 속성을 보면 아래와 같이 visibility를 설정할 수 있다.
4. MainActivity.java의 메인 코드를 아래와 같이 바꿔준다.
public class MainActivity extends AppCompatActivity {
ImageView imageView;
ImageView imageView2;
int imageIndex = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.imageView);
imageView2 = findViewById(R.id.imageView2);
/*ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});*/
}
public void onButton1Clicked(View v){
changeImage();
}
private void changeImage(){
if(imageIndex==0){
imageView.setVisibility(View.VISIBLE);
imageView2.setVisibility(View.INVISIBLE);
imageIndex=1;
}
else if(imageIndex==1){
imageView.setVisibility(View.INVISIBLE);
imageView2.setVisibility(View.VISIBLE);
imageIndex=0;
}
}
}
5. 레이아웃 xml 파일에서 버튼에 onClick 속성 > OnButton1Clicked 로 설정해준다.
이러면 앱 실행 후 버튼을 누르면, 누를 때마다 이미지가 전환된다.
imageView = findViewById(R.id.imageView);
XML에서 id 지정할 때는 @+id/아이디
자바 소스 코드에서 id 지정할 때는 R.id.아이디
이다.
<스크롤뷰 사용하기>
스크롤뷰는 기본적으로 수직 방향이다.
예제를 따라할 건데 수평도 되고 수직도 되는 스크롤뷰를 만들거라서
먼저 1. xml에 수평방향 스크롤뷰 넣고 2. 거기에 기본(수직) 스크롤뷰 넣어서 3. 그 안에 이미지뷰 넣기
이게 개헷갈렸음.
<헷갈린 것들>
1. 스크롤뷰 Orientation 설정에서 수직/수평 바꿀 수 있는 줄 알았는데 그냥 팔레뜨에서 Containers 들어가면 그냥 ScrollView랑 HorizontalScrollView로 나뉘어져 있음.
2. HorizontalScrollView에 ScrollView를 집어넣으라는데 안됨. (계속 흰 화면에 스크롤뷰 드래그 하는데 아무일도 안 일어남) 근데 HorizontalScrollView 하위에 자동으로 생성된 LinearLayout을 삭제해야함. 삭제 후 Component Tree 리스트 안의 HorizontalScrollView로 드래그하니까 잘 넣어짐.
3. imageView도 마찬가지임. ScrollView 하위에 자동으로 생성된 LinearLayout을 제거한 뒤 넣으면 해결됨.
4. MainActivity에 코드 그대로 똑같이 따라 치는데
scrollView = findViewById(R.id.scrollView);
이 부분이 자꾸 에러가 뜨는 거임. id 뒤쪽의 scrollView에 빨간줄이 쳐지길래, xml에 있는 코드를 봤다.
근데 <ScrollView 코드 안에
android:id="@+id/scrollView"
이게 없었다. 그래서 id 지정해주는 코드를 추가해주니까 바로 해결.
<MainActivity 코드>
public class MainActivity extends AppCompatActivity {
ScrollView scrollView;
ImageView imageView;
BitmapDrawable bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = findViewById(R.id.scrollView);
imageView=findViewById(R.id.imageView);
scrollView.setHorizontalScrollBarEnabled(true); // 수평 스크롤바 사용 기능 설정
Resources res = getResources(); // *
bitmap=(BitmapDrawable) res.getDrawable(R.drawable.snow);
int bitmapWidth = bitmap.getIntrinsicWidth(); // *
int bitmapHeight = bitmap.getIntrinsicHeight(); // *
imageView.setImageDrawable(bitmap); // *
imageView.getLayoutParams().width = bitmapWidth; // *
imageView.getLayoutParams().height = bitmapHeight; // *
}
public void onButton1Clicked(View v){
changeImage();
}
private void changeImage(){
// * (생략. 위랑 동일(실제 코드에선 생략하면 안됨!))
bitmap = (BitmapDrawable) res.getDrawable(R.drawable.blue_snow);
// * // * // * // * // *
}
}
getResources, getDrawable 메소드가 이번의 핵심. 일단 가볍게 보고 넘어감.
(참고로 이미지 설정에 쓰이는 다른 메소드도 있다. setImageDrawable이 있는데, 이 경우 이미지의 크기를 화면에 맞게 줄이기 때문에 스크롤뷰에는 이미지의 원본 크기를 맞춰주는 getDrawable이 적합한 것이다.)
위에는 버튼을 누르면 한번만 바뀌길래 계속해서 바뀌도록 코드를 수정해보았다. (int image 추가)
public class MainActivity extends AppCompatActivity {
ScrollView scrollView;
ImageView imageView;
BitmapDrawable bitmap;
int image=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = findViewById(R.id.scrollView);
imageView=findViewById(R.id.imageView);
scrollView.setHorizontalScrollBarEnabled(true); // 수평 스크롤바 사용 기능 설정
Resources res = getResources();
bitmap=(BitmapDrawable) res.getDrawable(R.drawable.snow);
int bitmapWidth = bitmap.getIntrinsicWidth();
int bitmapHeight = bitmap.getIntrinsicHeight();
imageView.setImageDrawable(bitmap);
imageView.getLayoutParams().width = bitmapWidth;
imageView.getLayoutParams().height = bitmapHeight;
}
public void onButton1Clicked(View v){
changeImage();
}
private void changeImage(){
Resources res = getResources();
if(image==0){
bitmap = (BitmapDrawable) res.getDrawable(R.drawable.blue_snow);
image=1;
}
else{
bitmap = (BitmapDrawable) res.getDrawable(R.drawable.snow);
image=0;
}
int bitmapWidth = bitmap.getIntrinsicWidth();
int bitmapHeight = bitmap.getIntrinsicHeight();
imageView.setImageDrawable(bitmap);
imageView.getLayoutParams().width = bitmapWidth;
imageView.getLayoutParams().height = bitmapHeight;
}
}
'TIL > 안드로이드 스튜디오' 카테고리의 다른 글
3장 기본 위젯 (0) | 2024.11.20 |
---|---|
도전!4 - SMS 입력 화면 만들고 글자의 수 표시하기 (0) | 2024.11.20 |
도전!3 - 두 개의 이미지뷰에 이미지 번갈아 보여주기 (0) | 2024.11.18 |
1장 기초 맛보기 - Intent, Action, URI, 단축키, 뷰, 제약조건 ... (0) | 2024.11.11 |
오랜만에 다시 보는 안드로이드 스튜디오 (1) | 2024.11.07 |