[왕초보]특정 조건에서 선택된 버튼의 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 답변
-
var bgi: Int = getResources().getIdentifier("imageButton" + i, "background", getPackageName())
위 코드로
ImageButton
의background
id
를 가져오려고 하신것 같은데getIdentifier()
는R.id.something
,R.string.something
,R.drawable.something
등res
폴더에 있는 리소스 들을 이름을 매개변수로 하여 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
-
댓글 입력