android - 从 ViewHolder(列表)中删除项目,更新屏幕

标签 android android-layout android-intent

我有一个 ViewHolder,用于保存添加到列表中的(相对布局) View 。在每个单独的布局中,我都有一个删除按钮。我希望能够单击删除按钮并更新屏幕。我当前的实现有效,但我必须点击后退按钮,然后返回屏幕才能看到它已被删除。

本质上,这是一个动态添加项目的购物车。所以简而言之,我需要在单击删除按钮时更新屏幕的 onClick 事件中添加什么? Invalidate() 不起作用。

提醒:这些方法与 onCreate() 分开,所以我不能使用 finish() 或 getIntent() 或类似的东西。

编辑:我在 Reinier 的回答中添加了额外的评论

最佳答案

我假设您使用的是带有自定义 ListAdapter 的 ListView?将您的数据集(例如 ArrayList)传递给构造函数中的 ListAdapter。然后,当您操作数据集时(例如通过 dataset.remove(Object object)),在您的 ListAdapter 上调用 .notifyDatasetChanged()。然后,您的适配器将更新它所属的 View 。

更新

我不太确定您所说的“它搞砸了支架中的位置”是什么意思。 ViewHolder 基本上只是保存对要在 getView() 方法中操作的 View 的引用。您的数据集与您的 ViewHolder 是分开的,因此从您的数据集中删除内容不会影响布局 - 当然,除了从 ListView 中删除该项目。

这是一个应该起作用的示例。我试图尽可能多地解释。您可能知道其中的大部分内容,但我只是记下了一些额外的信息以供将来引用/Google 员工。

注意:它可能并不完美,但应该可以。

public class MyAdapter extends ArrayAdapter<CartItem> {

// This is our data-model.
// let's say your cartitems only contain an id and name
// normally this would be defined elsewhere in your code
public class CartItem {
    public int id;
    public String product_name;
}

/*
 * ViewHolders are basically meant to keep a reference to the Views,
 * so that you don't have to use .findViewById() on every getView()
 * for the elements you're trying to manipulate.
 * 
 * .findViewById() finds Views by traversing the hierarchy (heavy).
 * This generally isn't a problem, but we want to avoid this in
 * ListViews because getView() gets called a lot - which makes our app slow.   
 * 
 * We will want to keep a reference to our TextView and Button,
 * because these are the elements we want to change every getView().
 * Not to the RelativeLayout, because it's already passed in convertView
 * (after you inflated it for the first time) and we're not manipulating it
 * anyway.
 */
public class ViewHolder {

    public Button deleteButton;
    public TextView mTextView;

}

public MyAdapter(Context context, int textViewResourceId,
        ArrayList<CartItem> cartItems) {

    // here, we tie our data (ArrayList of CartItem's)
    // to the ListAdapter (ArrayAdapter = extended ListAdapter)
    super(context, textViewResourceId, cartItems);
}


    // this method 
public View getView(final int position, View convertView, ViewGroup parent) {

    final ViewHolder holder;

    // if convertView == null, that means we haven't inflated our listitem yet.
    if(convertView == null) {

        // so, we'll inflate our listitem now.
        // after this, convertView will contain our RelativeLayout
        // and its children/subviews
        LayoutInflater inflater = (LayoutInflater) getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.listitem, null);

        // now we're gonna instantiate the ViewHolder to keep a reference
        // to our TextView and ImageView
        holder = new ViewHolder();

        holder.mTextView = (TextView) convertView
                .findViewById(R.id.listitem_textview);
        holder.deleteButton = (Button) convertView
                .findViewById(R.id.listitem_deletebutton);

        // Now that we have our reference, we want to make sure we can
        // keep our reference by using tags. Tags are a way to attach
        // data to a View.
        convertView.setTag(holder);
    } else {
        // if we have already inflated our listitem, we just get the
        // references to our Views from the tag
        holder = (ViewHolder) convertView.getTag();
    }

    // we want to read/do-stuff-with a specific CartItem. First, get
    // a reference to the data-object.
    final CartItem mCartItem = (CartItem) getItem(position);

    // now, it's time to manipulate our views
    holder.mTextView.setText(mCartItem.product_name);
    holder.deleteButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            // then, pass a signal to MyAdapter that we want to remove
            // this item from our dataset
            remove(mCartItem);
            // now, we want to update any (list)views attached to our MyAdapter
            // this will let the ListView update itself
            notifyDataSetChanged();
        }

    });

    // convertView will be recycled, which means what we output here
    // will be the input for the next getView()-call
    return convertView;
}
}

如果您想从您的 Activity 中操作您的数据集,请执行以下操作:

MyAdapter myAdapter = new MyAdapter(this, R.layout.listitem, cartItems);
ListView listview = (ListView) findViewById(R.id.listview);
listview.setAdapter(myAdapter);

cartItems.remove(object);
myAdapter.notifyDatasetChanged();

这将从 ListView 中删除该项目,是的,这将重置位置索引。但是,如果您正确设置了 ListAdapter,这将不是问题。

关于android - 从 ViewHolder(列表)中删除项目,更新屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9706440/

相关文章:

java - 我希望我的 Android 应用程序能够打开所有文件扩展名

android - 哪种开始新 Activity 的方式最好?

android - 由于 Firebase Test Lab 上的 Chrome 自动更新,Instrumentation 测试的应用程序崩溃

Android 重叠 ImageView

android - 项目没有 project.properties 文件

java - 如何使用 setContentView(new Activity(this)); 以编程方式创建 admob 横幅不使用xml?

android - Xamarin Studio (Android) 错误膨胀类 <unknown> 除非清理

android - 每个列表项 Android 的不同 Intent

android - 实现无尽滚动(分页)后,图像未在回收站 View 中显示(加载)

android - 通过intent/Fileprovider共享文档