4

我尝试在里面CheckBox使用RelativeLayoutwithTextViewFrameLayout(在背景上使用选择器)编写我自己的。

我认为它需要父母的可检查状态,但为什么要setDuplicateParentStateEnabled(true)检查我不知道。FrameLayoutRelativeLayout

public class MyCheckbox extends RelativeLayout implements OnClickListener, Checkable
{
private static final int ID_CHECKBOX = -1234411;
private static final int ID_TEXTVIEW = -1234412;
private static final int ID_PARENT = -1234413;

private TextView textView;
private FrameLayout checkBox;
private boolean isChecked;

public MyCheckbox(Context context)
{
    this(context, null);
}

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

    LayoutParams lp;

    setId(ID_PARENT);
    setOnClickListener(this);

    // checkBox
    checkBox = new FrameLayout(context);
    checkBox.setId(ID_CHECKBOX);
    checkBox.setDuplicateParentStateEnabled(true);

    // textView
    textView = new TextView(context);
    textView.setId(ID_TEXTVIEW);
    textView.setOnClickListener(this);


    boolean checkboxToRight = false;

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaptrixCheckbox);

    for (int i = 0; i < a.getIndexCount(); i++)
    {
        int attr = a.getIndex(i);
        switch (attr)
        {
            case R.styleable.MyCheckbox_checkboxToRight:
                checkboxToRight = a.getBoolean(attr, false);
                break;

            case R.styleable.MyCheckbox_checkMark:
                checkBox.setBackgroundDrawable(a.getDrawable(attr));
                break;

            case R.styleable.MyCheckbox_text:
                textView.setText(a.getText(attr));
                break;
        }
    }
    a.recycle();

    if (checkboxToRight)
    {
        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        lp.addRule(ALIGN_PARENT_RIGHT);
        lp.addRule(CENTER_VERTICAL);
        lp.setMargins(margins, 0, margins, 0);
        addView(checkBox, lp);

        lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        lp.addRule(CENTER_VERTICAL);
        lp.addRule(LEFT_OF, ID_CHECKBOX);
        addView(textView, lp);
    }
    else
    {
        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        lp.addRule(CENTER_VERTICAL);
        lp.setMargins(margins, 0, margins, 0);
        addView(checkBox, lp);

        lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        lp.addRule(CENTER_VERTICAL);
        lp.addRule(RIGHT_OF, ID_CHECKBOX);
        addView(textView, lp);
    }

    refreshDrawableState();
}

@Override
public void onClick(View v)
{
    int id = v.getId();

    if (id == ID_PARENT || id == ID_TEXTVIEW) toggle();
}

public boolean isChecked()
{
    return isChecked;
}

public void setChecked(boolean chacked)
{
    isChecked = chacked;
    refreshDrawableState();
}

@Override
public void toggle()
{
    isChecked = !isChecked;
    refreshDrawableState();
}
}
4

4 回答 4

9

Holo 中的多选列表似乎有两种 UI 模式(在 ActionMode 的上下文中):使用复选框或突出显示。

如果您只需要突出显示,您可以使用这个更简单的方法:

使您的列表项布局用于根类,如下所示:

public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
private static final int[] STATE_CHECKABLE = {R.attr.state_pressed};
boolean checked = false;

public void setChecked(boolean checked) {
    this.checked = checked;
    refreshDrawableState();
}

public boolean isChecked() {
    return checked;
}

public void toggle() {
    setChecked(!checked);
}

@Override
protected int[] onCreateDrawableState(int extraSpace) {
    int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
    if (checked) mergeDrawableStates(drawableState, STATE_CHECKABLE);

    return drawableState;
}
}

并确保列表项布局中的根元素使用

android:background="?android:attr/listChoiceBackgroundIndicator"

我知道这并不是您问题的真正答案(您想要一个实际的复选框),但我还没有在任何地方看到此文档。

ListView 使用 Checkable 接口来确定它是否可以依赖列表项元素来显示可检查状态,或者它是否应该尝试显示它自己。

于 2012-11-23T08:27:22.017 回答
5

我只需要覆盖方法:

private static final int[] STATE_CHECKABLE = {android.R.attr.state_checked};

@Override
protected int[] onCreateDrawableState(int extraSpace)
{
    int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
    if (isChecked) mergeDrawableStates(drawableState, STATE_CHECKABLE);
    return drawableState;
}

现在一切正常。

于 2012-08-02T10:47:21.890 回答
3

Nik 的回答对我来说部分正确,您需要将android.R.attr.state_checkable添加到 STATE_CHECKABLE 数组中,并设置相应的 lenth (2),否则无法正常工作。

private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked, android.R.attr.state_checkable};

@Override
protected int[] onCreateDrawableState(int extraSpace)
{
    int[] result = super.onCreateDrawableState(extraSpace + CHECKED_STATE_SET.length);
    if(mChecked) mergeDrawableStates(result, CHECKED_STATE_SET);
    return result;
}
于 2013-05-08T03:53:52.267 回答
0

http://developer.android.com/reference/android/view/View.html#setClickable%28boolean%29

public MyCheckbox(Context context)
{
    this(context, null);
    this.setClickable(true);
}

public MyCheckbox(Context context, AttributeSet attrs)
{
    super(context, attrs);
    this.setClickable(true);
//......
}
于 2012-08-02T10:49:09.407 回答