비트맵 버튼 만들기

OneTwoThree·2022년 8월 7일

부스트코스 비트맵 버튼 만들기

비트맵 버튼

기존의 버튼을 상속한다.
나인패치 이미지를 버튼에 많이 적용하는데 이럴 경우 버튼이 눌려도 눌린지 아닌지 알 수 가 없어서 비트맵 이미지를 사용한다.

onDraw 메소드를 재정의 하면 버튼이 그려지는 것을 사용자가 정의할 수 있다.
onMeasure는 그려질 영역을 할당한다.

버튼을 만들기 위해 java 파일을 하나 만들어준다.

package com.example.button;

import android.content.Context;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;

public class BitmapButton extends AppCompatButton {
    public BitmapButton(@NonNull Context context) {
        super(context);
    }

    public BitmapButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
}

AppCompatButton을 상속한다.
그리고 생성자 2개를 필수로 정의해줘야 한다.
우클릭 > generate > constructor에서

위 2개를 선택해준다.
맨 위에게 java 파일에서 필요하고 두번째가 xml 파일 관련해서 필요하다.

package com.example.button;

import android.content.Context;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;

public class BitmapButton extends AppCompatButton {
    public BitmapButton(@NonNull Context context) {
        super(context);

        init(context);

    }

    public BitmapButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        init(context);
    }

    private void init(Context context){
        setBackgroundResource(R.drawable.title_bitmap_button_normal);

        setTextSize(100);

        
    }
}

이런 식으로 생성자 2개를 정의하고 생성자 내에서는 init을 호출하게 한 다음에
밖에서 init을 따로 정의했다.
그런데 setTextSize뿐만 아니라 다른 크기를 dp단위로 사용하고 싶으면 작업을 따로 해줘야 한다.

여기에 dimens.xml을 새로 만들어줘야 한다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="text_size">16dp</dimen>


</resources>

이렇게 dimens.xml을 만들어준다.

package com.example.button;

import android.content.Context;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;

public class BitmapButton extends AppCompatButton {
    public BitmapButton(@NonNull Context context) {
        super(context);

        init(context);

    }

    public BitmapButton(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        init(context);
    }

    private void init(Context context){
        setBackgroundResource(R.drawable.title_bitmap_button_normal);
        
        float textSize = getResources().getDimension(R.dimen.text_size);

        setTextSize(textSize);


    }
}

getResources().getDimension(R.dimen.text_size);를 이용해서 dimens.xml에 작성한 텍스트 사이즈를 가져온다. float형 textSize 변수에 저장하고 setTextSize 메소드에 인자로 전달한다.

package com.example.button;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;

public class BitmapButton extends AppCompatButton {
   public BitmapButton(@NonNull Context context) {
       super(context);

       init(context);

   }

   public BitmapButton(@NonNull Context context, @Nullable AttributeSet attrs) {
       super(context, attrs);

       init(context);
   }

   private void init(Context context){
       setBackgroundResource(R.drawable.title_bitmap_button_normal);

       float textSize = getResources().getDimension(R.dimen.text_size);

       setTextSize(textSize);

   }

   @Override
   public boolean onTouchEvent(MotionEvent event) {
       int action = event.getAction();

       switch (action) {
           case MotionEvent.ACTION_DOWN:
               setBackgroundResource(R.drawable.title_bitmap_button_clicked);
               break;

           case MotionEvent.ACTION_UP:
               setBackgroundResource(R.drawable.title_bitmap_button_normal);
               break;
       }

       invalidate();

       return true;
   }
}

화면 우클릭 > generate > override methods 에 가서 onTouchEvent를 오버라이딩 한다 \
버튼을 클릭했을 때 호출되는 함수이다.
버튼을 눌렀는지 뗀건지 이벤트를 알기 위해 getAction으로 가져온다.
그리고 switch문으로 구성해준다.
버튼의 backgroundResource를 지정해준다.

invalidate는 만약 상태가 바뀌면 이제 버튼의 그래픽을 다시 그려아 하기 때문에 넣은 함수이다.
또한 true를 리턴해준다. (그래야 이벤트가 지속적으로 발생)

지금까지 java 파일에 버튼을 만든 것이다.
이 버튼을 이제 xml 파일에 추가해줘야 한다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
  >

   <com.example.button.BitmapButton
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Hello World!"
       ></com.example.button.BitmapButton>



</LinearLayout>

여기서 주의할 점은 이렇게 사용자가 직접 만든 버튼을 추가할 때는 패키지 이름까지 넣어줘야 오류가 발생하지 않는다. <com.example.button.BitmapButton 이렇게 패키지 이름까지 써준 것을 확인할 수 있다.

   private void init(Context context){
       setBackgroundResource(R.drawable.title_bitmap_button_normal);

       float textSize = getResources().getDimension(R.dimen.text_size);

       setTextSize(textSize);

       setTextColor(Color.WHITE);

   }

BitmapButtom.java에서 한 것을 다시 생각해보면 AppCompatButton 을 상속받고 생성자 2개를 정의했는데 공통적으로 init을 호출한다. init에 생성할 내용을 넣어준다.
그리고 버튼을 클릭했을 때 호출되는 onTouchEvent도 호출해줬다.

근데 버튼 텍스트가 검은색이어서 하얀색으로 바꿔주려면 버튼의 생성자가 있는 .java파일에서 바꿔줘야 하는 것이다.

애뮬레이터에서 실행하면 이런 식으로 나타나고 클릭하면 색이 바뀌게 된다.

0개의 댓글