**Hierachy Event Model
=> 제공되는 메소드를 재정의 하는 방식
=> 터치나 키보드 이벤트
=> View, Activity를 상속받아 사용
=> View 클래스를 상속받아서 사용자 정의 뷰를 만들고 터치 이벤트 처리
**Overriding
=> 상위 클래스에 존재하는 메소드를 하위 클래스에서 재정의 하는 것
=> 목적은 기능 확장
=> 추상 메소드를 재정의하는 것은 오버라이딩이 아니고 구현
=> 프레임워크가 제공하는 메소드를 오버라이딩 하는 경우 상위 클래스 메소드를 호출해야 함
=> 파괴하는 메소드를 제외하고는 상위 클래스의 메소드를 호출하고 필요 기능을 추가
**Delegation Model
=> 이벤트 처리를 다른 객체에게 위임하는 방식
=> 상속을 받아 메소드를 재정의 하는 방식은 자주 사용하는 이벤트의 경우 효율적이나 자주 사용하지 않으면 자원 낭비
=> Delegation Model의 이벤트 처리 메소드는 첫번째 매개변수를 이용하여 이벤트가 발생한 객체를 확인 가능
1. 리스너
- OnTouchListener
- OnClickListener
- OnKeyListener
- OnLongClickListener
- OnFocusChangeListener
=> 리스너들은 뷰의 내부 인터페이스로 만들어져 있음
=> 대부분 메소드를 1개만 소유하고 있어 람다로 작성 가능
2. 이벤트 처리 방법
=> 이벤트를 처리할 객체에서 .set리스너(리스너 객체)를 호출해서 이벤트 처리를 위임
3. 리스너 객체 생성
1) 외부에 인터페이스를 구현한 클래스 생성
=> 이벤트처리하는 클래스를 외부에 별도로 생성하는 것이 권장되지만, 데이터 교환이 어려움
2) 내부에 인터페이스를 구현한 클래스 생성
=> 내부에 클래스를 만드므로 데이터 교환이 쉬움
=> 별도의 클래스를 만들기 때문에 anonymous나 람다보다 무거워질 가능성이 높음
3) anonymous나 람다를 이용하여 생성
=> 코드는 간결해지나 이벤트 처리를 많이 하게 되면 가독성이 떨어짐
4.View.OnClickListener
=> 클릭했을 때 이벤트 처리를 위한 리스너 인터페이스
=> 처리해야 할 메소드는 public void onClick(View view)
1) 실행가능한 Activity추가
2) 레이아웃 파일에 화면 디자인
=> 2개의 버튼 배치
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".EventActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn1"
android:text="버튼 1"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn2"
android:text="버튼 2"/>
</LinearLayout>
3) Activity에서 클릭 이벤트 처리
public class EventActivity extends AppCompatActivity {
String msg = "메시지";
class EventHandler implements View.OnClickListener{
public void onClick(View view){
Toast.makeText(
EventActivity.this,
msg,
Toast.LENGTH_SHORT)
.show();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
Button btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener(){
public void onClick(View view){
Toast.makeText(
EventActivity.this,
msg,
Toast.LENGTH_SHORT)
.show();
}
});
}
}
**이벤트 라우팅
=> 2개 이상의 객체로 부터 발생한 이벤트를 하나의 이벤트 핸들러를 이용하여 처리
=> 이벤트 라우팅을 하려면 이벤트 발생 객체를 구분할 수 있어야 함
- 안드로이드의 이벤트 처리 메소드들은 첫번째 매개변수가 이벤트가 발생한 객체
- 이 매개변수를 이용하여 구분하면 됨
**주기적인 화면 갱신
=> GUI 시스템에서는 화면 갱신을 Main Thread에서만 처리 가능
=> 화면 갱신 작업은 모아서 한꺼번에 처리하고 가장 나중에 수행
=> 주기적인 화면 갱신은 Handler를 이용하거나 Timer를 이용해야 함
1. 실행가능한 Activity 1개 추가
2. 화면 디자인
=> 텍스트를 출력할 수 있는 TextView 1개와 Button 1개를 세로방향으로 배치
3. 버튼을 누르면 1초다마 0~9까지 TextView에 출력하는 코드를 작성
=> Timer에 작성
1) 인스턴스 변수 선언
//클래스 안의 여러 메소드에서 사용하기 위해서 인스턴스 변수를 생성
//이벤트 처리를 할 때 anonymous 나 람다를 이용하면
//지역변수를 사용할 수 없기 때문에 인스턴스 변수로 선언하기도 합니다.
Button btn;
TextView disp;
2) onCreate 메소드에 뷰를 찾아오고 이벤트를 처리하는 코드를 추가
//버튼을 클릭했을 때 동작을 정의
btn.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View view) {
try{
for(int i=0; i<10; i+=1){
Thread.sleep(1000);
String msg = String.format("i : %d", i);
//로그 출력
Log.e("작업내역 : ", msg);
disp.setText(msg);
}
}catch (Exception e){ }
}
});
=> 코드는 아무런 문제가 없고 정상적으로 수행되나 화면 갱신만 안됨
- GUI 시스템 에서는 주기적인 화면 갱신을 일반코드로는 불가능
- 화면 출력은 모아서 한꺼번에 가장 나중에 수행하기 때문
**Timer
=> 일정한 주기를 가지고 작업을 수행하는 클래스 - 스레드로 구현
=> 클래스는 CountDownTimer
=> onTick이라는 메소드에 주기적으로 수행할 내용을 작성
=> 인스턴스를 생성할 때는 2개의 매개변수를 대입하여 생성, 첫번째 매개변수는 전체 수행시간, 두번째 매개변수는 주기
=> 타이머 시작은 start()를 호출하면 되고 중지는 cancel()
=> 클릭 메소드 수정
@Override
public void onClick(View view) {
CountDownTimer timer = new CountDownTimer(100000, 1000) {
int value = 0;
@Override
public void onTick(long l) {
String msg = String.format("value : %d", value++);
disp.setText(msg);
}
@Override
public void onFinish() {
}
};
timer.start();
**Timer를 이용해 이미지 변경
1. 필요한 이미지를 drawable 디렉토리에 복사
=> image1.jpg, image2.jpg
**안드로이드의 리소스
=> 안드로이드는 자원을 res 디렉토리에 저장
=> 실행시 자원을 전부 메모리에 로드하여 사용
=> raw 디렉토리에 저장된 데이터는 로드하지 않고 사용할 때 로드
=> 리소스 중에서도 크기가 큰 리소스는 res 디렉토리에 저장하지 않고 assets디렉토리에서 관리
1. drawable : 이미지, 이미지와 관련된 XML, 그림을 표현한 XML
2. layout : 화면 UI를 정의한 레이아웃 XML
3. values : 문자열, 색상, 크기, 배열 및 스타일등의 XML
4. menu : 메뉴
5. xml
6. anim : 애니메이션 XML
7. mipmap : 앱의 아이콘
8. raw : 이진파일 - html이나 사운드 파일
=> 안드로이드는 리소스를 res 디렉토리에 저장하면 R.java 파일에 static final int 형태로 확장자 없이 정수로 생성
- 종류가 다르더라도 이름이 같으면 문제가 발생할 소지가 있음
- 자원별로 클래스를 제작, 저장하므로 종류가 다르면 상관없으나 raw의 경우 한 클래스를 사용하므로, 확장자만 다를경우 에러 발생
=> 리소스명은 소문자와 숫자만으로 생성하는 것을 권장
**Animation
1. Twin Animation
=> 시작값과 종료값을 가지고 상태를 지정하여 수학적 계산의 의해 애니메이션을 만들어 내는 것
=> TranslateAnimation, ScaleAnimation, RotateAnimation, AlphaAnimation, AnimationSet을 이용하여 작성
=> 애니메이션 작성은 xml을 이용하는 경우가 많음
=> xml을 애니메이션으로 만들기
- Animation 변수명 = AnimationUtils.loadAnimation(Context context, int resId);
뷰 객체.startAnimation(변수명)
=> 애니메이션 관련 속성
- duration, fillAfter(애니메이션 종료후 마지막 상태 유지 여부 - 기본은 false)
- fillBefore(애니메이션 시작시 상태 - 기본은 true)
- repeatCount(0은 반복X, 1 -> 2, INFINITY -> 무한대)
- repeatMode(반복시의 동작으로 REVERSE를 설정시 반대되는 애니메이션 재생)
- startOffset(시작전에 대기시간)
- interpolator(애니메이션 진행 속도 변환)
- detachWallpaper : 배경은 애니메이션 되지 않도록 설정
- zAdjustment : 뷰가 겹쳤을 때 Z-index
1) 출력할 이미지를 drawable 디렉토리에 복사
2) res 디렉토리에 애니메이션을 위한 anim 디렉토리를 생성
3) anim 디렉토리에 rotate.xml 파일을 생성하고 회전 애니메이션 작성
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000"/>
4) 실행가능한 Activity 생성(AnimationActivity)
5) 레이아웃 수정
=> 버튼 1개, 이미지뷰 1개 작성
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".AnimationActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="애니메이션 시작"
android:id="@+id/animationbtn"/>
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:src="@drawable/image1"
android:id="@+id/imageview"/>
</LinearLayout>
6) Activity.java 파일의 onCreate에 작성
public class AnimationActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation);
final ImageView imageView = (ImageView)findViewById(R.id.imageview);
Button button = (Button)findViewById(R.id.animationbtn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Animation rotate = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate);
imageView.startAnimation(rotate);
}
});
}
}
2. AnimationListener
=> Animation도 화면 변경하는 작업이므로 애니메이션 종료후, 어떤 동작 을 수행시키려면 리스너의 콜백 메소드를 이용해야 함
=> 애니메이션 시작 전, 종료 후, 반복될 때 호출 되는 메소드를 소유
=> 애니메이션 객체.setAnimationListener(AnimationListener listener);
3. 기타 리소스
=> values 디렉토리에 만드는 리소스
1) strings.xml : 문자열 리소스
2) colors.xml
3) style.xml : 스타일 리소스 - 글자모양 등
4) arrays.xml : 문자열 배열
5) dimens.xml : 크기
**스마트폰 크기 호환성
=> 아이콘이나 이미지는 스마트 폰의 해상도에 따라 적절한 파일을 제공해주는 것이 필요
=> minmap이나 drawable 디렉토리를 만들 때 -mdpi, -hdpi, -xdpi, -xxdpi, -xxxdpi등을 추가하여 만들면 됨
=> 지역 코드를 붙일 수 있음
- en(영어), en_US(미국에서 사용하는 영어)..
=> 방향을 지정할 수 있음
- port(수직), land(수평)
=> 스마트폰 크기 가져오기
- DisplayMetrics ? = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(?);
- ?에 크기가 저장됨
=> 단위
- 절대 단위 : 크기가 고정 - pt, px, mm, in
- 상대 단위 : 크기가 가변 - dp(dip), sp(sip)
- 인쇄시에는 절대단위를 사용하는 것이 좋고, 화면 출력시는 상대 단위가 좋음
1)Strings.xml 파일에 문자열을 정의
<string name="btndisplay">Animation Start</string>
2) res 디렉토리에 values-ko 디렉토리를 생성
3) values-ko 디렉토리에 strings.xml파일을 만들고 작성
<string name="btndisplay">애니메이션 시작</string>
4) 레이아웃 파일에서 버튼의 텍스트를 수정
android:text="@string/btndisplay"
**회전 처리
=> 스마트 폰은 가로보기와 세로보기 모드가 존재
=> 안드로이드는 단말의 방향이 변경되면 Activity를 메모리에서 제거후 새로 제작
=> Activity에서 회전을 지원하고자하면 androidmanifest.xml파일에서 Activity를 등록 시 옵션 추가
(android:configChanges = "orientationkeyboardHidden|screenSize" 추가)
- Android:screenOrientation="portrait 나 landscape"를 설정하면 고정
=> 발향 전환이 발생하면 호출되는 메소드
- Activity 클래스의 onConfigurationChanged(Configuration newConfig) 호출후 매개변수의 orientation 속성 확인
(기기 방향을 알수 있음)
=> 방향에 따라 다른 레이아웃을 출력하고자 하면 layout-land 디렉토리를 만들고 layout을 생성하면 됨
- 위처럼 제작하면 회전 발생시 setContentView 메소드를 호출해 주어야 함
=> 이전 상태를 보관하고 차후 실행시 이전의 상태를 보존하고자하면, onSaveInstanceState 메소드를 재정의 하여 상태를 저장
- onCreate에서 이전 상태를 복원 해줌
1. 회전이 발생시 토스트 출력
1) androidmanifest.xml 파일 수정
<activity android:name=".AnimationActivity"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2. AnimationActivity.java 파일에 회전이 발생하면 호출되는 메소드를 재정의
'수업 정리' 카테고리의 다른 글
74일차 수업 정리(Android - Thread) (0) | 2020.07.21 |
---|---|
73일차 수업 정리(Android - 파일 입출력, SQLite) (0) | 2020.07.20 |
71일차 수업정리(Android - Toast, Dialog, EventHandling) (0) | 2020.07.16 |
70일차 수업정리(Android Layout) (0) | 2020.07.15 |
69일차 수업정리(Lambda, Android Interface) (0) | 2020.07.14 |