[왕초보]특정 조건에서 선택된 버튼의 background 를 바꾸고싶습니다

조회수 2376회

여러 액션 진행하는 중에 n=1이 되는 조건에서 29개의 버튼중에서 아무거나 하나 선택했을때

그 선택된 버튼의 background가 A 라면 B로 바꾸는 작업을 하려고 합니다.


for(i in 0..28) {
            var name: Int = getResources().getIdentifier("imageButton" + i, "id", getPackageName())
            var bgi: Int = getResources().getIdentifier("imageButton" + i, "background", getPackageName())
            if (n == 1) {
                (findViewById<ImageButton>(name)).setOnClickListener {
                    if (bgi == R.drawable.A) {
                        (findViewById<ImageButton>(name)).setBackgroundResource(R.drawable.B)
                    }
                }
            }
        }

이렇게 명령문을 짜봤는데 override fun onCreate() 안에 넣어도 안되고

n=1일떄 작동하는 다른 함수 안에 넣어도 안되는데 명령문을 잘못짠걸까요?ㅜㅜ

어떻게 바꿔야할지 조언부탁드려요 ㅠ

1 답변

  • 좋아요

    0

    싫어요
    채택 취소하기
    var bgi: Int = getResources().getIdentifier("imageButton" + i, "background", getPackageName())
    

    위 코드로 ImageButtonbackground id 를 가져오려고 하신것 같은데 getIdentifier()R.id.something, R.string.something, R.drawable.somethingres 폴더에 있는 리소스 들을 이름을 매개변수로 하여 id 를 찾는 메소드 입니다. 따라서 위 코드로는 background id 를 얻어 올 수 없습니다.

    먼저 getIdentifier() 에 대한 설명을 여기서 확인하시기 바랍니다.

    그렇다면 다른 방법이 필요합니다. ImageButton 에서 android:background 속성을 지정 했을때 내부적으로 해당 리소스에 대한 Drawable 객체가 생성됩니다. 이미지 파일을 지정했다면 BitmapDrawable 이 생성 될 것이고 layer-list 로 custom drawable 를 만드셨다면 LayerDrawable 객체가 생성 됩니다.

    문제는 Drawable 객체로 부터 리소스 id 를 가져올 방법이 마땅치 않다는 것인데요. 따라서 ImageButton 을 커스터마이징 하여 문의하신 내용에 대한 답변을 드려보려고 합니다.

    먼저, android:background 속성은 사용하지 않고 커스텀 속성을 만들어서 사용 할 것입니다. 아래와 같이 작성 됩니다.

    1. res/values/attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="CustomImageButton">
            <attr name="backgroundResource" format="integer" />
        </declare-styleable>
    </resources>
    

    2.CustomImageButton 를 작성합니다

    class CustomImageButton(context: Context, attrs: AttributeSet) : ImageButton(context, attrs) {
    
        private var backgroundResourceId = View.NO_ID
    
        init {
            //custom attrs load
            context.theme.obtainStyledAttributes(
                    attrs,
                    R.styleable.CustomImageButton,
                    0, 0).apply {
    
                try {
                    val bgResId = getResourceId(R.styleable.CustomImageButton_backgroundResource, 0)
                    if (bgResId != 0) {
                        setBackgroundResource(bgResId)
                    }
                } finally {
                    recycle()
                }
            }
        }
    
        override fun setBackgroundResource(resid: Int) {
            super.setBackgroundResource(resid)
            backgroundResourceId = resid
        }
    
        fun sameCheck(checkeResId: Int) = backgroundResourceId == checkeResId
    }
    

    이렇게 하면 layout 을 작성할 때 namespace:backgroundResource 속성으로 drawable id 를 지정 할 수 있습니다. 또한 setBackgroundResource() 를 override 하여 backgroundResId 값을 변수에 넣습니다. 이러면 해당 ImageButton 에 어떤 id 의 drawable resource 가 정의 되었는지 알 수 있고, sameCheck() 를 통해 매개변수로 넘어온 resId 가 현재 정의 된 drawable resource id 인지 비교 할 수 있습니다.

    3.layout 작성

    저는 6개의 ImageButton 을 추가 하였습니다. 각각의 id 는 imageButton(0~5) 이며, 위에서 만든 backgroundResource 속성을 사용 합니다. app 이라는 namespace 를 사용하였지만 사실 namespace 는 다른것을 써도 무방합니다. 또한 ic_launcher_background 를 background 로 지정 하였습니다.

    <?xml version="1.0" encoding="utf-8"?>

    <filysoft.buttontest.CustomImageButton
        android:id="@+id/imageButton0"
        ...
        app:backgroundResource="@drawable/ic_launcher_background" />
    
    <filysoft.buttontest.CustomImageButton
        android:id="@+id/imageButton1"
        ...
        app:backgroundResource="@drawable/ic_launcher_background" />
    
    <filysoft.buttontest.CustomImageButton
        android:id="@+id/imageButton2"
        ...
        app:backgroundResource="@drawable/ic_launcher_background" />
    
    <filysoft.buttontest.CustomImageButton
        android:id="@+id/imageButton3"
        ...
        app:backgroundResource="@drawable/ic_launcher_background" />
    
    <filysoft.buttontest.CustomImageButton
        android:id="@+id/imageButton4"
        ...
        app:backgroundResource="@drawable/ic_launcher_background" />
    
    <filysoft.buttontest.CustomImageButton
        android:id="@+id/imageButton5"
        ...
        app:backgroundResource="@drawable/ic_launcher_background" />
    

    4.마지막으로 MainActivity 를 다음과 같이 작성 합니다.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        for (i in 0..5) {
            val btnId = resources.getIdentifier("imageButton$i", "id", packageName)
            findViewById<View>(btnId).setOnClickListener(imageBtnClickListener)
        }
    }
    
    private val imageBtnClickListener = View.OnClickListener {
        (it as CustomImageButton).apply {
            if (n == 1) {
                if (sameCheck(R.drawable.ic_launcher_background)) {
                    setBackgroundResource(R.drawable.ic_launcher_foreground)
                }
            }
        }
    }
    

    n == 1 인 상태 일때 sameCheck() 를 통해 drawable 을 비교 합니다. 저는 ic_launcher_background 와 동일한지 비교 하였고, 동일할경우 ic_launcher_foreground 로 변경 하도록 작성 하였습니다.

    만약 button 이 동적으로 생성 된 다거나, 사용되는 background 종류가 몇개 되지 않는다면 view 의 tag 를 이용하는 방법도 생각 해 볼 수 있을 것 같습니다. 제가 jaguar 님의 정확한 상황을 몰라서 일단 위 방식으로 작성해보았네요. 이외에도 방법은 여러가지가 있을 수도 있습니다.

    좀 즉흥적으로 작성하느라 잘못된 부분이 있을수 있습니다만 접근방식과 흐름을 파악하시면 조금이나마 도움이 되실거라 생각 됩니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 정말정말 감사합니다! 알려주신대로 작성완료했는데, CustomImageButton.kt 에 AttributeSet 을 Unresolved reference라며 에러가 납니다. 이 부분을 어떻게 해야하나요?ㅜㅜ jaguar 2018.8.17 11:00
    • 앗 갑자기 해결됐네요 ㅋㅋㅋㅋ 정말 감사합니다!!! jaguar 2018.8.17 11:07
    • 다행이네요 즐거운 개발되세요:) 알 수 없는 사용자 2018.8.17 11:15
    • 안녕하세요! 지난번에 답 주신것에서 조금 수정하려고 하는데 어디를 손대야 좋을지 몰라서 다시 질문드려요 새로 질문글을 올릴까하다가 위 내용과 연결이 되어야할것같아서 댓글로 질문드립니다. 혹시 새로운 질문글을 올리는 것이 편하시다면 말씀주세요! jaguar 2018.8.23 23:31
    • 앗 질문을 다 하지 못했는데 글이 올라가버렸네요. 지난번 질문은 선택된 버튼의 이미지를 바꾸는 것이었는데, 이를 조금 바꿔서 어떤 버튼 "imageButton"+i 을 선택하면 또다른 변수 t 에 대해서 "imageButton"+(i+t) 의 이미지가 바꼈으면 하는데 어떻게 할 수 있을까요? jaguar 2018.8.23 23:33
    • 1. 클릭한 버튼의 getResourceName() 을 통해 이름을 가져옵니다 2. imageButton[index] 형태의 id 이므로 "imageButton" 이후의 string 을 가져와서 int 로 변환합니다. 3. t 를 더하여 다시 getIdentifier() 를 통해 id 를 가져온 후 해당하는 imageButton 의 이미지를 변경합니다 알 수 없는 사용자 2018.8.24 10:26
    • 답이 너무 늦었네요! 알려주신대로 해봤는데 코드를 잘못넣었더니 NullPointerException 에러랑 이런저런 에러가 나서 한참 헤매다가 드디어 성공했습니다!!! 매번 너무너무 감사합니다!!!! 덕분에 포기하지않고 느리지만 조금씩 발전해가며 즐겁게 개발하고있습니다! 다시한번 정말 감사합니다! jaguar 2018.8.30 15:12

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)