2012-08-02 2 views
4

J'essaie d'écrire mon propre CheckBox en utilisant RelativeLayout avec TextView et FrameLayout (avec le sélecteur sur le fond) à l'intérieur.Faire RelativeLayout vérifiable

J'ai setDuplicateParentStateEnabled(true) pour FrameLayout que cela prenne l'état vérifiable du parent, mais pourquoi faire RelativeLayout vérifiable je ne sais pas.

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

Répondre

5

J'ai juste besoin méthode de remplacement:

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

Maintenant, tous les travaux.

+1

Essayé. Ne fonctionne pas sur 4.0.3 X- ( – Mus

+0

Mus, mon application fonctionne sur 4.0.3 et 4.1.1 bien avec ce code – Nik

+0

Pouvez-vous poster votre mise en page XML? J'ai aussi des problèmes. Avez-vous mis android: clickable = "true" dans la mise en page par hasard? –

8

Il semble y avoir deux modèles d'interface utilisateur pour les listes sélectionner plusieurs dans Holo (dans le contexte de ActionMode): à l'aide de cases à cocher ou en surbrillance.

Si tout ce que vous avez besoin est mise en évidence, vous pouvez utiliser cette méthode plus simple:

Faites votre utilisation de mise en page de l'élément de la liste pour la racine d'une classe comme celui-ci:

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

et assurez-vous que l'élément racine dans votre mise en page élément de la liste utilise

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

Je sais que ce n'est pas vraiment une réponse à votre question (vous vouliez une case à cocher réelle), mais je n'ai pas vu cette anywhe documentée ré. Le ListView utilise l'interface Checkable pour déterminer s'il peut compter sur l'élément de liste pour afficher l'état vérifiable ou s'il doit essayer de l'afficher lui-même.

+0

Merci beaucoup pour ce @ Pierre-Luc! J'ai perdu tellement de temps à ce sujet dans le Les deux derniers jours et votre mise en œuvre était un excellent point de départ.Je ne voulais pas non plus de case à cocher, mais je devais mettre en place un checkable – krider2010

+0

@ Pierre-Luc, vous êtes une légende monsieur, je suivais [ce tutoriel] (http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/) pour implémenter un RelativeLayout vérifiable, mais il manquait refreshDrawableState(). Mes éléments ListView devaient être touchés deux fois avant que l'élément ne soit sélectionné (mis en évidence) –

+0

Bien sûr, c'est sup posé pour être "R.attr.state_pressed"? –

3

réponse Nik est en partie pour moi, vous avez besoin d'ajouter android.R.attr.state_checkable dans le tableau STATE_CHECKABLE, et réglez l'lenth correspondante (2), ou bien elle ne fonctionne pas.

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