我有一些麻烦:我有一个简单的GridView
,其中我有两类物品。我想为此GridView添加三个Menu Buttons
以获得Filter
,并为所选类别添加显示/隐藏项目。
对于该示例,使用以下图片,第一张图片代表我的简单GridView
和Button in ActionBar
。当我按下按钮时,SubMenu
显示三行,例如:“ All ”,“ Open ”& “闭”。当我按下“打开”按钮时,我只想显示类别为“打开”的项目:
我用Search Editext
为Filterable
找到了几件事,但我认为这不是实现我想要的好方法。我不需要TextView/EditText
作为过滤器,只需要ActionBar
中的按钮。
注意:我在使用@ana01's answer进行修改后更新了Adapter
。
似乎getView()
被调用太多了。我添加了3个Integers
来计算带有类别的项目数( nValues = total, nOpen = nb打开项目, nClosed =已结束项目的nb)。我使用 notifyDataSetChanged()来更新我的适配器。
这是Activity
我的BaseAdapter
:
public class MainActivity extends SherlockActivity {
ActionBar actionbar;
static GridView gridview;
static MyAdapter adapter;
String[] values = new String[] {
"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"
};
// 1 for Open items, 2 for Closed items
int[] vStatus = new int[] {
1, 2, 1, 2, 1
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridview = (GridView) findViewById(R.id.grid);
adapter = new MyAdapter(this);
gridview.setAdapter(adapter);
gridview.setOnItemClickListener(new OnItemClickListener() {
// new Intent to another Activity
// ...
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
return true;
}
// call an adapter method filterView()
// with the integer sort by category
// 0 = All items | 1 = Open | 2 = Closed
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
return false;
case R.id.action_listfilter_all :
adapter.filterView(0);
return true;
case R.id.action_listfilter_open :
adapter.filterView(1);
return true;
case R.id.action_listfilter_closed :
adapter.filterView(2);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public class MyAdapter extends BaseAdapter {
private Context mContext;
// Initialize the category's integer "visibleFlag"
private int visibleFlag = 0;
// Initialize the counters' categories
int nValues, nOpen, nClosed;
public MyAdapter(Context c) {
mContext = c;
}
// filterView method called by option selected item menu
public void filterView(int i) {
visibleFlag = i;
// refresh the content
notifyDataSetChanged();
/* gridview.invalidateViews(); */
}
protected class ViewHolder {
TextView text, view, like, user, coms;
ImageView imageview, imageflag;
}
// return the number of items regarding by category selected
public int getCount() {
switch(visibleFlag) {
case 0: nValues = values.length; break;
case 1: nValues = nOpen; break;
case 2: nValues = nClosed; break;
}
return nValues;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = ((MainActivity) mContext).getLayoutInflater();
convertView = inflater.inflate(R.layout.item_main, parent, false);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.text);
viewHolder.imageview = (ImageView) convertView.findViewById(R.id.image);
// set the tag of the category and
// augment the selected category (by + 1)
switch(vStatus[position]) {
case 1: viewHolder.imageview.setTag(1); nOpen++; break;
case 2: viewHolder.imageview.setTag(2); nClosed++; break;
}
// set the tag of the item's position
viewHolder.text.setTag(position);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// display the text with the position's tag
viewHolder.text.setText(values[(Integer) viewHolder.text.getTag()]);
// display the image with the position's tag
switch((Integer) viewHolder.imageview.getTag()) {
case 1: viewHolder.imageview.setImageResource(R.drawable.ic_open); break;
case 2: viewHolder.imageview.setImageResource(R.drawable.ic_closed); break;
}
return convertView;
}
}
}
但是这并没有显示所选类别的正确项目!
有人可以帮我搞清楚吗?
答案 0 :(得分:3)
您可能只需要前两行,因为如果已经设置了适配器,则gridView.setAdapter(adapter)
没有意义。
我认为您不需要AsynkTask来刷新您的集合,只需修改您的适配器以了解项类型:设置过滤器时(一个表示3种状态之一的整数: all ,关闭,打开),您的适配器应报告正确的计数并返回正确的项目(您可以使用3个不同的项目集合,尽管这意味着复制您的数据)
gridView.notifyDataChanged()
会在您的适配器中触发新的getCount()
调用,然后多次调用getView(..)
。 gridView.invalidateViews()
表示需要重新绘制子视图。您无需重新创建gridView。
如果您的项目看起来与您绘制的项目类似,我认为您可以使用ListView(使用相同的适配器)。
<强>更新强>:
如果getCount()
被多次调用,则可以,但是你应该避免在这种方法中执行繁重的任务(目前不是这种情况)。
在getView(..)
中,您应该提供与相应位置完全同步的视图,无论您是否重复使用以前创建的视图。所以问题是,只有在新创建(convertView==null)
时才更新视图,尽管您应该更新标题的文本和CO。在视图返回之前。
与您的“幽灵项目”相关,我不知道您的布局项目有多大,如果它们一次可见等,但您的适配器应创建至少与可见布局项目一样多的视图。
<强> UPDATE2 强>:
如下修改适配器,在适配器的构造函数中调用prepareData()
,看看它是否正常工作:
private ArrayList<Integer> closedIndexToRealIndex;
private ArrayList<Integer> openedIndexToRealIndex;
private void prepareData(){
nOpen = nClosed = 0;
closedIndexToRealIndex = new ArrayList<Integer>();
openedIndexToRealIndex = new ArrayList<Integer>();
for(int i = 0; i < values.count; i++){
if(vStatus[i] == 0){
openedInexToRealIndex.add(Integer.valueOf(i));
nOpen++;
}
else{
closedIndexToRealIndex.add(Integer.valueOf(i));
nClosed++;
}
}
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = ((MainActivity) mContext).getLayoutInflater();
convertView = inflater.inflate(R.layout.item_main, parent, false);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.text);
viewHolder.imageview = (ImageView) convertView.findViewById(R.id.image);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
int actualIndex = 0;
switch(visibleFlag){
case 0://all
actualIndex = position;
break;
case 1://opened
actualIndex = openedIndexToRealIndex.get(position).intValue();
break;
case 2://closed
actualIndex = closedIndexToRealIndex.get(position).intValue();
break;
default:
break;
}
viewHolder.text.setText(values[acutalIndex]);
if(vStatus[position] == 1)
viewHolder.imageview.setImageResource(R.drawable.ic_open);
else
viewHolder.imageview.setImageResource(R.drawable.ic_closed);
return convertView;
}