2012-11-29 21 views
11

まず、チェック可能なカスタムリスト項目とセレクタに関連するほとんどすべての質問を詳細に読んでいると言います。それらの多くはと同じようなの問題がありますが、私の問題を解決する答えはありません。カスタムリスト項目がセレクタでstate_checkedに応答していない

私のアプリのポイントでは、カスタムリストのアクティビティを提示します。作成されると、呼び出されたインテントから静的データのセットが取得され、そのデータがカスタムアレイアダプタに渡されます。各リストアイテムは、Checkableインターフェイスを実装する単純なRelativeLayoutです。デフォルトでは、アイテムの1つをクリックすると、選択した連絡先に関する詳細情報を表示する新しいアクティビティが表示されます。ただし、リスト内の項目を長押しすると、ActionModeが開始されます。この時点でリスト内の項目をクリックしても、詳細アクティビティは表示されず、チェックされる項目が設定されます。次に、ユーザーがアクションモード項目の1つを選択すると、チェックされた項目に対してアクションが実行されます。

重要なことは、どちらの選択モードでも、リスト項目をクリックするとチェックされるということです。

上記のすべてが完全に機能します。私のの問題は、デフォルトのセレクタを使用していても、チェックされているときにリスト項目の背景が強調表示されないという問題があります。

私がしたいことは、選択モードごとに2つのセレクタがあります。最初の項目では、項目がチェックされても背景は変更されず、2番目の項目では背景が変更されません。私はカスタムセレクタを実装しようとしましたが、それらのstate_checkedでも無視されます!セレクタの他の部分は正常に動作しますが、state_checkedは動作しません。

CheckableListItemの実装にはさまざまな例のアイデアが組み込まれていますので、私が何か間違っているとか、もっと良い方法があれば教えてください!

:面白いポイントは項目がチェックされたときに背景変更を行う代わりに、リストビューのlistSelectorプロパティの、私は私のセレクタにresults_list_item.xmlのリスト項目の背景を設定した場合ということです。しかし、これを実行すると、セレクタの長押し遷移が機能しなくなります。

ResultsActivity.java

public class ResultsActivity extends ListActivity implements OnItemLongClickListener { 

    private ListView listView;   // Reference to the list belonging to this activity 
    private ActionMode mActionMode;  // Reference to the action mode that can be started 
    private boolean selectionMode;  // Detail mode or check mode 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_results); 

     // When the home icon is pressed, go back 
     ActionBar actionBar = getActionBar(); 
     actionBar.setDisplayHomeAsUpEnabled(true); 

     // Get a reference to the list 
     listView = getListView(); 

     // Initially in detail mode 
     selectionMode = true; 

     // Get the contacts from the intent data and pass them to the contact adapter 
     @SuppressWarnings("unchecked") 
     ArrayList<Contact> results = ((ArrayList<Contact>)getIntent().getSerializableExtra("results")); 
     Contact[] contacts = new Contact[results.size()]; 
     ContactArrayAdapter adapter = new ContactArrayAdapter(this, results.toArray(contacts)); 
     setListAdapter(adapter); 

     // We will decide what happens when an item is long-clicked 
     listView.setOnItemLongClickListener(this); 
    } 

    /** 
    * If we are in detail mode, when an item in the list is clicked 
    * create an instance of the detail activity and pass it the 
    * chosen contact 
    */ 
    public void onListItemClick(ListView l, View v, int position, long id) { 
     if (selectionMode) { 
      Intent displayContact = new Intent(this, ContactActivity.class); 
      displayContact.putExtra("contact", (Contact)l.getAdapter().getItem(position)); 
      startActivity(displayContact); 
     } 
    } 

    public boolean onCreateOptionsMenu(Menu menu) { 
     return super.onCreateOptionsMenu(menu); 
    } 

    /** 
    * If the home button is pressed, go back to the 
    * search activity 
    */ 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case android.R.id.home: 
       Intent intent = new Intent(this, SearchActivity.class); 
       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
       startActivity(intent); 
       return true; 
      default: 
       return super.onOptionsItemSelected(item); 
     } 
    } 

    /** 
    * When an item is long-pressed, switch selection modes 
    * and start the action mode 
    */ 
    public boolean onItemLongClick(AdapterView<?> adapter, View view, int position, long i) { 
     if (mActionMode != null) 
      return false; 

     if (selectionMode) { 
      toggleSelectionMode(); 
      listView.startActionMode(new ListActionMode(this, getListView())); 
      return true; 
     } 
     return false; 
    } 

    /** 
    * Clear the list's checked items and switch selection modes 
    */ 
    public void toggleSelectionMode() { 
     listView.clearChoices(); 
     ((ContactArrayAdapter)listView.getAdapter()).notifyDataSetChanged(); 
     if (selectionMode) { 
      selectionMode = false; 
     } else { 
      selectionMode = true; 
     } 
    } 
} 

activity_results.xml

<ListView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/list" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:choiceMode="multipleChoice" 
    android:listSelector="@drawable/list_selector" /> 

list_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android" > 
    <item android:state_pressed="true" android:drawable="@drawable/blue_transition" /> 
    <item android:state_checked="true" android:drawable="@drawable/blue" /> 
</selector> 

TwoLineArrayAdapter

public abstract class TwoLineArrayAdapter extends ArrayAdapter<Contact> { 

    private int mListItemLayoutResId; 

    public TwoLineArrayAdapter(Context context, Contact[] results) { 
     this(context, R.layout.results_list_item, results); 
    } 

    public TwoLineArrayAdapter(Context context, int listItemLayoutResourceId, Contact[] results) { 
     super(context, listItemLayoutResourceId, results); 
     mListItemLayoutResId = listItemLayoutResourceId; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 

     LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

     View listItemView = convertView; 
     if (convertView == null) { 
      listItemView = inflater.inflate(mListItemLayoutResId, parent, false); 
     } 

     // Get the text views within the layout 
     TextView lineOneView = (TextView)listItemView.findViewById(R.id.results_list_item_textview1); 
     TextView lineTwoView = (TextView)listItemView.findViewById(R.id.results_list_item_textview2); 

     Contact c = (Contact)getItem(position); 

     lineOneView.setText(lineOneText(c)); 
     lineTwoView.setText(lineTwoText(c)); 

     return listItemView; 
    } 

    public abstract String lineOneText(Contact c); 

    public abstract String lineTwoText(Contact c); 

} 

ContactArrayAdapter

public class ContactArrayAdapter extends TwoLineArrayAdapter { 

    public ContactArrayAdapter(Context context, Contact[] contacts) { 
     super(context, contacts); 
    } 

    public String lineOneText(Contact c) { 
     return (c.getLastName() + ", " + c.getFirstName()); 
    } 

    public String lineTwoText(Contact c) { 
     return c.getDepartment(); 
    } 

} 

CheckableListItem。Javaの

public class CheckableListItem extends RelativeLayout implements Checkable { 

    private boolean isChecked; 
    private List<Checkable> checkableViews; 

    public CheckableListItem(Context context, AttributeSet attrs, 
      int defStyle) { 
     super(context, attrs, defStyle); 
     initialise(attrs); 
    } 

    public CheckableListItem(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initialise(attrs); 
    } 

    public CheckableListItem(Context context, int checkableId) { 
     super(context); 
     initialise(null); 
    } 

    private void initialise(AttributeSet attrs) { 
     this.isChecked = false; 
     this.checkableViews = new ArrayList<Checkable>(5); 
    } 

    public boolean isChecked() { 
     return isChecked; 
    } 

    public void setChecked(boolean check) { 
     isChecked = check; 
     for (Checkable c : checkableViews) { 
      c.setChecked(check); 
     } 
     refreshDrawableState(); 
    } 

    public void toggle() { 
     isChecked = !isChecked; 
     for (Checkable c : checkableViews) { 
      c.toggle(); 
     } 
    } 

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

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

    protected void onFinishInflate() { 
     super.onFinishInflate(); 
     final int childCount = this.getChildCount(); 
     for (int i = 0; i < childCount; i++) { 
      findCheckableChildren(this.getChildAt(i)); 
     } 
    } 

    private void findCheckableChildren(View v) { 
     if (v instanceof Checkable) { 
      this.checkableViews.add((Checkable) v); 
     } 
     if (v instanceof ViewGroup) { 
      final ViewGroup vg = (ViewGroup) v; 
      final int childCount = vg.getChildCount(); 
      for (int i = 0; i < childCount; i++) { 
       findCheckableChildren(vg.getChildAt(i)); 
      } 
     } 
    } 
} 

results_list_item.xml

<com.test.mycompany.Widgets.CheckableListItem 
    android:id="@+id/results_list_item" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:paddingLeft="10dp" 
    android:paddingRight="10dp" 
    android:paddingTop="5dp" 
    android:paddingBottom="5dp" > 

    <TextView android:id="@+id/results_list_item_textview1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:textSize="20sp" 
     android:textColor="#000000" 
     android:focusable="false" /> 

    <TextView android:id="@+id/results_list_item_textview2" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_below="@id/results_list_item_textview1" 
     android:textSize="16sp" 
     android:textColor="@android:color/darker_gray" 
     android:focusable="false" /> 

</com.test.mycompany.Widgets.CheckableListItem> 
+0

あなたの商品をチェックしたり、チェックを外していますか?また、android:state_activitedで作業してみることもできます。 – DroidBender

+0

私はそれを自分でやっていません。しかし、彼らはチェックされています。私は、項目のsetCheckedメソッドにログステートメントを置くと、呼び出されていることがわかります。 – Groppe

+0

bgを直接設定したときに 'CheckableListItem'で' android:longClickable = true'を試してください。(注釈に指定されています) – Ronnie

答えて

0

は私が変更とCheckedListItemでこれらのメソッドを追加し、それが私のために働いています:

@Override 
public boolean onTouchEvent(MotionEvent event) { 

    int action = event.getAction() & MotionEvent.ACTION_MASK; 
    if (action == MotionEvent.ACTION_UP) { 
     toggle(); 
    } 

    return true; 
} 

public void toggle() { 

    setChecked(!isChecked()); 
} 

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

問題があることだったようですクリックでは、ビューのチェックされた状態を切り替えることは決してありませんでした。

+0

それは私のために働いていない...今アイテムをクリックすると何も起こらない。それらはあなたが変えた唯一のものですか?他の方法を削除しましたか? – Groppe

+0

いいえ、私はしませんでしたが、私も 'ListView'に入れませんでした。 ListViewにすべてのクリックを受け取るリスナーがあるため、ビューは決してタッチイベントを受け取りません。私が提案しているのは、選択モードを 'CHOICE_MODE_SINGLE'または' CHOICE_MODE_MULTIPLE'(いずれか必要なもの)に設定することです。これにより、リスト項目を選択できるようになります。したがって、 'CheckedListItem'クラスで' state_checked'ではなく 'state_selected'を使います。 –

0

まだ解決されていない場合は、セレクタと状態と色の定義を含むバックグラウンドドロワブルを「チェック可能なレイアウト」にしてみてください。それ以外の場合は、mBackgroundがnullであるためdrawableStateChangedは何も行いません。

次に、listview.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE)を使用して複数の項目を確認できるようにしてください(例:android:background = "@ drawable/list_selector")。

設定の選択モードが自動的に行われるため、項目を確認するためにsetOnItemClickListenerを実装する必要はありません。 (チェック可能なレイアウトをクリック可能にしないでください)

少なくとも、これは私が私の問題を解決する方法です。

関連する問題