【问题标题】:Add / Delete pages to ViewPager dynamically动态添加/删除页面到 ViewPager
【发布时间】:2011-11-09 05:50:55
【问题描述】:

我想从我的视图寻呼机中动态添加或删除页面。这可能吗?

【问题讨论】:

  • @Sam_k 还没有。我还没有时间尝试。 Paresh 提供的解决方案不起作用,但 Zsombor 可能。如果我找到任何东西,我会告诉你的。
  • 考虑this answer

标签: android android-viewpager


【解决方案1】:

是的。您可以将视图动态添加或删除到向 ViewPager 提供视图的 PagerAdapter,并从 PagerAdapter 调用 notifyDataSetChanged() 以提醒受影响的 ViewPager 有关更改。但是,当您这样做时,您必须覆盖 PagerAdapter 的 getItemPosition(Object),这会告诉他们当前显示的项目是否已更改位置。默认情况下,此函数设置为POSITION_UNCHANGED,因此如果不覆盖此方法,ViewPager 不会立即刷新。例如,

public class mAdapter extends PagerAdapter {
    List<View> mList;

    public void addView(View view, int index) {
        mList.add(index, view);
        notifyDataSetChanged();
    }

    public void removeView(int index) {
        mList.remove(index);
        notifyDataSetChanged();
    }

    @Override
    public int getItemPosition(Object object)) {
        if (mList.contains(object) {
            return mList.indexOf(object);
        } else {
            return POSITION_NONE;
        }
    }
}

虽然,如果您只是想暂时从显示中添加或删除视图,而不是从 PagerAdapter 的数据集中,请尝试使用 setPrimaryItem(ViewGroup, int, Object) 转到 PagerAdapter 数据中的特定视图,并使用 destroyItem(ViewGroup, int, Object) 删除一个从显示器查看。

【讨论】:

  • 覆盖 getItemPosition 帮助我修复了一个多星期以来的错误。非常感谢你
  • 你在 getItemPosition 中的 if 语句后丢失了右括号
  • @Yazon2006 我不这么认为。它与 else 关键字在同一行。也许你错过了?
  • @CodePro_NotYet 是的,也许你是对的!感谢您的仔细检查!
  • 进行此转换以查看 myspecificFragment 的作品,否则我必须转换为 myspecificFragment
【解决方案2】:

是的,由于 ViewPager 从 PagerAdapter 获取子视图,您可以在其上添加新页面/删除页面,然后调用 .notifyDataSetChanged() 重新加载它。

【讨论】:

  • 理论上你的答案是正确的..但在现实世界中..从 ViewPager 中删除和添加东西很痛苦..特别是碎片..
  • 你应该覆盖适配器中的 getItemPosition()
  • @GuilhermeOliveira 我将视图插入到索引1并调用notifyDatasetChanged。但是viewpager不会刷新所有视图,而是启动最后一个索引。您知道如何解决吗?
  • 其实你可以很容易的在你当前的位置(ViewPager右侧)之后添加片段。但是,如果您想在当前位置(即 ViewPager 的左侧)之前添加而不跳转到它.. 真的很棘手。我花了 2 天时间弄清楚,但仍然不知道该怎么做。
  • 在调用 notifyDataSetChange 之后,它会进入空白页面并重新实例化视图。如果我从视图寻呼机适配器中删除视图,我需要做什么?我尝试使用 getItemPosition() 但它不起作用。请提供任何建议。谢谢。
【解决方案3】:

是的,代码应该是这样的:

public int addPage(View view, int position) {
        if ((position >= 0) && (position < getSize())) {
            myPagerAdapter.mListViews.add(position, view);
            myPagerAdapter.notifyDataSetChanged();
            return position;
        } else {
            return -1;
        }
    }

public View removePage(int position) {
        if ((position < 0) || (position >= getSize()) || (getSize()<=1)) {
            return null;
        } else {
            if (position == mPager.getCurrentItem()) {
                if(position == (getSize()-1)) {
                    mPager.setCurrentItem(position-1);
                } else if (position == 0){
                    mPager.setCurrentItem(1);
                }
            }
            View tempView = myPagerAdapter.mListViews.remove(position);
            myPagerAdapter.notifyDataSetChanged();
            return tempView;
        }
    }

但是有一个错误。如果当前Item为0,去掉page 0,不会立即刷新屏幕,我还没有找到解决办法。

【讨论】:

  • mListViews 是从哪里来的?
  • @Muz 看起来像mListViews 将是类myPagerAdapter 中的视图列表,它将扩展FragmentPagerAdapter,因为这将是存储所有视图的理想区域(页面) 对于 ViewPager mPager
  • @tc007733,这不是错误,您需要覆盖的关键是 getItemPosition(Object o) 并在不再有效时返回 POSITION_NONE stackoverflow.com/questions/13664155/…
【解决方案4】:

这是此问题的替代解决方案。我的适配器:

private class PagerAdapter extends FragmentPagerAdapter implements 
              ViewPager.OnPageChangeListener, TabListener {

    private List<Fragment> mFragments = new ArrayList<Fragment>();
    private ViewPager mPager;
    private ActionBar mActionBar;

    private Fragment mPrimaryItem;

    public PagerAdapter(FragmentManager fm, ViewPager vp, ActionBar ab) {
        super(fm);
        mPager = vp;
        mPager.setAdapter(this);
        mPager.setOnPageChangeListener(this);
        mActionBar = ab;
    }

    public void addTab(PartListFragment frag) {
        mFragments.add(frag);
        mActionBar.addTab(mActionBar.newTab().setTabListener(this).
                            setText(frag.getPartCategory()));
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

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

    /** (non-Javadoc)
     * @see android.support.v4.app.FragmentStatePagerAdapter#setPrimaryItem(android.view.ViewGroup, int, java.lang.Object)
     */
    @Override
    public void setPrimaryItem(ViewGroup container, int position,
            Object object) {
        super.setPrimaryItem(container, position, object);
        mPrimaryItem = (Fragment) object;
    }

    /** (non-Javadoc)
     * @see android.support.v4.view.PagerAdapter#getItemPosition(java.lang.Object)
     */
    @Override
    public int getItemPosition(Object object) {
        if (object == mPrimaryItem) {
            return POSITION_UNCHANGED;
        }
        return POSITION_NONE;
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) { }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) { }

    @Override
    public void onPageScrollStateChanged(int arg0) { }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) { }

    @Override
    public void onPageSelected(int position) {
        mActionBar.setSelectedNavigationItem(position);
    }

    /**
     * This method removes the pages from ViewPager
     */
    public void removePages() {
        mActionBar.removeAllTabs();

                    //call to ViewPage to remove the pages
        vp.removeAllViews();
        mFragments.clear();

        //make this to update the pager
        vp.setAdapter(null);
        vp.setAdapter(pagerAdapter);
    }
}

动态删除和添加代码

//remove the pages. basically call to method removeAllViews from ViewPager
pagerAdapter.removePages();

pagerAdapter.addPage(pass your fragment);

Peri Hartman的建议下,我将null设置为ViewPager适配器并在视图删除后重新放置适配器后它开始工作。在此之前,页面 0 没有显示其列表内容。

【讨论】:

  • 非常感谢!这是一件很难做到的事情
  • 里面是什么vp,你是怎么初始化的?
【解决方案5】:

我确定你已经通过扩展 PageAdapter 创建了一个适配器,所以有一种方法:

 @Override
 public void destroyItem(View collection, int position, Object view) {
           ((ViewPager) collection).removeView((View) view);
 }

对于相同的详细示例,只需通过this example

【讨论】:

  • 它从容器中销毁项目。我想从我的应用程序中永久删除。
  • @Parash Rply 如果你得到我请
  • 链接坏了,能补一下吗?
【解决方案6】:

首先:重写pagerAdapter方法“getItemPosition”

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

第二:移除与adapter的数据绑定。调用adapter.notifydatachanged

【讨论】:

  • 虽然这个解决方案有效,但我听说它的内存效率非常低
【解决方案7】:
@Bind(R.id.pager)
ViewPager pager;
int pos = pager.getCurrentItem();
pager.removeViewAt(pos);

【讨论】:

  • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
【解决方案8】:

根据其他答案和其他资源,我以这段代码结束。

CustomPagerAdapter

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CustomPagerAdapter extends PagerAdapter {

  private List<Fragment> pages = new ArrayList<>();
  private Map<Fragment, Integer> fragmentsPosition = new HashMap<>();

  private Fragment currentPrimaryItem;
  private FragmentManager fragmentManager;
  private FragmentTransaction currentTransaction;


  public CustomPagerAdapter(FragmentManager fragmentManager) {
    this.fragmentManager = fragmentManager;
  }

  @Override
  public Object instantiateItem(ViewGroup container, int position) {
    if (currentTransaction == null) {
      currentTransaction = fragmentManager.beginTransaction();
    }

    Fragment pageFragment = pages.get(position);
    String tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);
    Fragment fragment = fragmentManager.findFragmentByTag(tag);

    if (fragment != null) {
      if (fragment.getId() == container.getId()) {
        currentTransaction.attach(fragment);
      }
      else {
        fragmentManager.beginTransaction().remove(fragment).commit();
        fragmentManager.executePendingTransactions();
        currentTransaction.add(container.getId(), fragment, tag);
      }
    }
    else {
      fragment = pageFragment;
      currentTransaction.add(container.getId(), fragment, tag);
    }

    if (fragment != currentPrimaryItem) {
      fragment.setMenuVisibility(false);
      fragment.setUserVisibleHint(false);
    }

    return fragment;
  }

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

  @Override
  public void destroyItem(ViewGroup container, int position, Object object) {
    if (currentTransaction == null) {
      currentTransaction = fragmentManager.beginTransaction();
    }

    currentTransaction.detach((Fragment) object);
  }

  @Override
  public void setPrimaryItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment) object;

    if (fragment != currentPrimaryItem) {
      if (currentPrimaryItem != null) {
        currentPrimaryItem.setMenuVisibility(false);
        currentPrimaryItem.setUserVisibleHint(false);
      }

      if (fragment != null) {
        fragment.setMenuVisibility(true);
        fragment.setUserVisibleHint(true);
      }

      currentPrimaryItem = fragment;
    }
  }

  @Override
  public void finishUpdate(ViewGroup container) {
    if (currentTransaction != null) {
      currentTransaction.commitAllowingStateLoss();
      currentTransaction = null;
      fragmentManager.executePendingTransactions();
    }
  }

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

  @Override
  public int getItemPosition(Object o) {
    Integer result = fragmentsPosition.get(o);

    if (result == null) {
      return PagerAdapter.POSITION_UNCHANGED;
    }

    return result;
  }

  // ---------------------------------- Page actions ----------------------------------

  public void addPage(Fragment fragment) {
    fragmentsPosition.clear();
    pages.add(fragment);
    notifyDataSetChanged();
  }

  public void removePage(int position) {
    fragmentsPosition.clear();

    Fragment pageFragment = pages.get(position);
    String tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);

    Fragment fragment = fragmentManager.findFragmentByTag(tag);

    if (fragment != null) {
      fragmentsPosition.put(fragment, PagerAdapter.POSITION_NONE);
    }

    for (int i = position + 1; i < pages.size(); i++) {
      pageFragment = pages.get(i);
      tag = pageFragment.getArguments().getString(MainActivity.FRAGMENT_TAG_ARG);
      fragment = fragmentManager.findFragmentByTag(tag);

      if (fragment != null) {
        fragmentsPosition.put(fragment, i - 1);
      }
    }

    pages.remove(position);
    notifyDataSetChanged();
  }

}

MainActivity

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

  public static final String FRAGMENT_TAG_ARG = "tag";

  private CustomPagerAdapter mCustomPagerAdapter;

  private ViewPager mViewPager;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mCustomPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager());
    mCustomPagerAdapter.addPage(MainFragment.newInstance("Main_Title"));
    mCustomPagerAdapter.addPage(SecondaryFragment.newInstance("Secondary_Title"));

    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mCustomPagerAdapter);
  }

}

要删除页面:

mCustomPagerAdapter.removePage(1);

MainFragment

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MainFragment extends Fragment {

  public static final String FRAGMENT_TAG = "MainFragment";

  public static MainFragment newInstance(String text) {
    return newInstance(text, FRAGMENT_TAG);
  }

  public static MainFragment newInstance(String text, String tag) {
    MainFragment fragment = new MainFragment();
    Bundle args = new Bundle();
    args.putString("text", text);
    args.putString(MainActivity.FRAGMENT_TAG_ARG, tag + "_" + fragment.hashCode());
    fragment.setArguments(args);
    return fragment;
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    TextView textView = (TextView) rootView.findViewById(R.id.section_label);
    textView.setText(getArguments().getString("text"));
    return rootView;
  }

}

SecondaryFragment 具有相同的代码。

布局是简单的 ViewPager/Fragment 布局,android.support.v4.view.ViewPager 和 id container 和 Fragment TextView 和 id section_label

资源:

【讨论】:

    【解决方案9】:

    您必须再次将适配器设置为viewpager,然后它将刷新内容。

    在我的 PagerAdaper 中删除视图(int pos)

    public void removeView(int index) {
           imageFileNames.remove(index);
           notifyDataSetChanged();
    }
    

    无论我在哪里删除文件,我都必须这样做

    imagePagerAdapter.removeView(currentPosition);
    viewPager.setAdapter(imagePagerAdapter);
    

    编辑:

    下面这个方法是有效的,你可以应用下面那个。

    public void updateView(int pos){
          viewPager.setAdapter(null);
          imagePagerAdapter =new ImagePagerAdapter(YOUR_CONTEXT,YOUR_CONTENT);
          viewPager.setAdapter(imagePagerAdapter);
          viewPager.setCurrentItem(pos);
    }
    

    将 YOUR_CONTEXT 替换为您的上下文,将您的内容替换为您的内容名称,即更新的列表或其他内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      相关资源
      最近更新 更多