Как удалить фрагмент из FragmentPagerAdapter?

Я знаю, что здесь уже есть некоторые темы по этому поводу, но я не смог найти решение, которое я мог бы найти для своего случая.

У меня есть рабочая скользящая галерея с использованием пользовательских FragmentActivity а также FragmentPagerAdapter который содержит список фрагментов.

В пределах FragmentActivity это ImageView "удалять". Если нажать, функция deleteMedia() называется который затем должен удалить текущий Fragment и следующее Fragment должен отображаться. Как мне сделать это в моем примере?

FragmentActivity:

public class GalleryPagerActivity extends FragmentActivity implements OnClickListener {

    private Intent intent;
    private SharedPreferences settings;
    private PagerAdapter mPagerAdapter;
    private ViewPager mPager;
    private List<Fragment> fragments;
    private List<WhiteboardMedia> wiList;

    private int selectedPosition;
    private LinearLayout llTop;
    private TextView tvTop;
    private ImageView delete;
    private ImageView share;
    private TextView tvCounter;
    private TextView tvFilename;
    private TextView tvFilesize;
    private TextView tvDate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            super.setContentView(R.layout.gallery_pager);

            intent = getIntent();

            Type collectionType = new TypeToken<List<WhiteboardMedia>>(){}.getType();

            wiList = gson.fromJson(intent.getStringExtra("wiList"), collectionType);
            selectedPosition = intent.getIntExtra("position", 1);

            llTop = (LinearLayout) findViewById(R.id.llTop);
            llTop.setOnClickListener(this);
            tvTop = (TextView) findViewById(R.id.tvTop);
            tvTop.setOnClickListener(this);
            delete = (ImageView) findViewById(R.id.imgDelete);
            delete.setOnClickListener(this);
            share = (ImageView) findViewById(R.id.imgShare);
            share.setOnClickListener(this);

            tvCounter = (TextView) findViewById(R.id.tvCounter);
            tvFilename = (TextView) findViewById(R.id.tvFilename);
            tvFilesize = (TextView) findViewById(R.id.tvFilesize);
            tvDate = (TextView) findViewById(R.id.tvDate);

            createContextMenu();
            initDropbox();
        } catch (Exception e) {
            Log.e("GalleryPagerActivity", e.getLocalizedMessage());
        }
    }

    /**
     * Initialise the pager
     */
    private void initialisePager() {
        mPager = (ViewPager) super.findViewById(R.id.viewpager);
        mPager.setAdapter(this.mPagerAdapter);
        mPager.setOnPageChangeListener(new GalleryPageListener(tvCounter, tvFilename, tvFilesize, tvDate, wiList));

        mPager.setCurrentItem(selectedPosition, true);
        updatePage(selectedPosition);
    }

    public void updatePage(int position)
    {
        int focusedPage = position + 1;
        Log.i("onPageSelected", "page selected " + position);

        WhiteboardMedia wiImage = wiList.get(position);

        String imageDate = "N/A";
        try {
            Date dateTaken= new Date(); //wiImage.getDate();
            SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd");
            imageDate = sdf.format(dateTaken);
        } catch (Exception e) {
        }

        try {
            tvCounter.setText(focusedPage + "/" + wiList.size());
            tvFilename.setText(wiImage.getFilename());
            tvFilesize.setText(wiImage.getSize() + "a");
            tvDate.setText(imageDate);
        } catch (Exception e) {
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    private WhiteboardMedia getActiveWhiteboardImage() {
        return wiList.get(mPager.getCurrentItem());
    }

    private final int DELETE = 1;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(1, DELETE, 2, R.string.delete).setIcon(R.drawable.menu_btn_trash);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case DELETE:
            deleteMedia();
            return true;
        }
        return super.onContextItemSelected(item);
    }

    @Override
    public void onClick(View v) {
        if (v == delete) {
            deleteMedia();
        }
    }

    private void deleteMedia() {
        // TODO delete the active Fragment and display the next Fragment in the list
    }

    /******************************************************************************
     * Context Menu
     *****************************************************************************/
    private void createContextMenu() {
        // context menu stuff
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        // stuff
    }

}

FragmentPagerAdapter:

public class GalleryPagerAdapter extends FragmentPagerAdapter {

private final List<Fragment> fragments;

public GalleryPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
    super(fm);
    this.fragments = fragments;
}

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

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

Спасибо за помощь!

5 ответов

Решение

Во-первых, я предлагаю вам рассмотреть возможность изменения FragmentPagerAdapter, чтобы больше походить на образец. Вы обычно не держите список фрагментов, больше, чем ArrayAdapter обычно содержит список Views для строк. Обычно вы создаете фрагменты по требованию, а кто-то еще держит список.

Затем, чтобы удалить что-то, удалите это из данных вашей модели (что FragmentPagerAdapter нормально заворачивает). Удостоверься что getCount() затем вернет нужное количество предметов. Затем позвоните notifyDataSetChanged() на FragmentPagerAdapter, который должен вызвать перерисовку ViewPager,

Вот решение, которое я использую:

mViewPager: это представление, которое вы используете для установки фрагмента

mViewPager = (YourViewPager) findViewById(R.id.myPager);

ТАБЛИЦА: это просто целочисленный список позиций всех моих фрагментов

    public void destroyAllItem() {
        int mPosition = mViewPager.getCurrentItem();
        int mPositionMax = mViewPager.getCurrentItem()+1;
        if (TABLE.size() > 0 && mPosition < TABLE.size()) {
            if (mPosition > 0) {
                mPosition--;
            }

            for (int i = mPosition; i < mPositionMax; i++) {
                try {
                    Object objectobject = this.instantiateItem(mViewPager, TABLE.get(i).intValue());
                    if (objectobject != null)
                        destroyItem(mViewPager, TABLE.get(i).intValue(), objectobject);
                } catch (Exception e) {
                    Log.i(TAG, "no more Fragment in FragmentPagerAdapter");
                }
            }
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);

        if (position <= getCount()) {
            FragmentManager manager = ((Fragment) object).getFragmentManager();
            FragmentTransaction trans = manager.beginTransaction();
            trans.remove((Fragment) object);
            trans.commit();
        }
    }

Если вы используете FragmentPagerAdapter для динамического добавления и удаления фрагментов в произвольной позиции (не всегда в конце), существует метод, которому необходимо уделить больше внимания, - getItemId. По умолчанию FragmentPagerAdapter использует сочетания позиций viewId в качестве имени тега для фрагментов, однако позиция изменяется при добавлении или удалении фрагментов. В результате вы можете получить пустую страницу, потому что добавляемая вами позиция занята существующим фрагментом. Чтобы решить эту проблему, переопределите getItemId.

@Override
public long getItemId(int position) {
    long itemId = ...;  //Provide your unique ID here according to you logic
    return itemId;
}

Я нашел решение, переопределив метод "onPostResume()" действия и вызвав внутри него notifyDataSetChanged.

@Override
protected void onPostResume() {
    super.onPostResume();
    if(this.mCustomPagerAdapter!=null){
        this.mCustomPagerAdapter.notifyDataSetChanged();
    }
}

В моем случае, когда я пытаюсь удалить один элемент из адаптера, я буду делать следующее:

// get the position of item to remove
int position = getBinding().vp.getCurrentItem();
// remove the item from adapter
adapter.removeItem(position);
adapter.notifyDataSetChanged();
// minus one from the count
totalInvoice--;
updateTitle(getBinding().vp.getCurrentItem());
if (totalInvoice == 0) {
    finish();
}
// set the adapter to view pager again            
getBinding().vp.setAdapter(adapter);
// smooth scroll to given position
getBinding().vp.setCurrentItem(position);

Причина, которую я сделал выше, состоит в том, что я обнаружил, что, хотя вы удалили один из списка данных, но представление фрагмента все еще существует. Таким образом, вы должны позволить пейджеру просмотра создать представление данной позиции. Ответ выше, который пытается удалить все фрагменты, не работает для меня. Итак, я обнаружил плохой способ настройки адаптера для просмотра пейджера снова.

Другие вопросы по тегам