我有ExpandableListView
,我需要在Button
点击时添加特定childView中放置按钮的新视图元素。
为此,我创建了一个TableLayout
,其中放置了一个行,其中包含我需要在子视图中添加的视图元素。
这是我的孩子布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:paddingTop="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="@color/ColorPrimary"
android:labelFor="@+id/time_stamp_view"
android:textSize="20sp"
android:text="@string/info_action_name"
android:layout_marginRight="12dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="24dp"
android:id="@+id/action_text"/>
<Spinner
android:id="@+id/spinnerAction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/action_text"
android:layout_marginRight="24dp"
android:layout_alignBottom="@+id/action_text"
android:layout_alignTop="@+id/action_text"/>
<TableLayout
android:id="@+id/tableTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_below="@+id/action_text"
android:layout_alignStart="@+id/date_text"
android:layout_marginBottom="8dp">
</TableLayout>
<!-- This imageview is the "button" to click -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/addTimeImageView"
android:layout_below="@+id/tableTime"
android:src="@drawable/ic_time_add"
android:layout_centerHorizontal="true"
android:contentDescription="@string/info_add_time_image"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="@color/ColorPrimary"
android:textSize="20sp"
android:text="@string/info_date1"
android:layout_marginRight="12dp"
android:layout_marginLeft="0dp"
android:id="@+id/date_text"
android:layout_below="@+id/addTimeImageView"
android:layout_alignStart="@+id/date2_text"
android:layout_marginTop="16dp"/>
</RelativeLayout>
这是我的自定义适配器:
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> expandableListTitle;
private HashMap<String, List<Action>> expandableListDetail;
private LayoutInflater layoutInflater;
private int mViewResourceId;
private int k = 0;
public ExpandableListAdapter(Context context, List<String> expandableListTitle,
HashMap<String, List<Action>> expandableListDetail,
int viewResourceId) {
this.context = context;
this.expandableListTitle = expandableListTitle;
this.expandableListDetail = expandableListDetail;
this.mViewResourceId = viewResourceId;
this.layoutInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public Object getChild(int listPosition, int expandedListPosition) {
return this.expandableListDetail.get(this.expandableListTitle.get(listPosition))
.get(expandedListPosition);
}
// @Override
// public int getChildTypeCount(){
// return 2;
// }
// @Override
// public int getChildType(int groupPosition, int childPosition)
// {
// return expandableListDetail.get(this.expandableListTitle.get(groupPosition))
// .get(childPosition).getId();
// }
@Override
public long getChildId(int listPosition, int expandedListPosition) {
return expandedListPosition;
}
@Override
public View getChildView(final int listPosition, final int expandedListPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final Action expandedListAction = (Action) getChild(listPosition, expandedListPosition);
ViewHolder holder;
ArrayAdapter<CharSequence> adapterAction = null;
String[] timeSlot;
if (convertView == null) {
convertView = layoutInflater.inflate(mViewResourceId, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder)convertView.getTag();
if(expandedListAction.getId() == 1)
adapterAction = ArrayAdapter.createFromResource(context, R.array.actionId1, R.layout.spinner_item);
else if(expandedListAction.getId() == 20)
adapterAction = ArrayAdapter.createFromResource(context, R.array.actionId20, R.layout.spinner_item);
if(adapterAction != null)
adapterAction.setDropDownViewResource(R.layout.dropdown_list_spinner);
holder.spinnerAction.setAdapter(adapterAction);
ArrayAdapter<?> adapter = (ArrayAdapter<?>)holder.spinnerAction.getAdapter();
for(Map.Entry<String, String[]> entry : expandedListAction.getActionToPerform().entrySet()){
holder.spinnerAction.setSelection(((ArrayAdapter<CharSequence>)adapter).getPosition(entry.getKey()));
timeSlot = entry.getValue();
//Here i add row to table dinamically, according to data passed to adapter
//why if add row when inflate layout, the adapter don't do that for each childView because convertview is not null for every child.
// I can't override getChildTypeCount() because every view is different, not just few.
for (int t = 0; t < timeSlot.length; t++) {
TableRow timeRow = new TableRow(context);
layoutInflater.inflate(R.layout.time_layout, timeRow, true);
EditText timeText = (EditText) timeRow.findViewById(R.id.timeText);
timeText.setText(timeSlot[t]);
holder.tableTime.addView(timeRow);
}
}
}
return convertView;
}
@Override
public int getChildrenCount(int listPosition) {
return this.expandableListDetail.get(this.expandableListTitle.get(listPosition))
.size();
}
@Override
public Object getGroup(int listPosition) {
return this.expandableListTitle.get(listPosition);
}
@Override
public int getGroupCount() {
return this.expandableListTitle.size();
}
@Override
public long getGroupId(int listPosition) {
return listPosition;
}
@Override
public View getGroupView(int listPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String listTitle = (String) getGroup(listPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_group, null);
}
TextView listTitleTextView = (TextView) convertView
.findViewById(R.id.listTitle);
listTitleTextView.setText(listTitle);
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int listPosition, int expandedListPosition) {
return true;
}
static class ViewHolder {
@Bind(R.id.spinnerAction)
Spinner spinnerAction;
@Bind(R.id.addTimeImageView)
ImageView imageTimeView;
@Bind(R.id.tableTime)
TableLayout tableTime;
public ViewHolder(View view){ButterKnife.bind(this, view);}
}
}
这段代码工作得很好,但是我需要在Imageview
上添加一个在表中添加新行的监听器。我尝试这样做(我在getView中添加了这段代码):
holder.imageTimeView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ViewGroup parent = (ViewGroup)v.getParent();
Action azione1 = expandableListDetail.get(expandableListTitle.get(listPosition)).get(expandedListPosition);
String actionType = null;
for(Map.Entry<String, String[]> entry : azione1.getActionToPerform().entrySet()) {
actionType = entry.getKey();
}
Action azione2 = new Action();
azione2.setId(azione1.getId());
azione2.setGroupAddress(azione1.getGroupAddress());
azione2.setWeekDay(azione1.getWeekDay());
Map<String, String[]> actionPerform = azione1.getActionToPerform();
String[] time = actionPerform.get(actionType);
String[] time2 = new String[time.length+1];
time2[0] = "New time"+k;
k++;
for(int t=0; t<time.length; t++)
time2[t+1] = time[t];
Map<String, String[]> actionToPerform2 = new HashMap<>();
actionToPerform2.put(actionType, time2);
azione2.setActionToPerform(actionToPerform2);
//When i call updateAction, i update the HashMap expandableListDetail passed from ModifyScenarioActivity when i set the adapter,
//and then i call notifyDataSetChanged() on ExpandableListView adapter.
((ModifyScenarioActivity)context).updateAction(azione1, azione2, expandableListTitle.get(listPosition));
TableLayout table = (TableLayout)parent.findViewById(R.id.tableTime);
table.invalidate();
table.refreshDrawableState();
}
});
此侦听器不起作用,因为它在表中添加了新行,但是相同的行被多次添加到其他子表的其他表中。 任何人都可以帮我处理这种情况吗?我不知道如何解决它。其他方法也很受欢迎。
修改
我添加了这个声明:
if(holder.tableTime.getChildCount() < timeSlot.length) {
holder.tableTime.removeAllViews();
// for (int t = 0; t < timeSlot.length; t++) {
//
// TableRow timeRow = new TableRow(context);
//
// layoutInflater.inflate(R.layout.time_layout, timeRow, true);
//
// EditText timeText = (EditText) timeRow.findViewById(R.id.timeText);
// timeText.setText(timeSlot[t]);
//
// holder.tableTime.addView(timeRow);
// }
}
现在表格已刷新,但在其他子视图的另一个表格中,显示修改后的子视图的同一行,但我无法解释为什么在填充expandedListAction
时使用getChild()
进行调用在不同的listPosition和expandedListPosition
上。我在调试器中发现数据没问题。
修改
我解决了每次调用getView时删除问题,表中的所有行以及再次添加resresreshed数据的问题。所以我问我是否可以提高滚动性能,也许每次都不删除和刷新表。 这是解决方案:
holder.tableTime.removeAllViews();
for (int t = 0; t < timeSlot.length; t++) {
TableRow timeRow = new TableRow(context);
layoutInflater.inflate(R.layout.time_layout, timeRow, true);
EditText timeText = (EditText) timeRow.findViewById(R.id.timeText);
timeText.setText(timeSlot[t]);
holder.tableTime.addView(timeRow);
}