2013-09-23 12 views
4

ViewGroup을 확장하는 클래스를 만들었습니다. 이 MyCustomViewGroup 클래스의 기능 중 하나는 Button을 확장하는 중첩 클래스 MyButton의 컨테이너 역할을합니다.공통 리소스에서 사용자 정의 ViewGroup의 여러 구성 요소에 대한 StateListDrawables 만들기

정상적인 방법으로 사용자 지정 AttributeSet에서 MyCustomViewGroup에 대한 사용자 지정 속성을 설정했습니다. 이 속성 중 하나는 MyButton 중첩 클래스의 인스턴스 배경에 사용할 StateListDrawable을 정의합니다. 이 클래스 변수를 mMyButtonBackground에 저장합니다.

public class MyCustomViewGroup extends ViewGroup { 
    private Drawable mMyButtonBackground; 
    ... 

MyCustomViewGroup에 MyButton의 새 인스턴스를 만들 때마다 배경을 설정합니다.

MyButton myButton = new MyButton(context); 
    myButton.setBackground(mMyButtonBackground); 

런타임시 StateListDrawable은 가장 최근에 추가 된 MyButton 인스턴스에서만 작동하는 것 같습니다.

예를 들어 MyCustomViewGroup에 MyButton의 인스턴스를 4 개 생성한다고 가정 해보십시오. MyButton 번호 4를 클릭하면 StateListDrawable에 정의 된대로 배경이 변경됩니다. MyButton 1에서 3을 클릭하면 배경이 변경되지 않지만 MyButton 4에서 변경됩니다.

논리적으로 이것은 변경 가능성 문제를 암시합니다. 모든 MyButton 인스턴스는 mMyButtonBackground에 저장된 동일한 StateListDrawable을 공유합니다. 이것을 고려해 볼 때, 나는 시도했다 :

MyButton myButton = new MyButton(context); 
    Drawable myButtonBackground = mMyButtonBackground.mutate(); 
    myButton.setBackground(myButtonBackground); 

그러나 이것은 문제를 해결하지 못했다. 나는 또한 그것을 StateListDrawable로 캐스팅하려고 시도했습니다.

MyButton myButton = new MyButton(context); 
    StateListDrawable myButtonBackground = (StateListDrawable)mMyButtonBackground.mutate(); 
    myButton.setBackground(myButtonBackground); 

이 또한 문제를 해결하지 못했습니다. 이 문제를 해결하기 위해 내 연구에서 나는 this article by Romain Guy on Drawable mutations을 읽었습니다. StateListDrawable은 Drawable의 하위 클래스이므로 동일한 접근 방식을 적용 할 수 있어야한다고 생각 했겠지만 작동시키지 못합니다. 내가 뭘 놓치고 있니?

+0

아니요 정적이 아니지만 지금은 명확하게하기 위해 질문을 편집했습니다. 감사. –

답변

3

죄송보기 당 하나의 SLD가 필요합니다. Drawable을 배경으로 설정하면 에 대한 청취자로 등록되어 Drawable이라는 새 통계를 받아 들일 수 있으며 다시 그리기는 View이어야합니다. 따라서 단일 인스턴스 StateListDrawable은 항상 배경으로 설정된 View의 콜백을 갖습니다. 그래서 마지막으로 Button에서 작동하지만, Drawable은 콜백 View에서 무효화를 유발하므로 다른 Buttons에 대한 조치를 취하면 동일한 Button이 다시 그려집니다.

Button에 대해 새 StateListDrawable을 생성하면 쉽게 피할 수 있습니다. 새로운 Buttons을 만들 때 래퍼 컨테이너에서 당신은 단지 배경으로 사용하기 위해 StateListDrawable의 이름을 나타내는 String과 속성을 전달 그것을 저장하고 사용할 수 있습니다

String mBtnDrawable = ""; //initialize in the constructor 

// creating new Buttons 
MyButton myButton = new MyButton(context); 
int drawableId = getContext().getResources().getIdentifier(mBtnDrawable, "drawable", getContext().getPackageName()); 
StateListDrawable bck = (StateListDrawable) getContext().getResources().getDrawable(drawableId); // maybe also mutate it? 
myButton.setBackground(bck); 
+0

하나의 작은 발언 : .getResources(). getIdentifier()를 사용하지 않아도됩니다. 대신에 느린 대신 format = "reference"로 속성을 만들어서 사용할 수 있습니다. myAttr = "@ drawable/something"로 xml – pskink

+0

@pskink 알아요.하지만 게으르므로 직접적인 방법으로 문서를 보지 않았습니다. – Luksprog

+0

나도 알아, 게으름은 틀린 게 아냐. – pskink

7

여러 뷰와 SLD의 한 인스턴스를 공유 할 수 없습니다, 당신은 문제가 같은 Drawable 인스턴스를 사용한다는 것입니다, pskink 대답에 따라

+0

예 그게 문제라고 생각했습니다. 확인해 주셔서 감사합니다. 내가 Luksprog에 대한 내 의견에서 말한 것처럼 멋진 청결한 솔루션처럼 보인 MyButton의 새로운 인스턴스를 만들 때마다 mMyButtonBackground를 복제하려고 시도했지만 Clone() 메서드는 StateListDrawables에 대해 숨겨져 있습니다. 클론을 만들 수있는 방법이 있습니까? –

+0

클론이 보호되어 SLD를 확장하고 거기에있는 – pskink

0

를 자원 클래스가 무엇에 따르면 (Resources.java를), 아래 코드가 문제를 해결할 수 있음을 알게되었습니다.

Drawable selector = res.getDrawable(R.drawable.setting_btn_pressed_selector); 
view1.setBackgroundDrawable(selector.getConstantState().newDrawable()); 
view2.setBackgroundDrawable(selector.getConstantState().newDrawable()); 
view3.setBackgroundDrawable(selector.getConstantState().newDrawable()); 

하지만이 코드의 부작용을 알지 못합니다. 누구 알아? 의견을 남기거나 저의 실수를 지적하십시오.