2012-08-02 28 views
4

我尝试使用RelativeLayoutTextViewFrameLayout(在选择器背景)内写我自己的CheckBox使RelativeLayout可检查

我有setDuplicateParentStateEnabled(true)对于FrameLayout它从父级检查状态,但为什么使RelativeLayout检查我不知道。

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

回答

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

现在所有的作品。

+1

试了一下。 。?对4.0.3 X-不起作用( – Mus 2012-11-06 11:22:30

+0

亩,我的应用程序在4.0.3和4.1.1的精品工程,此代码 – Nik 2012-11-06 11:27:41

+0

您可以发布您的布局XML,我有太多的问题你有没有设置机器人:点击在万一布局=“真”? – 2014-04-15 12:13:12

8

似乎有对在全息多选列表(在ActionMode的上下文中)两个UI模式:使用复选框或高亮。

如果你需要的是突出,你可以用这个简单的方法:

使根列表项的布局使用的一类像这样的:

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" 

我知道这是不是一个真正的回答你的问题(你想要一个实际的复选框),但我还没有看到这个记录anywhe回覆。

ListView控件使用勾选的接口,以确定它是否可以依靠列表项元素上显示可检查状态,还是应尽量显示它本身。

+0

非常感谢你为这个@皮埃尔 - 吕克!我在浪费了太多时间在这过去几天和你的实现是一个很好的起点,我也不想一个复选框,但实现可检验的需要 – krider2010 2013-12-07 21:15:47

+0

@皮埃尔 - 吕克,你是一个传奇先生,我是继[本教程(HTTP:。。/ /www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/)来实现可检查的RelativeLayout但缺少refreshDrawableState()。我的ListView项目不得不被触摸两次成为该选项之前(突出显示)。 – 2014-01-03 12:36:29

+0

当然是sup构成“R.attr.state_pressed”? – 2015-11-08 11:08:51

3

Nik的回答对我来说是部分正确的,你需要将STANDARD_CHECKABLE数组中添加android.R.attr.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; 
}