我想创建一个显示图像的CustomView。单击后, View 应更改其状态。 View 可以代表的状态为(关闭,设置,未设置)三种状态。我想使用XML中的选择器来做到这一点。不必一定是自定义选择器。我可以重用选择器的三个状态(状态名称不同则没关系)。

有没有一个好的方法可以做到这一点?

最佳答案

以防万一您的问题尚未解决。我使用Android 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 ):
(我假设启用特定状态会自动禁用其他状态-诸如“state_on”之类的可绘制对象只是表示各个状态的.png图像)
<?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>

另外,请注意,如 list 文件中所述,在选择器xml文件中引用您正确的软件包名称:
xmlns:app="http://schemas.android.com/apk/res/com.example.statebuttontest"

最后,扩展了StateButtonButton类。使用简单的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));
    }
}

10-05 23:13
查看更多