과제
코드는 총 3개로 되어있다.
- 액티비티의 UI를 정의하는
activity_main.xml - 메뉴 아이템을 정의하는
menu1.xml - 액티비티의 동작을 제어하는
MainActivity.java
activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/baseLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/jeju2"/>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/edtInput"
android:layout_alignParentLeft="true"
android:text="각도 및 확대/축소 비율 입력"
android:textSize="20dp"/>
<EditText
android:id="@+id/edtInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/textView1"
android:text="0,1.0" />
</RelativeLayout>
코드 해석
RelativeLayout: 레이아웃의 최상위 뷰 그룹- 레이아웃의 속성으로는
android:id,android:layout_width,android:layout_height,android:orientation가 설정android:id는baseLayout으로 설정되어 있고,android:layout_width와android:layout_height는match_parent로 설정되어 레이아웃이 부모 컨테이너와 동일한 크기를 가짐레이아웃이 부모 컨테이너와 동일한 크기를 갖도록 하는데 부모 컨테이너란 무엇일까?
여기서 “부모 컨테이너”는 현재 레이아웃이 포함된 상위 레이아웃을 가리킨다.
일반적으로 액티비티의 루트 레이아웃이 부모 컨테이너가 돤다.
액티비티의 루트 레이아웃은 액티비티의 XML 레이아웃 파일에서 최상위에 정의된 레이아웃이다.
위의 코드에서
android:layout_height="match_parent"는<RelativeLayout>이 포함된 부모 컨테이너(일반적으로 액티비티)의 세로 크기와 동일하게 설정되어 레이아웃이 채워지도록 한다. android:orientation은 수직 방향(vertical)으로 설정
- 레이아웃의 속성으로는
ImageView: 이미지를 표시하는 뷰- 이미지의 속성으로는
android:id,android:layout_width,android:layout_height,android:layout_centerHorizontal,android:layout_centerVertical,android:src가 설정됨 android:id는imageView1으로 설정되어 있고,android:layout_width와android:layout_height는wrap_content로 설정되어 이미지의 원본 크기에 맞게 크기가 조정android:layout_centerHorizontal과android:layout_centerVertical은 이미지를 수평과 수직으로 중앙에 정렬android:src는@drawable/jeju14로 설정되어 해당 이미지를 표시
- 이미지의 속성으로는
TextView: 텍스트를 표시하는 뷰- 텍스트의 속성으로는
android:id,android:layout_width,android:layout_height,android:layout_alignBottom,android:layout_alignParentLeft,android:text,android:textSize가 설정됨 android:id는textView1으로 설정되어 있고,android:layout_width와android:layout_height는wrap_content로 설정되어 텍스트의 내용에 맞게 크기가 조정android:layout_alignBottom은edtInput과 하단을 맞춰줌android:layout_alignParentLeft는 부모 레이아웃의 왼쪽에 정렬android:text는 “각도 및 확대/축소 비율 입력”으로 텍스트를 표시android:textSize는20dp로 텍스트의 크기를 조정
- 텍스트의 속성으로는
EditText: 사용자 입력을 받는 텍스트 입력란이 됨- 에디트 텍스트의 속성으로는
android:id,android:layout_width,android:layout_height,android:layout_alignParentTop,android:layout_toRightOf,android:text가 설정 android:id는edtInput으로 설정되어 있고,android:layout_width는match_parent,android:layout_height는match_parent와wrap_content로 설정layout_alignParentTop는 true로 설정되어EditText가 상단에 위치layout_toRightOf는 현재 뷰를 다른 뷰의 오른쪽에 배치하는 시켜줌@+id/textView1은 다른 뷰의 ID를 참조하며, 현재 뷰를textView1뷰의 오른쪽에 배치하도록 지정android:text="0, 1.0"으로 인해 입력 초기값은 “0,1.0”으로 설정
- 에디트 텍스트의 속성으로는
실행 화면
menu1.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/itemRotate"
android:title="그림 회전">
</item>
<item android:id="@+id/itemZoom"
android:title="그림 확대">
</item>
<item android:id="@+id/itemShrink"
android:title="그림 축소">
</item>
<group android:checkableBehavior="single" >
<item
android:id="@+id/item1"
android:checked="true"
android:title="한라산">
</item>
<item
android:id="@+id/item2"
android:title="추자도">
</item>
<item
android:id="@+id/item3"
android:title="범섬">
</item>
</group>
</menu>
코드 해석
onCreate()메서드: 액티비티가 생성될 때 호출되는 메서드setContentView(R.layout.activity_main): 액티비티의 레이아웃을 설정한다.activity_main.xml파일의 내용이 화면에 표시됨setTitle("제주도 풍경"): 액티비티의 타이틀을 “제주도 풍경”으로 설정findViewById(R.id.edtInput): XML에서 정의한edtInputID를 가진EditText뷰를 찾아줌edtInput.setText("0,1.0"):edtInput의 텍스트를 “0,1.0”으로 설정findViewById(R.id.imageView1): XML에서 정의한imageView1ID를 가진ImageView뷰를 찾아줌
onCreateOptionsMenu()메서드: 옵션 메뉴를 생성하는 메서드getMenuInflater().inflate(R.menu.menu1, menu):menu1.xml파일을 인플레이트하여 메뉴를 생성
onOptionsItemSelected()메서드: 옵션 메뉴 아이템을 선택했을 때 호출되는 메서드item.getItemId(): 선택된 메뉴 아이템의 ID를 가져옴R.id.itemRotate: “itemRotate” 메뉴 아이템을 선택한 경우edtInput.getText().toString().split(",")[0]:edtInput의 텍스트를 가져와서 “,”로 분리한 후 첫 번째 값을 가져옴imageView1.setRotation(angle):imageView1의 회전을angle값으로 설정
R.id.itemZoom: “itemZoom” 메뉴 아이템을 선택한 경우edtInput.getText().toString().split(",")[1]:edtInput의 텍스트를 가져와서 “,”로 분리한 후 두 번째 값을 가져옴checkScaleBounds(scaleValue):scaleValue값이 화면 스케일 범위 내에 있는지 확인imageView1.setScaleX(scaleValue):imageView1의 X 축 스케일을scaleValue로 설정imageView1.setScaleY(scaleValue):imageView1의 Y 축 스케일을scaleValue로 설정
R.id.itemShrink: “itemShrink” 메뉴 아이템을 선택한 경우shrinkValue:edtInput의 텍스트를 가져와서 “,”로 분리한 후 두 번째 값을 가져옵니다. 이 값을 절반으로 조정checkScaleBounds(scaleValue):scaleValue값이 화면 스케일 범위 내에 있는지 확인
R.id.item1: “item1” 메뉴 아이템을 선택한 경우imageView1.setImageResource(R.drawable.jeju2):imageView1의 이미지를jeju2로 설정
R.id.item2: “item2” 메뉴 아이템을 선택한 경우imageView1.setImageResource(R.drawable.jeju14):imageView1의 이미지를jeju14로 설정
R.id.item3: “item3” 메뉴 아이템을 선택한 경우imageView1.setImageResource(R.drawable.jeju6):imageView1의 이미지를jeju6으로 설정
- 기타: 선택한 메뉴 아이템이 없는 경우, 부모 클래스인
super.onOptionsItemSelected(item)을 호출
checkScaleBounds()메서드: 화면 스케일 범위를 확인하는 메서드imageView1.getWidth():imageView1의 너비를 가져옴imageView1.getHeight():imageView1의 높이를 가져옴imageView1.getDrawable().getIntrinsicWidth():imageView1에 설정된 이미지의 원본 너비를 가져옴imageView1.getDrawable().getIntrinsicHeight():imageView1에 설정된 이미지의 원본 높이를 가져옴maxScaleX: 뷰의 너비와 이미지의 너비를 비교하여 X 축 스케일의 최대값을 계산maxScaleY: 뷰의 높이와 이미지의 높이를 비교하여 Y 축 스케일의 최대값을 계산return scaleValue <= maxScaleX && scaleValue <= maxScaleY: 스케일 값이 X 축과 Y 축의 최대값보다 작거나 같으면true를 반환하고, 그렇지 않으면false를 반환
실행 화면
범선으로 그림을 변경한 모습
MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package com.cookandroid.project7_1;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
EditText edtInput;
ImageView imageView1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("제주도 풍경");
edtInput = findViewById(R.id.edtInput);
edtInput.setText("0,1.0"); // 입력 초기값 설정
imageView1 = findViewById(R.id.imageView1);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater mInflater = getMenuInflater();
mInflater.inflate(R.menu.menu1, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.itemRotate:
float angle = Float.parseFloat(edtInput.getText().toString().split(",")[0]);
imageView1.setRotation(angle);
return true;
case R.id.itemZoom:
float scaleValue = Float.parseFloat(edtInput.getText().toString().split(",")[1]);
if (checkScaleBounds(scaleValue)) {
imageView1.setScaleX(scaleValue);
imageView1.setScaleY(scaleValue);
} else {
Toast.makeText(this, "화면보다 확대를 크게 할 수 없습니다.", Toast.LENGTH_SHORT).show();
}
return true;
case R.id.itemShrink:
float shrinkValue = Float.parseFloat(edtInput.getText().toString().split(",")[1]) / 2;
if (checkScaleBounds(shrinkValue)) {
imageView1.setScaleX(shrinkValue);
imageView1.setScaleY(shrinkValue);
} else {
Toast.makeText(this, "화면보다 축소를 작게 할 수 없습니다.", Toast.LENGTH_SHORT).show();
}
return true;
case R.id.item1:
imageView1.setImageResource(R.drawable.jeju2);
return true;
case R.id.item2:
imageView1.setImageResource(R.drawable.jeju14);
return true;
case R.id.item3:
imageView1.setImageResource(R.drawable.jeju6);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private boolean checkScaleBounds(float scaleValue) {
int viewWidth = imageView1.getWidth();
int viewHeight = imageView1.getHeight();
int imageWidth = imageView1.getDrawable().getIntrinsicWidth();
int imageHeight = imageView1.getDrawable().getIntrinsicHeight();
float maxScaleX = (float) viewWidth / imageWidth;
float maxScaleY = (float) viewHeight / imageHeight;
return scaleValue <= maxScaleX && scaleValue <= maxScaleY;
}
}
코드 해석
onCreate()메서드- 액티비티가 생성될 때 호출되는 메서드
setContentView(R.layout.activity_main): activity_main.xml 레이아웃을 액티비티에 설정setTitle("제주도 풍경"): 액티비티의 타이틀을 “제주도 풍경”으로 설정findViewById(R.id.edtInput): edtInput EditText를 찾아 변수에 할당edtInput.setText("0,1.0"): edtInput EditText의 텍스트를 “0,1.0”으로 설정findViewById(R.id.imageView1): imageView1 ImageView를 찾아 변수에 할당
onCreateOptionsMenu()메서드- 옵션 메뉴를 생성하기 위해 호출되는 메서드
getMenuInflater().inflate(R.menu.menu1, menu): menu1.xml 파일을 가져와서 메뉴를 생성
onOptionsItemSelected()메서드- 옵션 메뉴에서 선택한 아이템에 대한 동작을 처리하기 위해 호출되는 메서드
item.getItemId()를 사용하여 선택한 아이템의 ID를 확인- 선택한 아이템에 따라 다음 동작을 수행
- “itemRotate”:
edtInput의 텍스트를 가져와서 “,”로 분리한 후 첫 번째 값을 회전 각도로 설정 - “itemZoom”:
edtInput의 텍스트를 가져와서 “,”로 분리한 후 두 번째 값을 확대/축소 비율로 설정 설정한 값이 화면 스케일 범위 내에 있는지 확인하고, 그에 따라 이미지의 X 및 Y 축 스케일을 설정 - “itemShrink”:
edtInput의 텍스트를 가져와서 “,”로 분리한 후 두 번째 값을 절반으로 조정하여 축소 비율로 설정 설정한 값이 화면 스케일 범위 내에 있는지 확인하고, 그에 따라 이미지의 X 및 Y 축 스케일을 설정 - “item1”, “item2”, “item3”: 각각의 아이템에 대해
imageView1의 이미지를 변경
- “itemRotate”:
- 선택한 아이템에 대한 동작을 수행한 후
true를 반환
checkScaleBounds()메서드- 주어진 스케일 값이 화면 스케일 범위 내에 있는지 확인하는 메서드
imageView1.getWidth()및imageView1.getHeight():imageView1의 너비와 높이를 가져옴imageView1.getDrawable().getIntrinsicWidth()및imageView1.getDrawable().getIntrinsicHeight():imageView1에 설정된 Drawable의 원본 너비와 높이를 가져옴maxScaleX와maxScaleY: 이미지 뷰의 너비와 높이를 기준으로 최대 스케일 값을 계산합니다. 이미지가 화면에 맞게 스케일되지 않도록 최대 스케일 값을 제한scaleValue와shrinkValue가 최대 스케일 값을 초과하지 않으면true를 반환하고, 그렇지 않으면false를 반환
실행 화면
45도 회전한 모습
화면보다 그림이 크게 확대되어 화면 밖으로 짤릴경우 경고가 토스트로 출력되는 모습
그림을 축소한 모습
그림을 다시 확대한 모습
그림을 회전과 축소를 같이 한 모습
댓글남기기