如何从ViewPager和PagerAdapter中删除项目

7
我正在使用PagerAdapter和ViewPager来展示ImageView数组和TextView数组。但是,当我点击按钮时,如何删除Pager?完整的代码在下面,但我已经在XML中添加了一个onclick按钮应该删除页面。

https://www.swipetips.com/android-viewpager-gallery-images-and-texts-tutorial/

 package com.androidbegin.viewpagertutorial;

    import android.content.Context;
    import android.support.v4.view.PagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.TextView;

    public class ViewPagerAdapter extends PagerAdapter {
        // Declare Variables
        Context context;
        String[] rank;
        String[] country;
        String[] population;
        int[] flag;
        LayoutInflater inflater;

        public ViewPagerAdapter(Context context, String[] rank, String[] country,
                String[] population, int[] flag) {
            this.context = context;
            this.rank = rank;
            this.country = country;
            this.population = population;
            this.flag = flag;
        }

        @Override
        public int getCount() {
            return rank.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == ((RelativeLayout) object);
        }

        @Override
        public Object instantiateItem(final ViewGroup container, final int position) {

            // Declare Variables
            TextView txtrank;
            TextView txtcountry;
            TextView txtpopulation;
            ImageView imgflag;

            Button b;

            inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View itemView = inflater.inflate(R.layout.viewpager_item, container,
                    false);

            // Locate the TextViews in viewpager_item.xml
            txtrank = (TextView) itemView.findViewById(R.id.rank);
            txtcountry = (TextView) itemView.findViewById(R.id.country);
            txtpopulation = (TextView) itemView.findViewById(R.id.population);
            b=(Button)itemView.findViewById(R.id.button1);


            b.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {



                }
            });

            // Capture position and set to the TextViews
            txtrank.setText(rank[position]);
            txtcountry.setText(country[position]);
            txtpopulation.setText(population[position]);

            // Locate the ImageView in viewpager_item.xml
            imgflag = (ImageView) itemView.findViewById(R.id.flag);
            // Capture position and set to the ImageView
            imgflag.setImageResource(flag[position]);

            // Add viewpager_item.xml to ViewPager
            ((ViewPager) container).addView(itemView);

            return itemView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            // Remove viewpager_item.xml from ViewPager
            ((ViewPager) container).removeView((RelativeLayout) object);

        }
    }

////////////////////

// Locate the ViewPager in viewpager_main.xml
        viewPager = (ViewPager) findViewById(R.id.pager);
        // Pass results to ViewPagerAdapter Class
        adapter = new ViewPagerAdapter(MainActivity.this, rank, country, population, flag);
        // Binds the Adapter to the ViewPager
        viewPager.setAdapter(adapter);
2个回答

17

首先,由于需要动态删除对象,您需要使用List。第二步,您需要。

    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }

强制适配器每次创建新页面,而不使用内存中的页面。

 public class ViewPagerAdapter extends PagerAdapter {
    // Declare Variables
    Context context;
    List<String> rank;
    List<String> country;
    List<String> population;
    List<Integer> flag = new ArrayList<Integer>();
    LayoutInflater inflater;

    public ViewPagerAdapter(Context context, String[] rank, String[] country,
            String[] population, int[] flag) {
        this.context = context;
        this.rank = new ArrayList<String>(Arrays.asList(rank));
        this.country = new ArrayList<String>(Arrays.asList(country));
        this.population = new ArrayList<String>(Arrays.asList(population));
        for (int i : flag){ 
            this.flag.add(i);
        }

    }

    @Override
    public int getCount() {
        return rank.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == ((RelativeLayout) object);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        // Declare Variables
        TextView txtrank;
        TextView txtcountry;
        TextView txtpopulation;
        ImageView imgflag;

        inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View itemView = inflater.inflate(R.layout.viewpager_item, container,
                false);

        // Locate the TextViews in viewpager_item.xml
        txtrank = (TextView) itemView.findViewById(R.id.rank);
        txtcountry = (TextView) itemView.findViewById(R.id.country);
        txtpopulation = (TextView) itemView.findViewById(R.id.population);
         Button b=(Button)itemView.findViewById(R.id.button1);

         final int delPosition = position;

         b.setOnClickListener(new OnClickListener() {

             @Override
             public void onClick(View v) {
                 rank.remove(delPosition);
                 country.remove(delPosition);
                 population.remove(delPosition);
                 flag.remove(delPosition);
                 notifyDataSetChanged();
             }
         });
        // Capture position and set to the TextViews
        txtrank.setText(rank.get(position));
        txtcountry.setText(country.get(position));
        txtpopulation.setText(population.get(position));

        // Locate the ImageView in viewpager_item.xml
        imgflag = (ImageView) itemView.findViewById(R.id.flag);
        // Capture position and set to the ImageView
        imgflag.setImageResource(flag.get(position));

        // Add viewpager_item.xml to ViewPager
        ((ViewPager) container).addView(itemView);

        return itemView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // Remove viewpager_item.xml from ViewPager
        ((ViewPager) container).removeView((RelativeLayout) object);

    }
    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }
}

我有一个问题,当我尝试删除列表中的最后一项时,我的应用程序会崩溃。 它显示“java.lang.IndexOutOfBoundsException:无效索引6,大小为6”。 它指向这行代码:imageView.setImageResource(regionImages.get(position)); - Kala J
@KalaJ 在 Stack Overflow 上发布你的代码作为一个问题,然后告诉我链接! - mmlooloo
1
其实,我有一个新的ViewPager问题:http://stackoverflow.com/questions/26632219/how-can-i-save-the-state-and-value-of-button-press-between-views-in-a-viewpager 如果您有时间,能否帮忙看一下?谢谢。 - Kala J
Kala,你试图访问数组中的第7个项目,但实际上该数组只有6个项目。第6个索引是第7个项目,但它并不存在。 数组从索引0开始。 - Nickmccomb

1

所选答案将快速影响性能

确实,您需要实现Adaptor的getItemPosition()方法,但应按照预期进行重写。

getItemPosition()方法告诉ViewPager在调用adapter.notifyDataSetChanged()时是否删除viewItem,重新绘制或不重新绘制viewItem。

基本上,在调用adapter.notifyDataSetChanged()时,会调用您对getItemPosition()方法的实现来回答一个简单的问题。

这个问题是“我们拥有的每个viewItem的位置是否已更改?”

对于这个问题有两个答案

  1. PagerAdapter.POSITION_UNCHANGED //未更改,节省资源,使用缓存的viewitem
  2. PagerAdapter.POSITION_NONE //我们不再拥有该视图,请重新创建它或删除它。

这个问题决定了ViewPager是否重新创建新的viewItem或使用已缓存的viewItem。此外,从这个答案中,可以决定删除被视为已删除或已移除的ViewItem。

如果ViewPager在每次调用adapter.notifyDataSetChanged()时都必须为项目列表中的每个数据项创建一个新的视图项,那么性能会受到影响。想象一下,如果您有来自数据库的数千条数据的列表; 性能将受到影响。这正是从getItemPosition()返回PagerAdapter.POSITION_NONE所做的。您正在绕过一个关键的性能机制。
作为开发人员,您有责任弄清楚如何回答该问题。但请记住,您回答该问题的方式会影响应用程序的性能。
如何实现:
在您的PagerAdapter中,使用instantiateItem(@NonNull ViewGroup container, int position)方法。在实例化后给您的视图设置一个标签。给它一个独特的名称。我使用要显示在该视图中的图像的名称。
public MyAdaptorPagerAdaptor(Context context, ArrayList<MyMedia> myMedias) {
    this.context = context;
    this.myMedias = myMedias;
    this.authCode = authCode;
}

public Object instantiateItem(@NonNull ViewGroup container, int position) {
    
    mageView imageView = new ImageView(context);
    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
    mageView.setTag(myMedia.getName()); //the most important part

    //....... do your stuff
    return imageView;
}

然后覆盖getItemPosition(@NonNull Object object)方法。在该消息中,super.getItemPosition(object);返回答案1,即PagerAdapter.POSITION_UNCHANGED //nothing changed save resources use cached viewitem,这是默认行为。但我们想要遍历数据项,看看从getItemPosition(@NonNull Object object)传递给我们的viewItem是否仍存在于Adapter项数组中。我们感兴趣的是当它不存在时。那就是我们返回答案2的时候。PagerAdapter.POSITION_NONE。作为对象传递给我们的viewItem,恰好是我们在public Object instantiateItem(@NonNull ViewGroup container, int position)方法中返回的对象。在我的情况下,它是ImageView
@Override
public int getItemPosition(@NonNull Object object) {
    int res = super.getItemPosition(object);
    ImageView imageView = (ImageView) object;
    final String tag = (String) imageView.getTag();

    // look for an item with our tag from our items list.
    MyMedia myMedia = null;
    for (MyMedia item : myMedias) {
        if (item.getName().equals(tag)) {
            myMedia = item;
            break;
        }
    }

    //if this item is null, then it does not exist in my items list
    // so I tell View pager I don't have that item.
    if (myMedia == null) {
        res = PagerAdapter.POSITION_NONE;
    }
    return res;
}

最后一步。现在从您的片段活动中,只需从您传递给适配器作为数据源的适配器数组或ArrayList中删除数据。

//remove deleted item from myMedias ArrayList
myMedias.remove(position);

//tell your adapter instance data changed
pagerAdapter.notifyDataSetChanged();  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接