ListView 总是从 CustomAdaptor 中删除最后一行

Posted

技术标签:

【中文标题】ListView 总是从 CustomAdaptor 中删除最后一行【英文标题】:ListView always deletes last row from CustomAdaptor 【发布时间】:2020-02-05 23:10:09 【问题描述】:

我在 AlertDialog 中有一个 ListView,每行包含更多按钮,它会弹出一个带有删除选项的列表。当我单击删除选项时,它会删除最后一项。在 CustomAdaptor 中,我在从 ArrayList 中删除项目后尝试了 notifyDataSetChanged()。在这里,无论项目位置如何,它总是删除最后一个项目。

自定义适配器代码

public class CustomAdapter extends BaseAdapter 
Context context;
List<String> lrowItems ;
ArrayList<String> listItems;
String className;
CalHelper calHelper;
Settings settings;
LayoutInflater inflter;
public CustomAdapter(Context applicationContext, ArrayList<String> listItems) 
    this.context = applicationContext;
    this.listItems = listItems;
    this.className = context.getClass().getSimpleName();
    this.calHelper  = new CalHelper(applicationContext);
    this.settings  = new Settings(applicationContext);
    inflter = (LayoutInflater.from(applicationContext));


@Override
public int getCount() 
    if(listItems != null) 
        return listItems.size();
    else
        return 0;
    


@Override
public Object getItem(int position) 
    return listItems.get(position);


@Override
public long getItemId(int position) 
    return position;


//With following overrides Prevent listview item will not mix randomly
//and convertView provided is of the appropriate type.
@Override
public int getViewTypeCount() 
    if(getCount() > 0) //for no records in returning view
        return getCount();
    else
        return super.getViewTypeCount();
    


@Override
public int getItemViewType(int position) 
    return position;


/* private view holder class for holding calculation history*/
private class HistoryViewHolder 
    TextView more;
    TextView expression;
    TextView result;
    TextView shortNote;
    TextView expTime;


/* private view holder class for holding GST calculations history*/
private class GstHistoryViewHolder 
    TextView amount;
    TextView gst;
    TextView total;
    TextView expTime;
    ImageView share;


/* private view holder class */
private class BMIViewHolder 
    TextView bmiScore;
    TextView bmiDate;
    TextView bmiWeight;


@Override
public View getView(final int position, View convertView, ViewGroup viewGroup) 
    LayoutInflater mInflater = (LayoutInflater) context
            .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    //final int pos = position;
    if(className.equals("MainActivity")) 
        final HistoryViewHolder holder = new HistoryViewHolder();
        final String expString = listItems.get(position);
        final String expre = expString.substring(0, expString.indexOf(":"));
        final String expreTime = expString.substring(expString.indexOf(":") + 1, expString.length());
        final String result = expre.substring(expre.indexOf("=")+1);
        String timePattern = calHelper.calHistoryTimePattern(expreTime);
        SimpleDateFormat localDateFormat = new SimpleDateFormat(timePattern);

        if (convertView == null) 
            convertView = mInflater.inflate(R.layout.listview_row, null);
            holder.more = (TextView) convertView
                    .findViewById(R.id.more);
            holder.expression = (TextView) convertView.findViewById(R.id.expression);
            holder.result = (TextView) convertView.findViewById(R.id.result);
            holder.shortNote = (TextView) convertView.findViewById(R.id.shortNote);
            holder.expTime = (TextView) convertView.findViewById(R.id.expTime);
            holder.expression.setText(expre.substring(0, expre.indexOf("=")));
            holder.result.setText(result);
            String time = localDateFormat.format(new Date(expreTime));
            holder.expTime.setText(time);
            holder.shortNote.setText(settings.getHistoryNote(context,expString));

            convertView.setTag(holder);

            final TextView btnMore = (TextView) holder.more;
            btnMore.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    showPopup(v, position, expString, expre, expreTime, holder.shortNote);
                
            );

        
    


    return convertView;



public void showPopup(View v, final int position, final String expString, final String expression, final String expTime, final TextView shortNote) 
    final PopupMenu popup = new PopupMenu(context, v);

    //truncate title with ellipsis for more characters
    final String noteTitle = expression.length()>10? expression.substring(0, 10) + "..." : expression;
    MenuInflater inflater = popup.getMenuInflater();
    inflater.inflate(R.menu.history_menu, popup.getMenu());
    //registering popup with OnMenuItemClickListener
    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() 
        public boolean onMenuItemClick(MenuItem item) 
            Intent intent = new Intent(context, MainActivity.class);
            int itenId = item.getItemId();
            switch (itenId)
                case R.id.mnuInsertExpression:
                    //some code here
                break;
                case R.id.mnuHisNote:
                    //some code here                        
                    break;
                case  R.id.mnuCopyHisRecord:
                    calHelper.copyToClipboard(expression);
                    break;
                case R.id.mnuShareHisRecord:
                    calHelper.shareText(expression);
                    break;
                case  R.id.mnuDeleteHisRecord:  //This is where I am deleting item
                    System.out.println("Pos:"+position);
                      listItems.remove(position);
                      notifyDataSetChanged();
                    Collections.reverse(listItems); //sort descending by time again
                    settings.clearSharedPre(context,expString); //remove note attached to this expression from ShredPref
                    settings.saveArrayList(context, listItems, "EXP_HISTORY");
                    intent.putExtra("HISTORY_RECORD_DELETED", true);
                    Toast.makeText(context,"Record removed from history", Toast.LENGTH_SHORT).show();
                    context.startActivity(intent);
                    break;
            
            return true;
        
    );
    popup.show();

非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

试试这个 getView():

        @Override
        public View getView(int position, View convertView, ViewGroup viewGroup) 
            HistoryViewHolder holder;
            if(className.equals("MainActivity")) 
                final String expString = listItems.get(position);
                final String expre = expString.substring(0, expString.indexOf(":"));
                final String expreTime = expString.substring(expString.indexOf(":") + 1, expString.length());
                final String result = expre.substring(expre.indexOf("=")+1);
                String timePattern = calHelper.calHistoryTimePattern(expreTime);
                SimpleDateFormat localDateFormat = new SimpleDateFormat(timePattern);

                if (convertView == null) 
                    LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
                    convertView = mInflater.inflate(R.layout.listview_row, null);
                    holder = new HistoryViewHolder();
                    holder.more = (TextView) convertView.findViewById(R.id.more);
                    holder.expression = (TextView) convertView.findViewById(R.id.expression);
                    holder.result = (TextView) convertView.findViewById(R.id.result);
                    holder.shortNote = (TextView) convertView.findViewById(R.id.shortNote);
                    holder.expTime = (TextView) convertView.findViewById(R.id.expTime);

                    holder.more.setOnClickListener(new View.OnClickListener() 
                        @Override
                        public void onClick(View v) 
                            int pos = (int) v.getTag();
                            showPopup(v, pos, expString, expre, expreTime, holder.shortNote);
                        
                    );
                else
                    holder = (HistoryViewHolder)convertView.getTag();
                
                holder.expression.setText(expre.substring(0, expre.indexOf("=")));
                holder.result.setText(result);
                String time = localDateFormat.format(new Date(expreTime));
                holder.expTime.setText(time);
                holder.shortNote.setText(settings.getHistoryNote(context, expString));
                holder.more.setTag(position);
                convertView.setTag(holder);
            
            return convertView;
        

希望有帮助!

【讨论】:

太棒了!!有用。 holder.more.setOnClickListene 给出了语法错误,我用原来的 btnMore.setOnClickListener 替换了它,但其余的都是按照你提到的方式。非常感谢。【参考方案2】:

因为您使用的是 getView 参数的位置,所以在您使用它时,它始终是最后一个索引。

相反,您需要将该位置添加到视图中,可能在您的 convertView 中是我通常做的(标签可以是您想要的任何东西),在您创建每个项目视图时在 getView 方法中执行convertView.setTag(position),并且然后在 showpopup 中的删除方法中,您可以执行 (int)view.getTag() 以获取要从数据集中删除的位置。

【讨论】:

使用 setTag 和 getTag 无效。我得到了正确的视图位置,但它只删除了最后一项。我在 AlertDalog 中显示 ListView,这会对正常的列表视图/适配器功能产生任何影响。【参考方案3】:

您应该使用setTag()postion 添加到button,并在使用getTag()showPopup() 传递给position 时获取position。您可以执行以下操作。

 // ....
 final TextView btnMore = (TextView) holder.more;
 btnMore.setTag(position); // here add the position to the button using setTag().
 btnMore.setOnClickListener(new View.OnClickListener() 
    @Override
    public void onClick(View v) 
         // here you can get position your button using v.getTag().
         int pos = (int) v.getTag();
         showPopup(v, pos, expString, expre, expreTime, holder.shortNote);
    
);

【讨论】:

这又是在删除最后一项。

以上是关于ListView 总是从 CustomAdaptor 中删除最后一行的主要内容,如果未能解决你的问题,请参考以下文章

删除 listView 时未更新总小时数

为啥我的 ListView 是从下到上开始的?

为啥我们应该总是从函数返回值?

UIView 动画总是从当前状态开始

CGMutablePath 总是从 0,0 开始

总是从 CLLocationManager 获得相同的坐标