System.out.println("Hello, World");

레이아웃을 통해 버튼을 만들어주고 

menu.xml을 이용하여 각각 메뉴버튼을 만들어주고 라디오버튼과 체크박스를 만들어준다. 

라디오 버튼은 그룹으로 묶어서 한 항목이 선택되었을떄 다른 항목을 선택할 경우 그 항목만 체크된다. 

체크박스는 체크했을경우와 체크안했을경우가 나타난다.






위와 같은 소스로 실행하게 되면 


   


   



위와 같이 실행된다. 



Posted by 김마농



화면에 짜장, 짬뽕, 기타 메뉴를 만들어준다. 

짜장과 짬뽕을 선택하면 토스트 메시지로 저장해둔 메시지가 출력되고, 기타를 선택하면 다른 팝업창이 출력되어 우동과 만두를 선택하라고 한다. 

그 항목중 한개를 선택하면 메시지가 토스트된다.






메뉴를 XML로 만들어서도 사용할 수 있다.

XML로 메뉴를 만들면 개발과정도 편리할 뿐만 아니라 국제화에도 유리하므로 이후 메뉴를 디자인할때는

가급적이면 XML로 정의하는 것이 유리하다.






Posted by 김마농

타이머 처리를 위해 Handler 클래스를 사용한다. 핸들러는 스레드간의 메시지 통신을 위한 장치로서 sendMessage 메서드나 유사 메서드로 특정 핸들러에게 메시지를 보낼수 있다. 핸들러는 스레드의 경계를 넘어설수 있는 범용적인 통신 장치이며 제대로 사용할려면 꽤 많은 것을 알아야 하지만 한 스레드내에서 간단하게 타이머로도 쓸수 있다.


mHandler가 핸들러이며 handleMessage에서 value값을 1 증가 시켜 텍스트뷰로 호출한다. sendEmptyMessageDelayed 메서드로 1초간의 지연시간을 두어 1초후에 호출되도록 한다.



다음은 핸들러가 하는 일이 복잡하지 않고 코드가 단순하다면 굳이 외부에 둘 필요 없이 onCreate 메서드 안에서 지역적으로 초기화 시키는 것도 가능하다. 이벤트 리스너를 onCreate에서 생성 및 초기화하는 것과 마찬가지이다.



핸들러 초기화문이 onCreate에 작성되어 있으며 최초 빈 메시지를 보내는 문장과 나란히 둘수 있어 좀더 간단해보인다. 

핸들러가 자신을 재귀호출하면 무한히 반복되지만 일정 조건이 만족되면 재호출을 중지 할 수도 있다.


핸들러로도 타이머 흉내를 낼 수 있지만 익숙해지면 오히여 융통성이 있다. 중간에 타이머를 멈추거나 주기를 바꾸는 것도 가능하지만 스레드 간의 통신을 위해 제공되는 클래스라 원래의 용도와는 조금 맞지 않는 면이 있기 때문에 CountDownTimer 클래스를 활용하는 것이다.




위의 소스는 객체를 생성하자마자 시작하며 10초동안 1초 간격으로 나누어 작업한다. 

value가 5가 되면 cancel이 되도록 명령을 했지만 무슨 이유인지 작동안하고 10초까지 카운트한다. 




Posted by 김마농

버튼은 클릭이외에도 롱클릭이라는 이벤트를 받는다. 롱클릭은 버튼을 일정한 시간동안 계속 누르고 있는 동작이며 터치를 떼지 않고 계속 누르고 있으면 롱클릭 이벤트가 발생한다. 

다음은 버튼과 롱클릭 버튼을 2개 모두 활용한 모습이다. 

XML에서 각각 버튼에 mOnClick이라는 OnClick을 주었고, 이 버튼을 찾아서 setonLongListener를 해준다.



Posted by 김마농

보통 버튼에 리스너를 추가하여 작업하지만 소스가 지저분해진다. 

하지만 버튼에 클릭했을때 어떤 동작을 수행할지 추가해주면 소스도 깨끗해지고 간편해진다.




하지만 속성을 통한 핸들러 연결은 클릭 이벤트에 대해서만 예외적으로만 적용되는 것이므로 다른 이벤트에는 사용할 수 없다.

 또 SDK1.6버전에서 추가된 기능이라 다른 버전에서는 실행되지 않을 수 있다.

Posted by 김마농


버튼 2개를 통해 Text뷰를 찾아가서 문자열을 변경한다. 


비슷한 코드가 반복되면 통합하는것이 리팩토링의 기초이다. 다행히 안드로이드는 하나의 리스너를 여러 뷰에 대해 등록하는 것을 허용한다.

한 객체를 두 번 사용하려면 이름이 필수적이므로 익명 클래스의 임시 객체를 생성하는 방법은 쓸 수 없다.



핸들러가 하나로 통합되었다는 면에서는 바람직하지만 액티비티를 리스너로 사용한다는 점은 다소 부담스럽다. 최상위의 액티비티는 그대로 두고 

별도의 리스너 객체를 멤버로 선언한후 이 멤버를 리스너로 사용하는 것이 좀 더 깔끔하다. 






Posted by 김마농


키 액션을 통해 mX, mY의 값에 변화를 주어 원이 이동시키게끔 만들어준다. 



Posted by 김마농


처음 누를때, 누른 상태로 이동할 때, 떨어질 떄 각각 다른 이벤트가 발생한다. 현재 화면좌표는 MotionEvent의 getX, getY메서드로 조사한다. 

곡선을 구성하는 점의 개수는 제한이 없으므로 고정 크기의 배열을 사용해서는 안되며 반드시 가변 크기를 지원하는 컬렉션을 사용해야 한다. 

추가만 되고, 중간에 삽입, 삭제할 일을 없으므로 배열형식의 ArrayList가 적합하다. 

Posted by 김마농

가장 중요한거부터 언급

- 리스너로 전달할 지역 변수는 final로 선언한다.




 텍스트뷰 객체를 mText 멤버로 선언하고 onCreate에서 딱 한번만 조사한다. onTouch에서는 텍스트 뷰를 따로 구할 필요 없이 mText 멤버를 참조하면 된다. 메서드로 뭔가 전달할 것이 있으면 인수를 사용하는 것이 문법적인 정석이다. 그러나 이벤트 핸들러의 경우 인터페이스에 의해 원형이 고정되어 있으므로 인수를 더 추가할 방법이 없다. 그래서 어떡하든 핸들러내에서 참조할 수 있는 형태로 전달해야 하는 것이다.


이 방법도 문제가 있는데 리스너가 아주 많을 경우 각 리스너로 전달할 변수를 일일히 클래스의 멤버로 선언하자면 외부 클래스가 너무 뚱뚱해진다는 것이다. 멤버란 클래스의 상태를 저장하는 변수이지 정보 전달용이 아니다. 외부 클래스를 날씬하게 유지하려면 특정 리스너로 전달할 값은 메서드의 지역 변수로 선언해야 한다. 이런 경우는 코드가 조금 더 복잡해진다. 



onTouch가 호출되었을때는 outText 변수가 존재하지 않으므로 outText의 실제값을 참조할 수 없다. 미래에 호출될 리스너에게 현재의 지역 변수값을 전달하는 것은 불가능하다. 

이에 비해 지역 변수에 final을 붙이면 더 이상 변경할 수 없는 상수가 되므로 onTouch를 등록하는 시점에 그 값을 분명히 전달 할 수 있다. 

onTouch 메서드에서 참조하는 outText는 리스너가 등록될 시점의 값을 가지는 상수객체이다. outText변수와 onTouch 리스너는 생성 시점과 등록 시점이 같지만 존재 기간은 서로 다르다. outText는 일개 지역 변수이지만 onTouch는 리스너로 등록되므로 사실상 전역적으로 지속된다.




Posted by 김마농

1. 콜백 메서드 정의하기 

- 이벤트를 받는 가장 쉬운 방법은 해당 클래스를 상속받아 콜백 메서드를 재정의하는 것이다. 콜백은 특정 이벤트가 발생했을때 시스템에 의해 자동으로 호출되는 메서드이며 이 메서드에 코드를 작성해 놓으면 이벤트 발생시의 동작을 정의 할 수 있다.

사용자와 상호 작용하는 주체가 뷰이므로 이벤트 콜백은 주로 뷰가 제공한다. 



2. 리스너 인터페이스 구현

- 이벤트 리스너는 통상 특정 뷰에 대해 정의되는 것이므로 외부에 선언할 필요 없이 액티비티 클래스 내부에 이너클래스로 선언한다. 

액티비티는 리스너 타입의 객체 TouchListener를 멤버로 선언 및 생성하고 뷰는 setOnTouchListener 메서드로 리스너 객체를 터치 이벤트와 연결했다.



리스너로 이벤트를 처리하는 절차를 간략하게 요약하면 다음과 같다.

 1) 리스너를 상속받는 클래스를 선언하고 추상 메서드를 구현한다.

 2) 리스너 객체 TouchListener를 선언 및 생성한다.

 3) 준비된 리스너 객체를 뷰의 이벤트와 연결한다.



3. 액비티비가 리스너 구현

- 안드로이드 프로젝트에는 최소한 액티비티 하나는 존재하므로 액티비티가 리스너 인터페이스를 구현하는 것도 물론 가능하다. 액비티비는 Activity 클래스를 이미 상속 받지만 인터페이스는 개수에 상관없이 얼마든지 더 상속받을 수 있다. 선언문에서 인터페이스를 상속받고 본체에 핸들러 메서드를 정의하면 된다. But 이렇게 만들어진 뷰는 액티비티에 강하게 종속된다는 면에서 기동성이 떨어진다. 이 뷰를 다른 액티비티에 재사용하려면 액티비티가 구현하는 리스너를 분리하여 다른 액티비로 옮겨야 한다. 뷰와 관련도니 메서드가 뷰 자신에게 포함되지 않고 부모가 구현해 주기 때문에 독립성이 떨어진다.


4. 뷰가 리스너 구현

 - 액티비티가 리스너를 구현 할 수 있다면 뷰도 마찬가지이다. 액티비비나 뷰나 둘 다 클래스이므로 임의의 인터페이스를 구현할 수 있다. 어떤 이유로든 뷰를 파생했다면 클래스 선언문이 있으므로 액티비티한테 빌붙을 필요 없이 뷰 스스로가 자신이 필요로 하는 리스너 인터페이스를 상속받아 구현하면 된다.


5. 익명 이너 클래스 사용

- 3, 4번은 간편하기는 하지만 인터페이스를 구현해 줄 적당한 클래스가 있을 때만 쓸수 있는 방법이므로 역시 일반적인 해법은 아니다. 

자바 이벤트 처리 방식의 특성상 하나당 객체 하나씩을 만들어야 하는데 이는 너무 번거로운 일이다. 이벤트 처리를 위해 꼭 필요한 알맹이는 사실 핸들러 메서드 뿐이다. 그러나 객체 지향 언어이다보니 메서드가 홀로 존재할 수 없으며 클래스 안에 넣어야 하고 객체를 생성한 후 등록하는 번거러운 과정을 거쳐야 한다. 

자바는 이런 경우를 위해 언어 차원에서 익명 이너 클래스라는 문법을 제공한다. 상위 클래스나 인터페이스의 메서드 하나를 재정의하기 위해 클래스를 선언하는 경우, 그리고 그 클래스의 객체가 단 하나만 필요한 경우는 굳이 클래스를 선언할 필요 없이 상속과 재정의를 동시에 할 수 있다.



6. 익명 이너 클래스의 임시 객체 사용

 - 익명클래스의 객체 TouchListener는 두 개를 생성할 수 없으며 오로지 하나만 생성할 수 있다. 특정 뷰에 대한 이벤트 핸들러로만 쓸 경우는 굳이 두 개를 생성할 필요도 없다. 

이럴때는 객체의 이름조차도 줄 필요가 없으며 임시 객체를 하나를 생성하여 등록 메서드의 인수로 전달해버리면 된다.



또한 핸들러의 우선순위는 

뷰의 리스터 -> 뷰의 onTouchEvent 콜백 메서드 -> 액티비티의 onTouchEvent 콜백 메서드로 보면 된다. 보다시피 좁은 범위일수록 우선 순위가 높은데 이는 상식과 일치한다. 그러나 이 우선순위가 절대적인것은 아니다. 각 핸들러는 리턴값으로 다음 순위 메서드의 호출 기회를 통제한다.


Posted by 김마농