Отключить изменения состояния в представлениях в ExpandableListView при нажатии на них

Задний план

когда вы создаете свои собственные пользовательские представления для listView, вы можете иметь флажок (или любое другое представление, которое имеет «state_pressed» для его рисования) внутри, которое будет отображаться только как затронутое только тогда, когда оно действительно нажато, вместо нажатия в любом месте строки listView.

Способ сделать это для listView - просто использовать следующий код на его адаптере (как показано здесь ):

public boolean isEnabled(int position) 
  { 
  return false; 
  } 

Эта проблема

это решение не работает для ExpandableListView, так как у него нет этой функции.

Не только это, но я думаю, что любой щелчок по элементам в ExpandableListView (даже тем, которые не расширяются) вызовет notifyDataSetChanged (или макет, который его запускает).

Почему это происходит?

Что я пробовал

Я пытался использовать " isChildSelectable", " areAllItemsEnabled", "setClickable" и даже "duplicateParentState" . Ни одно из этих решений не помогло.

Вопрос

Каков наилучший способ установить флажок в строках и разрешить только им обрабатывать эффекты касания на себе?

Кроме того, почему щелчок по элементам (даже без дочерних элементов) вызывает обновление всего ExpandableListView?


person android developer    schedule 11.12.2013    source источник


Ответы (1)


Если я правильно понял, вы хотите иметь флажок в каждой родительской строке ExpandableListView. Я делал что-то подобное раньше (не используя флажки, а кнопки), и мне пришлось реализовать собственный адаптер. Это будет что-то вроде этого:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class ExpandableListTest extends BaseExpandableListAdapter {
private Context context;
private List<String> _listDataHeader; // header titles
// child data in format of header title, child title
private HashMap<String, List<String>> _listDataChild;

public ExpandableListTest(Context context) {
    this.context = context;
}

@Override
public Object getChild(int groupPosition, int childPosititon) {
    if (_listDataChild != null) {
        return this._listDataChild.get(
                this._listDataHeader.get(groupPosition))
                .get(childPosititon);
    } else {
        return null;
    }
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

@Override
public View getChildView(int groupPosition, final int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {

    final int position = groupPosition;
    final String childText = (String) getChild(groupPosition, childPosition);

    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this.context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.child_layout, null);
    }

    TextView txtListChild = (TextView) convertView.findViewById(R.id.text);

    txtListChild.setText(childText);

    convertView.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View arg0) {
            // do something
        }
    });

    return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {
    if (_listDataChild == null) {
        return 0;
    } else {
        return this._listDataChild.get(
                this._listDataHeader.get(groupPosition)).size();
    }
}

@Override
public Object getGroup(int groupPosition) {
    if (_listDataHeader == null) {
        return null;
    } else {
        return this._listDataHeader.get(groupPosition);
    }

}

@Override
public int getGroupCount() {
    if (_listDataHeader == null) {
        return 1;
    } else {
        return this._listDataHeader.size();
    }

}

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public View getGroupView(int pos, boolean isExpanded, View view,
        ViewGroup parent) {

    if (view == null) {
        LayoutInflater infalInflater = (LayoutInflater) this.context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = infalInflater.inflate(R.layout.layout_with_checkbox, null);
    }
    getGroup(pos);

    CheckBox checkBox=(CheckBox)view.findViewById(R.id.checkBox);
    checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
            if(arg1){
                //the checkBox is checked
            }
        }
    });

    return view;
}

@Override
public boolean hasStableIds() {
    return false;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return false;
}

}

Если вы хотите установить флажок в дочерней строке, просто поменяйте местами код и макеты, используемые в getGroupView() и getChildView().

Родительский макет xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft="10dp"
        android:paddingRight="10dp" >

        <CheckBox
            android:id="@+id/checkBox"
            android:layout_width="30dp"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="40dp"
            android:layout_toRightOf="@+id/imageView1"
            android:text="Text goes here"
            android:textSize="18sp" />
    </RelativeLayout>

</LinearLayout>
person RominaV    schedule 11.12.2013
comment
Флажки обрабатывают только события касания на себе? - person RominaV; 11.12.2013
comment
в моем случае они на самом деле являются проверяемыми изображениями (но это произойдет для любого проверяемого представления с чертежами с состоянием нажатия), и я использую для них setOnClickListener. проблема в том, что когда вы касаетесь самой строки, кажется, что вы тоже касаетесь их, поэтому они получают эффект от их рисования для state_pressed . - person android developer; 11.12.2013
comment
Вы пробовали этот код? Я только что проверил его снова, и он работает нормально. Я не использовал Checkable ImageView, но протестировал его с флажком, переключателем и обоими стилями с возможностью рисования для нажатого состояния. Они не реагируют на события касания в строке. - person RominaV; 11.12.2013
comment
Хорошо, я попробовал ваш образец (и, кстати, вы написали layout_with_checkbox вместо parent_layout.xml). у него есть проблема: он не позволяет отображать какое-либо влияние на выбранный элемент. это означает, что если вы щелкнете где-нибудь, кроме флажка, вы не получите никаких указаний на то, что его коснулись. не только это, но даже несмотря на то, что я добавил несколько элементов в вашу хэш-карту, похоже, это не позволяет расширять строки, чтобы показать их. как будто касание полностью заблокировано, кроме флажков... - person android developer; 12.12.2013