2014-02-21 13 views
7

Ich möchte ein CustomView erstellen, das ein Bild anzeigt. Beim Klicken sollte die Ansicht ihren Status ändern. Es sollte drei Zustände geben (aus, gesetzt, nicht gesetzt) ​​ die Ansicht darstellen kann. Ich möchte dies mit einem Selektor in XML tun. Es muss nicht notwendigerweise ein benutzerdefinierter Selektor sein. Ich könnte drei Zustände des Selektors wiederverwenden (es spielt keine Rolle, ob die Namen des Status dann anders sind).Wie implementiert man ein CustomView mit benutzerdefinierten Selektorzuständen?

Gibt es einen guten Weg, dies zu erreichen?

Antwort

13

Nur für den Fall, dass Ihr Problem sich noch nicht gelöst hat. Ich mache den Wechsel von Staaten mit einer neuen Implementierung des Android Button.

Die Zustände werden in .xml definiert und über einen Selektor festgelegt. Hier wird die drei definierte Zustände in der attrs.xml Datei:

<?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> 

Und der Wähler (statebutton_selector.xml) innerhalb des Drawables Ordner: (Ich gehe davon aus, dass ein bestimmten Zustand automatisch ermöglicht, die deaktiviert anderen Staaten - die Drawables wie „state_on“ sind .png nur Bilder, die die einzelnen Staaten darstellt)

<?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> 

beachten Sie außerdem, zu referenzieren Ihre korrekten Paketnamen in der Auswahl XML-Datei, wie in Ihrer Manifest-Datei angegeben:

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

Und schließlich die StateButton Klasse, die Button erstreckt. Mit einer einfachen OnClickListener wird der Zustand geändert. Ich habe auch eine OnStateChangedListener implementiert, die zum Beispiel von einer Aktivität implementiert werden kann, die den Button enthält und immer dann aufgerufen wird, wenn sich der Status ändert.

Die Änderung des Status selbst erfolgt innerhalb der onCreateDrawableState(...) Methode, die bei jedem Klick auf die Schaltfläche automatisch aufgerufen wird. "extraspace + 1" bedeutet, dass es im Array drawableStates einen zusätzlichen Status geben wird.

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; 
    } 
} 

Last but not least, stellen Sie die Wahl als Hintergrund Ihren 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="" /> 

Ein Beispiel für die Activity (mit Listener):

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)); 
    } 
} 
Verwandte Themen