Как удалить фрагмент из FragmentPagerAdapter? - PullRequest
11 голосов
/ 18 марта 2012

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

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

В FragmentActivity есть ImageView «delete».Если щелкнуть, вызывается функция 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 ]

17 голосов
/ 12 июля 2012

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

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

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

TABLE: это просто список целых чисел позициивсе мои фрагменты

    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();
        }
    }
15 голосов
/ 18 марта 2012

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

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

1 голос
/ 21 марта 2018

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

@Override
public long getItemId(int position) {
    long itemId = ...;  //Provide your unique ID here according to you logic
    return itemId;
}
1 голос
/ 11 февраля 2016

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

@Override
protected void onPostResume() {
    super.onPostResume();
    if(this.mCustomPagerAdapter!=null){
        this.mCustomPagerAdapter.notifyDataSetChanged();
    }
}
0 голосов
/ 27 июля 2018

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

// 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);

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

...