들어가기 전에
안드로이드의 SDK에는 다양한 위젯들이 들어 있습니다.
대표적인 것으로 버튼이나 텍스트뷰를 들 수 있죠.
그런데 버튼의 모양을 조금 바꾸고 싶어도 버튼에서 사용할 수 있는 속성이 없다면 어떻게 해야 할까요?
버튼을 상속해서 새로운 버튼을 만들면 원하는 기능을 추가할 수 있습니다.
버튼의 배경에 이미지를 넣어주고 이 이미지가 버튼이 터치된 상태에 따라 바뀌도록 만들 수도 있습니다.
새로운 버튼을 만드는 방법을 알아봅시다.
학습 목표
- 이미지를 배경으로 설정하고 상태에 따라 변하도록 하려면 어떻게 해야 하는지 설명해봅시다.
핵심 단어
학습하기
비트맵 버튼
버튼의 배경에 이미지를 설정하고 그 버튼이 눌렸을 때 배경 이미지를 다르게 보여주고 싶다면 버튼을 상속해서 새로운 버튼을 만들 수 있습니다.
터치된 상태에 따라 배경 이미지를 바꾸어주어야 하니 터치 이벤트를 처리하는 방법도 알아야 하죠.
배경 이미지를 바꾸고 나면 바뀐 이미지를 화면에 보여줄 수 있게 화면을 갱신해야 합니다.
이때 invalidate 메소드가 사용됩니다.
Invalidate 메소드를 호출하면 화면을 다시 그리게 되며 추가적으로 그릴 수 있도록 onDraw 메소드도 호출해줍니다.
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
setBackgroundResource(this.iconClicked);
break;
case MotionEvent.ACTION_UP:
setBackgroundResource(this.iconNormal);
break;
}
invalidate();
return true;
}
뷰를 상속해서 새로운 뷰를 만든 경우에는 XML 레이아웃에 추가할 때 패키지 명까지 같이 넣어줍니다.
예를 들어, 버튼을 상속해서 비트맵 버튼을 만들었다면 다음과 같이 추가할 수 있습니다.
<org.techtown.bitmapwidget.BitmapButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
생각해보기
- 버튼의 배경 이미지가 바뀌는 기능을 좀 더 간단한 방법으로 만들 수는 없을까요?
- 만약 setBackground 함수만 호출하고 Invalidate메소드를 호출하지 않으면 어떤 일이 생길까요?
참고 자료
comment
현재 2021년 8월 안드로이드 버전에서는 안되는데 어떻게 해야 할까요??
현재 맥 기준에서 안드로이드 스튜디오를 사용한다면, 새로운 java 클래스를 생성할 때 create new class 대화상자를 사용할 수 없는 경우가 있습니다. 이때는 java 소스코드에서 직접 AppCompatButton 을 import 해주어야 사용 가능합니다.
import가 필요한 패키지의 경로는 다음과 같습니다.
버튼 모양을 바꿀 수 있는게 xml selector 지정해서 할 수도 있고,이런 식으로 할수도 있는거죠 ?
⭐️생각해보기⭐️
1. 상태 드로어블로 만들 수 있습니다. 또는 Button의 setBackground 메소드를 이용해도 됩니다.
2. 내부적으로는 변경되었지만 실제 단말기 화면에서는 보이지 않을 것 같습니다.
셀렉터를 좀더 쉽게 만들어주는 툴이 있어 공유 합니다
원하시는 상태에 원하시는 이미지를 드레그엔드롭으로 넣어주시고 제너레이트 버튼 눌러 주시면 원하시는 셀렉터를 만들어 드립니다
출처는 워낙 옜날에 받아 놓은거라 기억이 안나네요 문제가 되면 지우겠습니다
https://1drv.ms/u/s!AkHazPhIOHJsgb0l1lceqscDuQ2URw
제가 이해한것이 맞는지 모르겠지만, 다른 커스텀 뷰를 만들고싶다면 이런 방법으로 구현하면 되겠네요!
생각해보기
1. 상태드로어블을 사용하는 것 좋은 생각인 것 같습니다 !
2. invalidate 함수가 다시 그려주는걸 요청하는 함수라고 하셨는데, invalidate를 주석처리하고 실행해 보아도 차이점이 없습니다. 제가 뭘 잘못한건가요..?
1. 상태드로어블 강의에서 했던 방식으로 하는 것이 더 간단하지 않을까 생각합니다.
2. setBackground함수만 호출한다면, 버튼을 눌렀을때 버튼의 이미지가 바꼈다가, 손을 버튼에서 뗐을 때 버튼의 이미지가 돌아오지 않고, 바뀐 이미지 그대로 setting되어 유지될 것 같습니다.