Wie lösche ich einen Tab mit Actionbar, Viewpager und mehreren Fragmenten?
-
11-12-2019 - |
Frage
Ich verwende Code, den ich gefunden habe hier.
public class ActionBarTabs extends SherlockFragmentActivity {
CustomViewPager mViewPager;
TabsAdapter mTabsAdapter;
TextView tabCenter;
TextView tabText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
mViewPager = new CustomViewPager(this);
mViewPager.setId(R.id.pager);
setContentView(mViewPager);
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(bar.newTab().setText("Home"),
ToolKitFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText("FujiSan"),
FujiFragment.class, null);
}
public static class TabsAdapter extends FragmentPagerAdapter implements
ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public int getCount() {
return mTabs.size();
}
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(),
info.args);
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
}
Ich versuche es so zu ändern, dass ich Registerkarten dynamisch löschen kann.Ich habe es versucht, indem ich einfach diese Funktion erstellt habe:
public void removeTab(ActionBar.Tab tab) {
mTabs.remove(tab);
mActionBar.removeTab(tab);
notifyDataSetChanged();
}
Aber ich bekomme immer eine indexoutofboundsexception.Kennt jemand einen guten Weg, dies zu tun?
BEARBEITEN
Indem ich meine Methode ändere in:
public void removeTab(ActionBar.Tab tab) {
mTabs.remove(tab.getTag());
mActionBar.removeTab(tab);
notifyDataSetChanged();
}
Ich konnte Tabs erfolgreich entfernen.Wenn ich jedoch eine Registerkarte lösche, die NICHT die ganz rechts ist, wird die Ansicht (oder das Fragment?), das mit dem Tab verknüpft war, verschwindet nicht.Stattdessen scheint es mit der nächsthöheren Registerkarte verknüpft zu werden.Wenn ich beispielsweise Tab 0 gelöscht habe, wird die Ansicht von Tab 0 nur zu Tab 1 verschoben.Wenn ich den Tab mit der höchsten ID lösche, verschwinden der Tab und die Ansicht korrekt, kommen aber wieder, wenn ich einen neuen Tab hinzufüge.
Es ist, als ob irgendwo eine Liste von Fragmenten vorhanden wäre, die den Registerkarten zugeordnet sind, und das Löschen der Registerkarte löscht das Fragment nicht.Hat jemand eine Idee, was das verursacht?
BEARBEITUNG2
Ich habe versucht, die Fragmente mit zu löschen:
Fragment fragmentToRemove = getItem(tab.getPosition());
destroyItem(mViewPager, tab.getPosition(), fragmentToRemove);
und auch
Fragment fragmentToRemove = getItem(tab.getPosition());
FragmentTransaction fragmentTransaction = mActivity
.getSupportFragmentManager().beginTransaction();
fragmentTransaction.remove(fragmentToRemove);
fragmentTransaction.commit();
Aber beides hat bisher nicht funktioniert.
Lösung
hat es bekommen! generasacodicetagpre.
und überschreiben destroyitem generasacodicetagpre.
funktioniert perfekt !!!
Andere Tipps
Ich habe gerade heute entdeckt, dass der wahre Trick beim Einfügen oder Entfernen von Tabs darin besteht, sie zu überschreiben FragmentPagerAdapter.getItemPosition()
:
@Override
public int getItemPosition(Object object) {
Fragment fragment = (Fragment) object;
for (int i = 0; i < tabInfos.size(); i++) {
if (tabInfos.get(i).clss == fragment.getClass()) {
return i;
}
}
// The tab must have been removed
return POSITION_NONE;
}
getItemPosition()
wird von der aufgerufen ViewPager
nachdem Sie angerufen haben notifyDataSetChanged()
(nach dem Hinzufügen / Entfernen von Registerkarten).Der ViewPager
versucht, seinen Cache mit diesem Adapter neu zu synchronisieren.Es ruft getItemPosition()
für jedes 'Objekt' (Fragment), das es enthält, und wir sagen ihm, von welcher Position dieses Fragment stammt.Wenn es keine Übereinstimmung gibt, liegt es daran, dass wir diesen Tab gelöscht haben, also kehren Sie zurück POSITION_NONE
.
Ich habe auch festgestellt, dass es wichtig ist, zu überschreiben FragmentPagerAdapter.getItemId()
wenn Sie Registerkarten einfügen oder entfernen, weil die Fragmente die Positionen nach links und rechts verschieben.Diese Methode wird aufgerufen von FragmentPagerAdapter.instantiateItem()
und wird an einen Namen (String) für das Element angehängt.Es verwendet diesen Namen, um ein bereits vorhandenes Fragment mit einem übereinstimmenden Namen (falls vorhanden) zu suchen, andernfalls wird ein neues instanziiert.Hier ist ein Code:
@Override
public long getItemId(int position) {
TabInfo info = tabInfos.get(position);
// The default hashCode() implementation is based on memory address, which will be unique
int hash = info.clss.hashCode();
return hash;
}
ok - das aß mein Mittagessen für 2 Wochen.Ich habe nicht gefunden, dass das oben genannte oben genau wie gezeigt für mich funktionierte.Ich verwende Android Studio 3.5.1, falls dies ankommt.
Was folgt, ist mein FragmentPagerAdapter-Code in seiner Gesamtheit.Es enthält am meisten alles, was Sie brauchen sollten.Der Fragmentcode ist für unabhängig von jedem Ihrer Fragmente ziemlich unkompliziert.Aber lassen Sie mich wissen, ob mehr benötigt wird oder wenn Sie Fragen haben.
Wenn Sie auch Kommentare haben oder Fehlern finden, posten Sie bitte einen Kommentar.Ich hoffe, das hilft anderen. generasacodicetagpre.