카테고리 없음

72일차 공부 안드로이드 Overriding, Hierachy Event Model

이즈라핀 2020. 7. 17. 17:50

** Overriding

=> 상위 클래스에 존재하는 메소드를 하위 클래스에서 재정의 하는 것

=> 목적은 기능 확장

=> 추상 메소드를 재정의하는 것은 오버라이딩이 아니고 구현이라고 표현하는게 맞다.

 

=> 프레임워크가 제공하는 메소드를 오버라이딩 할 때는 상위 클래스의 메소드를 호출해야 한다.

=> 파괴하는 메소드를 제외하고는 상위 클래스의 메소드를 호출하고 필요한 기능을 추가한다.

 

** Hierachy Event Model

=> 제공되는 메소드를 재정의 하는 방식

=> 터치와 키보드 이벤트

=> View나 Activity를 상속받아서 사용해야 한다.

=> View클래스를 상속받아서 사용자 정의 뷰를 만들고 터치 이벤트를 처리

 

** 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"
    tools:context=".EventActivity"
    android:orientation="vertical">

    <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.java 파일에서 클릭이벤트 처리

 

package com.example.android0717;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

//Click 이벤트 처리를 위한 클래스
/*
class EventHandler implements View.OnClickListener{
    String msg;
    public void setMsg(String msg){
        this.msg = msg;
    }
    EventActivity eventActivity;
    //외부에서 문자열을 주입받아서 msg에 대입
    public EventHandler(
            EventActivity eventActivity,
            String msg){
        this.eventActivity = eventActivity;
        this.msg = msg;
    }

    public void onClick(View view){
        Toast.makeText(
                eventActivity,
                msg,
                Toast.LENGTH_SHORT)
                .show();
    }
}
*/

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개 이상의 객체로부터 발생한 이벤트를 하나의 이벤트 핸들러를 이용해서 처리

=> 이벤트 라우팅을 할려면 객체를 이벤트가 발생한 객체를 구분할 수 잇어야 한다.

안드로이드의 이벤트 처리 메소드들은 첫번째 매개변수가 이벤트가 발생한 객체이다.

이 매개변수를 이용해서 구분하면 된다.

 

package com.example.android0717;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

//Click 이벤트 처리를 위한 클래스
/*
class EventHandler implements View.OnClickListener{
    String msg;
    public void setMsg(String msg){
        this.msg = msg;
    }
    EventActivity eventActivity;
    //외부에서 문자열을 주입받아서 msg에 대입
    public EventHandler(
            EventActivity eventActivity,
            String msg){
        this.eventActivity = eventActivity;
        this.msg = msg;
    }

    public void onClick(View view){
        Toast.makeText(
                eventActivity,
                msg,
                Toast.LENGTH_SHORT)
                .show();
    }
}
*/

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);
        View.OnClickListener eventHandler =
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        switch (view.getId()){
                            case R.id.btn1:
                                Toast.makeText(EventActivity.this,
                                        "버튼 1 클릭",
                                        Toast.LENGTH_SHORT).show();
                                break;
                            case R.id.btn2:
                                Toast.makeText(EventActivity.this,
                                        "버튼 2 클릭",
                                        Toast.LENGTH_SHORT).show();
                                break;
                        }
                    }
                };
        Button btn1 = (Button)findViewById(R.id.btn1);
        Button btn2 = (Button)findViewById(R.id.btn2);
        //2개 버튼의 클릭 이벤트를 eventHandler 객체 1개가 처리
        //이런 형태를 이벤트 라우팅이라고 합니다.
        btn1.setOnClickListener(eventHandler);
        btn2.setOnClickListener(eventHandler);

    }
}

 

 

** 주기적인 화면 갱신

=> GUI 시스템에서는 화면 갱신을 Main Thread에서만 가능하다.

=> 화면을 갱신하는 작업은 모아서 한꺼번에 처리하고 가장 나중에 수행한다.

=> 주기적인 화면 갱신은 Handler를 이용하거나 Timer를 이용해야 한다.

 

1. 실행가능한 Activity를 1개 추가

 

2. 화면 디자인

=> 텍스트를 출력할 수 있는 TextView 1개와 Button 1개를 세로 방향으로 배치

 

3. 버튼을 누르면 1초마다 0 ~ 9 까지를 TextView에 출력하는 코드를 작성

 

package com.example.android0717;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TimerActivity extends AppCompatActivity {

    //클래스 안의 여러 메소드에서 사용하기 위해서 인스턴스 변수를 생성
    //이벤트 처리를 할 때 anonymous 나 람다를 이용하면
    //지역변수를 사용할 수 없기 때문에 인스턴스 변수로 선언하기도 합니다.
    Button btn;
    TextView disp;

    //Activity가 화면에 출력되기 전에 호출되는 메소드
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //레이아웃이나 뷰를 이용해서 Activity의 전체 화면을
        //설정
        setContentView(R.layout.activity_timer);

        //레이아웃 파일에 디자인 한 뷰 찾아오기
        btn = (Button)findViewById(R.id.btn);
        disp = (TextView)findViewById(R.id.disp);

        //버튼을 클릭했을 때 동작을 정의
        btn.setOnClickListener(
                new Button.OnClickListener(){
                    @Override
                    public void onClick(View view) {
                        try{
                            for(int i=0; i<10; i=i+1){
                                Thread.sleep(1000);
                                //disp.setText("i:" + i);
                                String msg = String.format("i:%d", i);
                                //로그 출력
                                Log.e("작업", msg);
                                disp.setText(msg);
                            }
                        }catch(Exception e){}
                        try{
                            for(int i=0; i<10; i=i+1){
                                Thread.sleep(1000);
                                //disp.setText("i:" + i);
                                String msg = String.format("i:%d", i);
                                //로그 출력
                                Log.e("작업", msg);
                                disp.setText(msg);
                            }
                        }catch(Exception e){}
                    }
                });
    }
}

 

 

 

=> 코드에 아무런 문제가 없고 정상적으로 수행되는데 하면 갱신만안됨

GUI 시스템에서는 주기적인 화면 갱신을 일반코드로는 할 수 없다.

화면 출력은 모아서 한꺼번에 가장 나중에 수행하기 때문이다.

 

** Timer

=> 일정한 주기를 가지고 작업을 수행하는 클래스 - 스레드로 구현된다.

=> 클래스는 CountDownTimer

=> onTick 이라는 메소드에 주기적으로 수행할 내용을 작성

=> 인스턴스를 생성할 때는 2개의 매개변수를 대입해서 생성하는데 첫번째 매개변수는 전체 수행할 시간이고 두번째 매개변수는 주기이다.

=> 타이머 시작은 start()로 호출하면 되고 중지는 cancel()이다.

 

클릭 메소드 수정

 

package com.example.android0717;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TimerActivity extends AppCompatActivity {

    //클래스 안의 여러 메소드에서 사용하기 위해서 인스턴스 변수를 생성
    //이벤트 처리를 할 때 anonymous 나 람다를 이용하면
    //지역변수를 사용할 수 없기 때문에 인스턴스 변수로 선언하기도 합니다.
    Button btn;
    TextView disp;

    //Activity가 화면에 출력되기 전에 호출되는 메소드
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //레이아웃이나 뷰를 이용해서 Activity의 전체 화면을
        //설정
        setContentView(R.layout.activity_timer);

        //레이아웃 파일에 디자인 한 뷰 찾아오기
        btn = (Button)findViewById(R.id.btn);
        disp = (TextView)findViewById(R.id.disp);

        //버튼을 클릭했을 때 동작을 정의
        btn.setOnClickListener(
                new Button.OnClickListener(){
                    @Override
                    public void onClick(View view) {
                        /*
                        try{
                            for(int i=0; i<10; i=i+1){
                                Thread.sleep(1000);
                                //disp.setText("i:" + i);
                                String msg = String.format("i:%d", i);
                                //로그 출력
                                Log.e("작업", msg);
                                disp.setText(msg);
                            }
                        }catch(Exception e){}

                         */

                        CountDownTimer timer =
                                new CountDownTimer(
                                        10000,
                                        1000) {
                                    int value = 0;
                                    @Override
                                    public void onTick(long l) {
                                        String msg = String.format("value:%d", value++);
                                        disp.setText(msg);
                                        //value = value + 1;
                                    }
                                    @Override
                                    public void onFinish() {

                                    }
                                };
                        timer.start();

                    }
                });
    }
}

 

 

** 타이머를 이용해 이미지 변경하기

1. 필요한 이미지를 drawable 디렉토리 안에 넣기

 

2. layout 파일에 ImageView 추가

 

<?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"
    tools:context=".TimerActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="출력 영역"
        android:id="@+id/disp"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="버튼"
        android:id="@+id/btn"/>
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/image1"
        android:id="@+id/imageview"/>

</LinearLayout>

 

3. onClick 메소드에 추가

 

package com.example.android0717;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class TimerActivity extends AppCompatActivity {

    //클래스 안의 여러 메소드에서 사용하기 위해서 인스턴스 변수를 생성
    //이벤트 처리를 할 때 anonymous 나 람다를 이용하면
    //지역변수를 사용할 수 없기 때문에 인스턴스 변수로 선언하기도 합니다.
    Button btn;
    TextView disp;

    //Activity가 화면에 출력되기 전에 호출되는 메소드
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //레이아웃이나 뷰를 이용해서 Activity의 전체 화면을
        //설정
        setContentView(R.layout.activity_timer);

        //레이아웃 파일에 디자인 한 뷰 찾아오기
        btn = (Button)findViewById(R.id.btn);
        disp = (TextView)findViewById(R.id.disp);

        //버튼을 클릭했을 때 동작을 정의
        btn.setOnClickListener(
                new Button.OnClickListener(){
                    @Override
                    public void onClick(View view) {
                        /*
                        try{
                            for(int i=0; i<10; i=i+1){
                                Thread.sleep(1000);
                                //disp.setText("i:" + i);
                                String msg = String.format("i:%d", i);
                                //로그 출력
                                Log.e("작업", msg);
                                disp.setText(msg);
                            }
                        }catch(Exception e){}
                         */

                        CountDownTimer timer =
                                new CountDownTimer(
                                        10000,
                                        1000) {
                                    int value = 0;
                                    @Override
                                    public void onTick(long l) {
                                        String msg = String.format("value:%d", value++);
                                        disp.setText(msg);
                                        //value = value + 1;
                                    }
                                    @Override
                                    public void onFinish() {

                                    }
                                };
                        timer.start();

                        //이미지 뷰 찾기
                        final ImageView imageView = (ImageView)findViewById(
                                        R.id.imageview);
                        //이미지 뷰에 출력할 리소스 배열
                        final int [] images = {
                                R.drawable.image1,
                                R.drawable.image2};

                        CountDownTimer t1 =
                                new CountDownTimer(
                                        100000,
                                        1000) {
                                    int idx = 0;
                                    @Override
                                    public void onTick(long l) {
                                        idx = idx + 1;
                                        imageView.setImageResource(images[idx % 2]);
                                    }

                                    @Override
                                    public void onFinish() {

                                    }
                                };
                        t1.start();
                    }
                });
    }
}

 

 

** 안드로이드의 리소스

=> 안드로이드는 자원을 res 데록토리에 저장

=> 실행을 할 때 자원을 전부 메모리에 로드해서 사용

=> raw 디렉토리에 저장된 데이터는 로드하지 않고 사용할 때 로드

=> 리소스 중에서도 크기가 큰 리소스는 res디렉토리에 저장하지 않고 assests 디렉토리에서 관리

 

1. drawable : 이미지, 이미지와 관련되 XML, 그림을 표현한 XML

2. layout : 화면 UI를 정의한 레이아웃 XML

3. value : 문자열, 색상, 크기, 배열 및 스타일 등의 XML

4. menu : 메뉴

5. xml

6. anim : 애니메이션 XML

7. mipmap : 앱의 아이콘

8. raw : 이진 파일 - html 이나 사운드 파일 등

 

=> 안드로이드는 리소스를 res 디렉토리에 저장을 하면 R.java 파일에 static final int 형태로 확장자를 제외하고 정수로 생성

자원별로 별도의 클래스를 이용해서 저장하기 때문에 image.thml, image.css 형태로 존재하면 에러가 발생하거나 처음 만든 것을 사용하지 못할 수 있다.

=> 리소스의 이름은 소문자와 숫자만으로 생성하는 것을 권장

 

** Animation

1. Twin Animation

=> 시작값과 종료값을 가지고 상태를 지정해서 수학적 계산에 의해서 애니메이션을 만들어내는 것

=> TranslateAnimation, ScaleAnimation, RotateAnimation, AlphaAnimation, AnimationSet을 이용해서 작성

=> 애니메이션 작성은 xml을 이용하는 경우가 많음

=> xml을 애니메이션으로 만들기

Animation 변수명 = AnimationUtils.loadAnimatoion(Context context, int resId);

뷰객체.startAnimation(변수명);

 

=> 애니메이션 관련 속성

=> duration, fillAfter(애니메이션 종료 후 마지막 상태 유지 여부 - 기본은 false), fillBefore(애니메이션 시작 할 떼 상태 - 기본은 true), repeatCount(0은 반복하지 않고 1은 2번, INFINITE 이면 무한대)

repeatMode(반복할 때의 동작으로 REVERSE를 설정하면 반대되는 애니메이션 재생)

startOffset(시작 전에 대기 시간)

Interpolator(애니메이션 진행 속도 변환)

detachWallpaper : 배경은 애니메이션되지 않도록 할 때 설정

zAdjustment : 뷰가 겹쳤을 때 Z - index

 

1) 출력할 이미지를 drawable 디렉토리에 복사

 

2) res 디렉토리에 애니메이션을 위한 anim 디렉토리를 생성

 

3) anim 디렉토리에 retate.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) 레이아웃을 수정

 

<?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"
    tools:context=".AnimationActivity"
    android:orientation="vertical">

    <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/image2"
        android:id="@+id/imageview"/>

</LinearLayout>

 

 

6) Activity.java 파일의 onCreate에 작성

 

package com.example.android0717;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;

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. 기타 리소스

1) values 디렉토리에 만드는 리소스

1) string.xml : 문자열 리소스

2) color.xml : 

3) style.xml : 스타일 리로스 - 글자모양 등

4) array.xml : 문자열 배열

5) dimens.xml : 크기

 

** 스마트폰 크기 호환성

=> 아이콘이나 이미지는 스마트 폰의 해상도에 따라 적절한 파일을 제공해주는 것이 필요

=> mipmap 이나 drawable 디렉토리를 만들 때 -mdpi, -hdpi, -xhdpi, -xxhdpi, -xxxhdpi 등을 추가해서 만들면 된다.

=> 지역 코드를 붙일 수 있다.

en(영어), en_US(미국에서 사용하는 영어)...

=> 방향을 지정할 수 있다.

port(수직), land(수평)

=> 스마트폰 크기 가져오기

DisplayMetrics ? = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(?);

?에 크기가 저장된다.

 

=> 단위

절대 단위 : 크기가 고정 - pt, px, mm, in

상대 단위 : 크기가 가변 - dp(dip), sp(sip)

인쇄를 할 때는 절대 단위를 사용하는 것이 좋고 화면 출력을 할 때는 상대 단위가 좋다.

 

1) string.xml 파일에 문자열을 정의

<resources>
    <string name="app_name">Android0717</string>
    <string name="btndisplay">Animation Start</string>
</resources>

 

2) res 디렉토리에 values-ko 디렉토리를 생성

 

3) values-ko 디렉토리에 string.xml 파일을 만들고 작성

<string name="btndisplay">애니메이션 시작</string>

 

4) layout 파일에서 버튼의 텍스트를 수정

 

<?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"
    tools:context=".AnimationActivity"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/btndisplay"
        android:id="@+id/animationbtn"/>
    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/image2"
        android:id="@+id/imageview"/>

</LinearLayout>

 

** 회전처리

=> 스마트폰은 가로보기와 세로보기 모드가 존재

=> 안드로이드는 단말의 방향이 변경되면 Activity를 메모리에서 제거한 수 해로 만든다.

=> Activity에서 회전을 지원하고자 하면 androidmanifest.xml 파일에서 activity를 등록할 때 android:configChanges = "orienatation|keyboardhiddenscreenSize" 옵션을 추가해 주어야 한다.

 

Android:screenOrientation="portrait 나 landscape"를 설정하면 고정된다.

 

=> 방향 전환이 발생하면 호출되는 메소드

Activity 클래스의 onConfigurationChanged(COnfiguration newConfig) 가 호출되고 매개변수의 orientation 속성을 조사하면 기기의 방향을 알 수 있다.

=> 방향에 따라 다른 레이아웃을출력하고자 하면 layout-land 디렉토리를 만들고 layout을 생성하면 된다.

이렇게 만들었을 때는 회전이 발생했을 때 setContextView메소드를 호출해 주어야 한다.

 

=> 이전 상태를 보관하고 다음에 실행했을 때 이전 상태를 가지고 실행하고자 하면 이 때는 inSaveInstanceState 메소드

 

회전이 발생하면 토스트를 출력

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 파일에 회전이 발생하면 호촐되는 메소드를 재정의

 

package com.example.android0717;

import androidx.appcompat.app.AppCompatActivity;

import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class AnimationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animation);
        if (savedInstanceState != null){
            Log.e("Date", savedInstanceState.getString("song"));
        }

        final ImageView imageView =
                (ImageView)findViewById(R.id.imageview);
        Button button =
                (Button)findViewById(R.id.animationbtn);

        button.setOnClickListener(new View.OnClickListener(){
            public void onClick(View view){
                Animation rotate =
                        AnimationUtils.loadAnimation(
                                getApplicationContext(),
                                R.anim.rotate);
                imageView.startAnimation(rotate);
                rotate.setAnimationListener(
                        new Animation.AnimationListener() {
                            @Override
                            public void onAnimationStart(Animation animation) {

                            }

                            @Override
                            public void onAnimationEnd(Animation animation) {
                                Toast.makeText(
                                        AnimationActivity.this,
                                        "애니메이션 종료",
                                        Toast.LENGTH_SHORT)
                                        .show();
                            }

                            @Override
                            public void onAnimationRepeat(Animation animation) {

                            }
                        });
            }
        });
    }

    //회전이 발생하면 호출되는 메소드
    @Override
    public void onConfigurationChanged(
            Configuration newConfig){
        setContentView(R.layout.activity_animation);
        super.onConfigurationChanged(newConfig);
    }
    @Override
    public void onSaveInstanceState(Bundle bundle){
        super.onSaveInstanceState(bundle);
        //어떤 데이터를 저장하면 onCreate에서 사용 가능
        bundle.putStringArray("song", "spice girls");
    }
}