2010-10-08 8 views
1

J'ai un ExpandableListView que je veux remplir avec mes vues personnalisées du type NoteView. NoteView étend LinearLayout et contient deux boutons et une case à cocher. J'ai presque tout fonctionnant, les NoteView sont remplis avec des données de support, les listes sont remplies, et les boutons sont cliquables et accomplissent les tâches requises.Comment implémenter une ligne listview personnalisée avec des boutons?

Le problème est que ExpandableListView ne répond plus du tout aux événements click/longclick/keypress (autres que la sélection d'éléments de liste avec trackball/DPAD). J'ai remplacé ma vue personnalisée par un TextView standard et les événements tactiles ont repris leur cours normal. Il est donc presque certain que je fais quelque chose de mal avec ma vue personnalisée ou un paramètre ListView obscur que je néglige.

Voici mon code NoteView et ma mise en page XML. Qu'est-ce que je rate?

//Custom Note View 
public class NoteView extends LinearLayout{ 

    private CheckBox mCheckBox; 
    private TextView mTitleTextView; 
    private TextView mDetailsTextView; 
    private TextView mDetailsRightTextView; 
    private LinearLayout mButtonLayout; 
    private Button mDeleteButton; 
    private Button mEditButton; 

    //data storage 
    private long mNoteId = -1; 
    private boolean mStretched = false; 
    private CharSequence mDetails = ""; 
    private CharSequence mStretchedDetails = ""; 
    private CharSequence mDetailsRight = ""; 
    private CharSequence mStretchedDetailsRight = "";  


    private NoteView.OnNoteButtonClickedListener mEditNoteListener; 
    private NoteView.OnNoteButtonClickedListener mDeleteNoteListener; 
    private NoteView.OnNoteCheckBoxClickedListener mCheckboxListener; 

    public NoteView(Context context) { 
     super(context); 
     init(context); 
    } 

    public NoteView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(context); 
    } 


    private void init(Context context) { 

     this.setPadding(0, 0, 5, 0); 
     this.setOrientation(LinearLayout.VERTICAL); 

     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     inflater.inflate(R.layout.noteview_layout, this);//returns the noteview itself, since is parent 

     //get views 
     mCheckBox = (CheckBox) findViewById(R.id.noteViewCB); 
     mTitleTextView = (TextView) findViewById(R.id.noteViewTitle); 
     mDetailsRightTextView = (TextView) findViewById(R.id.noteViewDetailsRight); 
     mDetailsTextView = (TextView) findViewById(R.id.noteViewDetails); 


     mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       if(mCheckboxListener != null) 
       { 
        mCheckboxListener.onNoteCheckBoxClicked(mNoteId, isChecked); 
       } 
      } 
     }); 

     //prepare button layout 
     mButtonLayout = (LinearLayout) findViewById(R.id.noteViewButtonLayout); 
     mEditButton = (Button) findViewById(R.id.noteViewEditButton); 
     mDeleteButton = (Button) findViewById(R.id.noteViewDeleteButton); 


     mEditButton.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       if(mEditNoteListener != null) 
       { 
        mEditNoteListener.onNoteButtonClicked(mNoteId); 
       } 
      } 
     }); 

     mDeleteButton.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       if(mDeleteNoteListener != null) 
       { 
        mDeleteNoteListener.onNoteButtonClicked(mNoteId); 
       } 
      } 
     }); 

    } 

    public void setOnEditClickedListener(NoteView.OnNoteButtonClickedListener listener) 
    { 
     mEditNoteListener = listener; 
    } 

    public void setOnDeleteClickedListener(NoteView.OnNoteButtonClickedListener listener) 
    { 
     mDeleteNoteListener = listener; 
    } 


    public void setOnCheckboxClickedListener(NoteView.OnNoteCheckBoxClickedListener listener) 
    { 
     mCheckboxListener = listener; 
    } 

    static abstract class OnNoteButtonClickedListener 
    { 
     public abstract void onNoteButtonClicked(long noteId); 
    } 


    static abstract class OnNoteCheckBoxClickedListener 
    { 
     public abstract void onNoteCheckBoxClicked(long noteId, boolean checked); 
    } 


    public void setNoteId(long noteId) 
    { 
     mNoteId = noteId; 
    } 

    public long getNoteId() 
    { 
     return mNoteId; 
    } 

    public void setTitle(CharSequence title) 
    { 
     mTitleTextView.setText(title); 
    } 

    public void setChecked(boolean checked) 
    { 
     mCheckBox.setChecked(checked); 
    } 

    public boolean isChecked() 
    { 
     return mCheckBox.isChecked(); 
    } 

    public void setDetails(CharSequence details, CharSequence stretchedDetails) 
    { 
     if(details == null || details.length() == 0) 
     { 
      mDetails = ""; 
     }else 
     { 
      mDetails = details; 
     } 

     if(stretchedDetails == null) 
     { 
      mStretchedDetails = ""; 
     } 
     else 
     { 
      mStretchedDetails = stretchedDetails; 
     } 

     refreshStretched(); 
    } 

    public void setDetailsRight(CharSequence detailsRight, CharSequence expandedDetailsRight) 
    { 
     if(detailsRight == null || detailsRight.length() == 0) 
     { 
      mDetailsRight = ""; 
     }else 
     { 
      mDetailsRight = detailsRight; 
     } 

     if(expandedDetailsRight == null) 
     { 
      mStretchedDetailsRight = ""; 
     } 
     else 
     { 
      mStretchedDetailsRight = expandedDetailsRight; 
     } 

     refreshStretched(); 
    } 

    public void setStretched(boolean expanded) 
    { 
     mStretched = expanded; 
     refreshStretched(); 
    } 

    public boolean getStretched() 
    { 
     return mStretched; 
    } 

    public boolean toggleStretched() 
    { 
     setStretched(!getStretched()); 
     return mStretched; 
    } 

    public void showButtons() { 

     if(mButtonLayout.getVisibility() != VISIBLE) 
     { 
      Animation slideIn = AnimationUtils.loadAnimation(this.getContext(), R.anim.slideonfromright); 

      mButtonLayout.setAnimation(slideIn); 
      mButtonLayout.setVisibility(VISIBLE); 
      mButtonLayout.startAnimation(slideIn); 
     }  
    } 

    public void hideButtons() { 
     if(mButtonLayout != null && mButtonLayout.getVisibility() == VISIBLE) 
     { 
      Animation slideOut = AnimationUtils.loadAnimation(this.getContext(), R.anim.slideofftoright); 
      slideOut.setAnimationListener(new AnimationListener() 
      { 
       @Override 
       public void onAnimationEnd(Animation animation) { 
        mButtonLayout.setVisibility(GONE); 
       } 
       @Override 
       public void onAnimationRepeat(Animation animation) {} 
       @Override 
       public void onAnimationStart(Animation animation) { } 
      }); 

      mButtonLayout.startAnimation(slideOut); 
     } 
    } 


    public void hideButtons(boolean noAnimation) { 
     mButtonLayout.setVisibility(GONE); 
    } 

    public void refreshStretched() { 

     if(mStretched) 
     { 
      mDetailsRightTextView.setText(mStretchedDetailsRight); 
      mDetailsTextView.setText(mStretchedDetails); 
     }else 
     { 
      mDetailsRightTextView.setText(mDetailsRight); 
      mDetailsTextView.setText(mDetails); 
     } 

     if(mDetailsRightTextView.length() == 0) 
     { 

      mDetailsRightTextView.setVisibility(GONE); 
     }else 
     { 
      mDetailsRightTextView.setVisibility(VISIBLE); 
     } 

     if(mDetailsTextView.length() == 0) 
     { 
      mDetailsTextView.setVisibility(GONE); 
     }else 
     { 
      mDetailsTextView.setVisibility(VISIBLE); 
     } 
    } 
} 

noteview_layout.xml

<?xml version="1.0" encoding="utf-8"?> 
<merge xmlns:android="http://schemas.android.com/apk/res/android" > 
    <LinearLayout 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal" 
    android:paddingRight="5dip"> 
     <CheckBox android:id="@+id/noteViewCB" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content"/> 
     <TextView android:id="@+id/noteViewTitle" 
     android:layout_width="wrap_content" 
     android:layout_height="fill_parent" 
     android:layout_weight="1" 
     android:gravity="center_vertical" 
     android:text="Title"/> 
     <LinearLayout 
       android:id="@+id/noteViewButtonLayout" 
       android:orientation="horizontal" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:padding="5dip" 
       android:visibility="gone" 
       android:layout_gravity="center_vertical"> 
      <Button android:id="@+id/noteViewEditButton" 
        android:layout_width="80dp" 
        android:layout_height="fill_parent" 
        android:background="@drawable/drawngreenbutton" 
        android:textStyle="bold" 
        android:text="Edit"/> 
      <Button android:id="@+id/noteViewDeleteButton" 
        android:layout_width="80dp" 
        android:layout_height="fill_parent" 
        android:background="@drawable/drawnredbutton" 
        android:textStyle="bold" 
        android:text="Delete"/> 
     </LinearLayout> 
    </LinearLayout> 
    <LinearLayout android:orientation="horizontal" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"> 
    <TextView android:id="@+id/noteViewDetails" 
    android:layout_width="0dip" 
    android:layout_height="wrap_content" 
    android:layout_weight="2" 
    android:layout_marginRight="10dip" 
    android:visibility="gone" 
    android:focusable="false" 
    android:bufferType="spannable"/> 
    <TextView 
    android:id="@+id/noteViewDetailsRight" 
    android:layout_width="0dip" 
    android:layout_height="wrap_content" 
    android:layout_weight="1" 
    android:visibility="gone" 
    android:focusable="false" 
    android:bufferType="spannable" 
    android:gravity="right"/></LinearLayout> 
</merge> 

Répondre

2

J'ai eu un problème similaire qui happends lorsque l'utilisation d'une case à cocher est dans la mise en page des articles de ListView. S'il vous plaît vérifier si l'ajout de l'attribut: android: focusable = « false » à la définition de case à cocher vous aide aime:

<CheckBox android:id="@+id/noteViewCB" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:focusable="false" /> 

La question semble être que Android ne vous permet pas de sélectionner des éléments de liste qui ont éléments sur eux qui sont focalisables.

Best,

+0

J'ai eu le même problème beaucoup plus tôt dans le développement et avait découvert que focusable = "false" était la solution. Ensuite, j'ai changé la mise en page à ma vue personnalisée au lieu d'une mise en page XML directe et j'ai oublié de le faire à nouveau dans toutes mes expériences. J'avais essayé de bloquer la focalisation des descendants via XML, mais je ne suis jamais allé sur les boutons individuels pour le contrôle de la mise au point. Merci, a parfaitement fonctionné. – CodeFusionMobile