2014-02-21 2 views
7

이미지를 표시하는 CustomView을 만들고 싶습니다. 클릭하면보기가 상태를 변경해야합니다. 세 가지 상태가 있어야합니다. (해제, 설정, 설정되지 않음)보기가 나타납니다. XML에서 선택자을 사용하여이 작업을 수행하려고합니다. 커스텀 선택자가 될 필요는 없습니다. 선택기의 세 가지 상태를 재사용 할 수 있습니다 (상태 이름이 다른 경우 중요하지 않습니다).사용자 지정 선택기 상태로 CustomView를 구현하는 방법은 무엇입니까?

이것을 수행하는 좋은 방법이 있습니까?

답변

13

문제가 아직 해결되지 않은 경우에 대비해. 나는 안드로이드 Button의 새로운 구현으로 상태를 변경합니다.

상태는 .xml로 정의되고 선택자을 통해 설정됩니다. 여기에 세 가지 상태가 attrs.xml이 파일에 정의 :

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <declare-styleable name="states"> 
     <attr name="state_on" format="boolean" /> 
     <attr name="state_off" format="boolean" /> 
     <attr name="state_notset" format="boolean" /> 
    </declare-styleable> 
</resources> 

그리고 선택 (statebutton_selector.xml)이 드로어 블 내부 폴더 : 는 (I 자동으로 특정 상태를 가능하면 비활성화 가정 다른 주 - "state_on"같은 드로어 블은 또한, 을 참조 할주의 개별 상태를 나타내는 이미지)

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res/com.example.statebuttontest"> 
<item 
    app:state_on="true" 
    app:state_off="false" 
    app:state_notset="false" 
    android:drawable="@drawable/state_on" /> 
<item 
    app:state_on="false" 
    app:state_off="true" 
    app:state_notset="false" 
    android:drawable="@drawable/state_off" /> 
<item 
    app:state_on="false" 
    app:state_off="false" 
    app:state_notset="true" 
    android:drawable="@drawable/state_notset" /> 
</selector> 

을 .png를하고 있습니다 매니페스트 파일에 명시된대로 선택기 XML 파일에서 올바른 패키지 이름 :

xmlns:app="http://schemas.android.com/apk/res/com.example.statebuttontest" 

그리고 마지막으로, Button를 확장하는 StateButton 클래스입니다. 간단한 OnClickListener으로 상태가 변경됩니다. 또한 OnStateChangedListener을 구현했습니다. 예를 들어 Button이 포함 된 Activity에 의해 구현 될 수 있으며 상태가 변경 될 때마다 호출됩니다.

상태 변경은 onCreateDrawableState(...) 메서드 내에서 자동으로 버튼을 클릭 할 때마다 수행됩니다. "extraspace + 1"은 drawableStates 배열 안에 하나의 추가 상태가 있음을 의미합니다.

public class StateButton extends Button implements OnClickListener { 

    private static final int[] mStates = { R.attr.state_notset, R.attr.state_on, R.attr.state_off }; 
    private int mStateIndex = 0; // first state is "notset" 

    private OnStateChangedListener mListener; 

    public StateButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View v) { 
     changeState(); 
    } 

    public void changeState() { 
     mStateIndex = (mStateIndex+1) % mStates.length; 

     // notify listener 
     if(mListener != null) mListener.onStateChanged(mStates[mStateIndex]); 
    } 

    @Override 
    protected int[] onCreateDrawableState(int extraSpace) { 

     final int[] drawableState = super.onCreateDrawableState(extraSpace+1); 

     int [] state = { mStates[mStateIndex] }; 

     mergeDrawableStates(drawableState, state); 

     return drawableState; 
    } 

    public void setOnStateChangedListener(OnStateChangedListener l) { 
     this.mListener = l; 
    } 
} 

마지막으로, 는 배경으로 선택 설정의 당신의 Button :

<com.example.statebuttontest.StateButton 
     android:id="@+id/stateButton1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
     android:layout_centerVertical="true" 
     android:background="@drawable/statebutton_selector" 
     android:text="" /> 

(수신기 포함) Activity의 예 :

public class MainActivity extends Activity implements OnStateChangedListener { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     StateButton s = (StateButton) findViewById(R.id.stateButton1); 
     s.setOnStateChangedListener(this); 
    } 

    @Override 
    public void onStateChanged(int state) { 
     Log.i("Main", "State changed to: " + getResources().getResourceEntryName(state)); 
    } 
}