ExpandableListView onChildClick 不触发(在 master/detail 流程中)
ExpandableListView onChildClick doesn't fire (in master/detail flow)
我知道很多人都问过类似的问题,但是 none 他们的解决方案对我有用。
我有一个 master/detail 流 ,expandable list
作为 list
。我可以单击组并展开它们,但是 我无法单击 children.
我已将它们设置为可选(起初我认为这是问题所在),它们上面没有任何 checkboxes
或图像,只有纯文本。我什至将该文本设置为不是 focusable
(因为可聚焦元素似乎是其他人的问题)。
这是我拥有的:
自定义 BaseExpandableAdapter
:
public class CabinetAndRacksExpandAdapter extends BaseExpandableListAdapter {
//(some fields that probably aren't relevant)
@Override
public int getGroupCount() {
return cabinets.size();
}
(more override methods here, probably not relevant)
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.listrow_cabinet, null);
}
Cabinet cabinet = (Cabinet) getGroup(groupPosition);
((CheckedTextView) convertView).setText(cabinet.toString());
((CheckedTextView) convertView).setChecked(isExpanded);
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
final Rack rack = (Rack) getChild(groupPosition, childPosition);
TextView text = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.listrow_rack, null);
}
final View view = convertView;
text = (TextView) convertView.findViewById(R.id.textView1);
text.setText(rack.toString());
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
我还有一个fragment
(master/detail流程中的列表片段)。它应该监听 child 和组的点击,所以它实现了那些 listeners
:
public class CabinetListFragment extends Fragment implements ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupClickListener{
//(some stuff that's probably not relevant)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_cabinet_list, container, false);
listView = (ExpandableListView) rootView;
listView.setOnChildClickListener(this);
listView.setOnGroupClickListener(this);
Bundle extras = getActivity().getIntent().getExtras();
if(extras != null)
{
String orderId = extras.getString(CabinetListActivity.ARG_ORDER_ID);
order = service.getOrderFromId(service.intFromString(orderId));
}
CabinetAndRacksExpandAdapter adapter = new CabinetAndRacksExpandAdapter(getActivity(), service.getCabinetsForOrder(order));
listView.setAdapter(adapter);
return rootView;
}
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Log.d("CabinetListFragment", "onChildClick");
mCallbacks.onChildSelected(groupPosition, childPosition);
return true;
}
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id)
{
Log.d("CabinetListFragment", "onGroupClick");
mCallbacks.onGroupSelected(groupPosition);
return false;
}
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onChildSelected(int groupPosition, int childPosition);
public void onGroupSelected(int groupPosition);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
}
此片段属于 Activity,它按应有的方式实现了回调:
public class CabinetListActivity extends FragmentActivity
implements CabinetListFragment.Callbacks{
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
public static final String ARG_ORDER_ID = "order_id";
private Service service;
private Order order;
private String orderId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cabinet_list);
service = Service.getInstance();
if (findViewById(R.id.cabinet_detail_container) != null) {
mTwoPane = true;
}
Bundle extras = getIntent().getExtras();
if(extras != null)
{
String orderId = extras.getString(ARG_ORDER_ID);
order = service.getOrderFromId(service.intFromString(orderId));
this.orderId = orderId;
}
}
/**
* Callback method from {@link CabinetListFragment.Callbacks}
* indicating which item was selected.
*/
@Override
public void onChildSelected(int groupPosition, int childPosition) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(CabinetDetailFragment.ARG_CHILD_ID, childPosition+"");
arguments.putString(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
arguments.putBoolean(CabinetDetailFragment.ARG_RACKMODE, true);
CabinetDetailFragment fragment = new CabinetDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.cabinet_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Log.d("CabinetListActivity", "show rack");
Intent detailIntent = new Intent(this, CabinetDetailActivity.class);
detailIntent.putExtra(CabinetDetailFragment.ARG_CHILD_ID, childPosition + "");
detailIntent.putExtra(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
detailIntent.putExtra(CabinetDetailFragment.ARG_RACKMODE, true);
startActivity(detailIntent);
}
}
@Override
public void onGroupSelected(int groupPosition) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
arguments.putString(CabinetDetailFragment.ARG_ORDER_ID, orderId);
arguments.putBoolean(CabinetDetailFragment.ARG_RACKMODE, false);
CabinetDetailFragment fragment = new CabinetDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.cabinet_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, CabinetDetailActivity.class);
detailIntent.putExtra(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
detailIntent.putExtra(CabinetDetailFragment.ARG_ORDER_ID, orderId);
detailIntent.putExtra(CabinetDetailFragment.ARG_RACKMODE, false);
startActivity(detailIntent);
}
}
//(more stuff that's probably not relevant)
}
我看不出我的 childClick
事件与 GroupClick
事件有何不同。
如前所述,GroupClick
触发并按预期处理,但 childClick
甚至没有触发(我已经尝试从片段中的 onChildClick 登录)。
顺便说一句,该方法 return 是真还是假似乎没有任何区别(自然地,因为它从未被调用过)。
我试过直接在 childView 上创建一个侦听器,这很有效。但是我需要在片段或 activity(最好是 activity(最好是 activity,但它应该是监听事件的片段)中做一些事情,这样就不行了。
为什么我的 fragment
在注册为 listener
时没有收到 onChildClick
事件的通知?该事件是否由于某种原因从未被解雇过?还是在别处处理?
也许,你正在尝试做的是类似这样的事情:
public class FaltasFragmentActivity extends Activity {
//Lista de faltas
private ExpandableListView mExpandalbeView;
private ExpandableListAdapter listAdapter;
private int posicion;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conduccion_faltas);
mExpandalbeView = (ExpandableListView) findViewById(R.id.expandable_faltas);
mExpandalbeView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
// Codigo para cerra el ultiom grupo abierto antes de abrir el nuevo
Toast.makeText(FaltasFragmentActivity.this, "pulsado group: " + groupPosition, Toast.LENGTH_SHORT).show();
return false;
}
});
// Listview on child click listener
mExpandalbeView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
Toast.makeText(FaltasFragmentActivity.this, "pulsado child: (" + groupPosition + ", " + childPosition + ")", Toast.LENGTH_SHORT).show();
return false;
}
});
// Listview Group expanded listener
mExpandalbeView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
Toast.makeText(FaltasFragmentActivity.this, "pulsado expand", Toast.LENGTH_SHORT).show();
}
});
// Listview Group collasped listener
mExpandalbeView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int groupPosition) {
Toast.makeText(FaltasFragmentActivity.this, "pulsado collapse", Toast.LENGTH_SHORT).show();
}
});
listAdapter = new ExpandableListAdapter(FaltasFragmentActivity.this, root, posicion, filtroBusqueda);
mExpandalbeView.setAdapter(listAdapter);
}
}
其中 ExpandableListAdapter(...)
是:
public class ExpandableListAdapter extends BaseExpandableListAdapter{...}
这对我有用!
希望这对您有所帮助!
只是瞎猜,但是你在那些不相关的方法中实现了吗
int getChildrenCount(int groupPosition) {
// Return whatever the children's count is
}
和
public boolean areAllItemsEnabled() {
return true;
}
在布局 XML R.layout.listrow_rack 中,您有没有禁用该项目,或者关联一个静默触发的点击侦听器?
好的,这就是问题所在:
这是我的 listrow_rack:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="40dp"
android:clickable="true"
android:orientation="vertical"
android:paddingLeft="40dp"
tools:context=".OrdreDetailActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:text="@string/hello_world"
android:textSize="14sp"
android:textStyle="bold">
</TextView>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/black" />
问题出在这一行:
android:clickable="true"
我不确定为什么,但也许它添加了一个侦听器,或者可能出于其他原因。但是当我删除它时,它起作用了。
支持 Andras Baláz Lathja 为我指明了正确的方向。
我知道很多人都问过类似的问题,但是 none 他们的解决方案对我有用。
我有一个 master/detail 流 ,expandable list
作为 list
。我可以单击组并展开它们,但是 我无法单击 children.
我已将它们设置为可选(起初我认为这是问题所在),它们上面没有任何 checkboxes
或图像,只有纯文本。我什至将该文本设置为不是 focusable
(因为可聚焦元素似乎是其他人的问题)。
这是我拥有的:
自定义 BaseExpandableAdapter
:
public class CabinetAndRacksExpandAdapter extends BaseExpandableListAdapter {
//(some fields that probably aren't relevant)
@Override
public int getGroupCount() {
return cabinets.size();
}
(more override methods here, probably not relevant)
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.listrow_cabinet, null);
}
Cabinet cabinet = (Cabinet) getGroup(groupPosition);
((CheckedTextView) convertView).setText(cabinet.toString());
((CheckedTextView) convertView).setChecked(isExpanded);
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
final Rack rack = (Rack) getChild(groupPosition, childPosition);
TextView text = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.listrow_rack, null);
}
final View view = convertView;
text = (TextView) convertView.findViewById(R.id.textView1);
text.setText(rack.toString());
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
我还有一个fragment
(master/detail流程中的列表片段)。它应该监听 child 和组的点击,所以它实现了那些 listeners
:
public class CabinetListFragment extends Fragment implements ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupClickListener{
//(some stuff that's probably not relevant)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_cabinet_list, container, false);
listView = (ExpandableListView) rootView;
listView.setOnChildClickListener(this);
listView.setOnGroupClickListener(this);
Bundle extras = getActivity().getIntent().getExtras();
if(extras != null)
{
String orderId = extras.getString(CabinetListActivity.ARG_ORDER_ID);
order = service.getOrderFromId(service.intFromString(orderId));
}
CabinetAndRacksExpandAdapter adapter = new CabinetAndRacksExpandAdapter(getActivity(), service.getCabinetsForOrder(order));
listView.setAdapter(adapter);
return rootView;
}
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Log.d("CabinetListFragment", "onChildClick");
mCallbacks.onChildSelected(groupPosition, childPosition);
return true;
}
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id)
{
Log.d("CabinetListFragment", "onGroupClick");
mCallbacks.onGroupSelected(groupPosition);
return false;
}
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onChildSelected(int groupPosition, int childPosition);
public void onGroupSelected(int groupPosition);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
}
此片段属于 Activity,它按应有的方式实现了回调:
public class CabinetListActivity extends FragmentActivity
implements CabinetListFragment.Callbacks{
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
public static final String ARG_ORDER_ID = "order_id";
private Service service;
private Order order;
private String orderId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cabinet_list);
service = Service.getInstance();
if (findViewById(R.id.cabinet_detail_container) != null) {
mTwoPane = true;
}
Bundle extras = getIntent().getExtras();
if(extras != null)
{
String orderId = extras.getString(ARG_ORDER_ID);
order = service.getOrderFromId(service.intFromString(orderId));
this.orderId = orderId;
}
}
/**
* Callback method from {@link CabinetListFragment.Callbacks}
* indicating which item was selected.
*/
@Override
public void onChildSelected(int groupPosition, int childPosition) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(CabinetDetailFragment.ARG_CHILD_ID, childPosition+"");
arguments.putString(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
arguments.putBoolean(CabinetDetailFragment.ARG_RACKMODE, true);
CabinetDetailFragment fragment = new CabinetDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.cabinet_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Log.d("CabinetListActivity", "show rack");
Intent detailIntent = new Intent(this, CabinetDetailActivity.class);
detailIntent.putExtra(CabinetDetailFragment.ARG_CHILD_ID, childPosition + "");
detailIntent.putExtra(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
detailIntent.putExtra(CabinetDetailFragment.ARG_RACKMODE, true);
startActivity(detailIntent);
}
}
@Override
public void onGroupSelected(int groupPosition) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
arguments.putString(CabinetDetailFragment.ARG_ORDER_ID, orderId);
arguments.putBoolean(CabinetDetailFragment.ARG_RACKMODE, false);
CabinetDetailFragment fragment = new CabinetDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.cabinet_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, CabinetDetailActivity.class);
detailIntent.putExtra(CabinetDetailFragment.ARG_GROUP_ID, groupPosition+"");
detailIntent.putExtra(CabinetDetailFragment.ARG_ORDER_ID, orderId);
detailIntent.putExtra(CabinetDetailFragment.ARG_RACKMODE, false);
startActivity(detailIntent);
}
}
//(more stuff that's probably not relevant)
}
我看不出我的 childClick
事件与 GroupClick
事件有何不同。
如前所述,GroupClick
触发并按预期处理,但 childClick
甚至没有触发(我已经尝试从片段中的 onChildClick 登录)。
顺便说一句,该方法 return 是真还是假似乎没有任何区别(自然地,因为它从未被调用过)。
我试过直接在 childView 上创建一个侦听器,这很有效。但是我需要在片段或 activity(最好是 activity(最好是 activity,但它应该是监听事件的片段)中做一些事情,这样就不行了。
为什么我的 fragment
在注册为 listener
时没有收到 onChildClick
事件的通知?该事件是否由于某种原因从未被解雇过?还是在别处处理?
也许,你正在尝试做的是类似这样的事情:
public class FaltasFragmentActivity extends Activity {
//Lista de faltas
private ExpandableListView mExpandalbeView;
private ExpandableListAdapter listAdapter;
private int posicion;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conduccion_faltas);
mExpandalbeView = (ExpandableListView) findViewById(R.id.expandable_faltas);
mExpandalbeView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
// Codigo para cerra el ultiom grupo abierto antes de abrir el nuevo
Toast.makeText(FaltasFragmentActivity.this, "pulsado group: " + groupPosition, Toast.LENGTH_SHORT).show();
return false;
}
});
// Listview on child click listener
mExpandalbeView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
Toast.makeText(FaltasFragmentActivity.this, "pulsado child: (" + groupPosition + ", " + childPosition + ")", Toast.LENGTH_SHORT).show();
return false;
}
});
// Listview Group expanded listener
mExpandalbeView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
Toast.makeText(FaltasFragmentActivity.this, "pulsado expand", Toast.LENGTH_SHORT).show();
}
});
// Listview Group collasped listener
mExpandalbeView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int groupPosition) {
Toast.makeText(FaltasFragmentActivity.this, "pulsado collapse", Toast.LENGTH_SHORT).show();
}
});
listAdapter = new ExpandableListAdapter(FaltasFragmentActivity.this, root, posicion, filtroBusqueda);
mExpandalbeView.setAdapter(listAdapter);
}
}
其中 ExpandableListAdapter(...)
是:
public class ExpandableListAdapter extends BaseExpandableListAdapter{...}
这对我有用! 希望这对您有所帮助!
只是瞎猜,但是你在那些不相关的方法中实现了吗
int getChildrenCount(int groupPosition) {
// Return whatever the children's count is
}
和
public boolean areAllItemsEnabled() {
return true;
}
在布局 XML R.layout.listrow_rack 中,您有没有禁用该项目,或者关联一个静默触发的点击侦听器?
好的,这就是问题所在:
这是我的 listrow_rack:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="40dp"
android:clickable="true"
android:orientation="vertical"
android:paddingLeft="40dp"
tools:context=".OrdreDetailActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:text="@string/hello_world"
android:textSize="14sp"
android:textStyle="bold">
</TextView>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/black" />
问题出在这一行:
android:clickable="true"
我不确定为什么,但也许它添加了一个侦听器,或者可能出于其他原因。但是当我删除它时,它起作用了。
支持 Andras Baláz Lathja 为我指明了正确的方向。