2012-11-16 3 views
4

J'essaie de mettre un FragmentTabHost en bas de l'écran. Il ya quelque temps, j'étais capable de le faire avec TabHost régulier (suivant this thread), mais maintenant cela ne fonctionne pas pour moi.Android: Onglets en bas avec FragmentTabHost

Y a-t-il un moyen de faire cela?

Merci!

+0

Tous les conseils que j'ai trouvé consiste à utiliser la mise en page XML attributs, comme décrit dans ce fil. Mais avec un FragmentTabHost, ces mises en page ne sont pas utilisées. Peut-être que cela doit être fait avec du code? Je ne sais pas quelle fonction appeler. – jamis0n

+1

Si vous souhaitez suivre les consignes de conception Android, vous ne devez pas utiliser les barres d'onglets du bas. Voir http://developer.android.com/design/patterns/pure-android.html – pegel

+0

J'ai répondu dans le lien suivant .http: //stackoverflow.com/a/14853097/874752 –

Répondre

0

Enfin j'ai suivi ce tutoriel: Android Tabs with Fragments

J'ai donné avec FragmentTabHost, cela est plus facile (AMHA) à mettre en œuvre, et j'ai pu mettre le tabWidget sur le fond sans effort.

+0

l'exemple montre l'onglet en haut. Pas au bas –

6

Je suis finalement arrivé au fond de la question. Il y a un problème avec FragmentTabHost.java qui créera toujours un élément TabHost pour vous, peu importe ce que vous définissez en XML et gonflez à l'avance. En tant que tel, j'ai commenté cette partie du code lors de l'écriture de ma propre version de FragmentTabHost.java.

Assurez-vous d'utiliser votre nouvelle version de cela dans votre mise en page XML, <com.example.app.MyFragmentTabHost

Et bien sûr gonflez:

Fragment1.java:

mTabHost = (MyFragmentTabHost) view.findViewById(android.R.id.tabhost); 
mTabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent); 

MyFragmentTabHost.java:

package com.example.app; 

import java.util.ArrayList; 

import android.content.Context; 
import android.content.res.TypedArray; 
import android.os.Bundle; 
import android.os.Parcel; 
import android.os.Parcelable; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentTransaction; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.FrameLayout; 
import android.widget.TabHost; 

/** 
* Special TabHost that allows the use of {@link Fragment} objects for 
* its tab content. When placing this in a view hierarchy, after inflating 
* the hierarchy you must call {@link #setup(Context, FragmentManager, int)} 
* to complete the initialization of the tab host. 
* 
*/ 
public class MyFragmentTabHost extends TabHost 
    implements TabHost.OnTabChangeListener { 
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); 
private FrameLayout mRealTabContent; 
private Context mContext; 
private FragmentManager mFragmentManager; 
private int mContainerId; 
private TabHost.OnTabChangeListener mOnTabChangeListener; 
private TabInfo mLastTab; 
private boolean mAttached; 

static final class TabInfo { 
    private final String tag; 
    private final Class<?> clss; 
    private final Bundle args; 
    private Fragment fragment; 

    TabInfo(String _tag, Class<?> _class, Bundle _args) { 
     tag = _tag; 
     clss = _class; 
     args = _args; 
    } 
} 

static class DummyTabFactory implements TabHost.TabContentFactory { 
    private final Context mContext; 

    public DummyTabFactory(Context context) { 
     mContext = context; 
    } 

    @Override 
    public View createTabContent(String tag) { 
     View v = new View(mContext); 
     v.setMinimumWidth(0); 
     v.setMinimumHeight(0); 
     return v; 
    } 
} 

static class SavedState extends BaseSavedState { 
    String curTab; 

    SavedState(Parcelable superState) { 
     super(superState); 
    } 

    private SavedState(Parcel in) { 
     super(in); 
     curTab = in.readString(); 
    } 

    @Override 
    public void writeToParcel(Parcel out, int flags) { 
     super.writeToParcel(out, flags); 
     out.writeString(curTab); 
    } 

    @Override 
    public String toString() { 
     return "FragmentTabHost.SavedState{" 
       + Integer.toHexString(System.identityHashCode(this)) 
       + " curTab=" + curTab + "}"; 
    } 

    public static final Parcelable.Creator<SavedState> CREATOR 
      = new Parcelable.Creator<SavedState>() { 
     public SavedState createFromParcel(Parcel in) { 
      return new SavedState(in); 
     } 

     public SavedState[] newArray(int size) { 
      return new SavedState[size]; 
     } 
    }; 
} 

public MyFragmentTabHost(Context context) { 
    // Note that we call through to the version that takes an AttributeSet, 
    // because the simple Context construct can result in a broken object! 
    super(context, null); 
    initFragmentTabHost(context, null); 
} 

public MyFragmentTabHost(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    initFragmentTabHost(context, attrs); 
} 

private void initFragmentTabHost(Context context, AttributeSet attrs) { 
    TypedArray a = context.obtainStyledAttributes(attrs, 
      new int[] { android.R.attr.inflatedId }, 0, 0); 
    mContainerId = a.getResourceId(0, 0); 
    a.recycle(); 

    super.setOnTabChangedListener(this); 


    /*** REMOVE THE REST OF THIS FUNCTION ***/ 
    /*** findViewById(android.R.id.tabs) IS NULL EVERY TIME ***/ 
} 

/** 
* @deprecated Don't call the original TabHost setup, you must instead 
* call {@link #setup(Context, FragmentManager)} or 
* {@link #setup(Context, FragmentManager, int)}. 
*/ 
@Override @Deprecated 
public void setup() { 
    throw new IllegalStateException(
      "Must call setup() that takes a Context and FragmentManager"); 
} 

public void setup(Context context, FragmentManager manager) { 
    super.setup(); 
    mContext = context; 
    mFragmentManager = manager; 
    ensureContent(); 
} 

public void setup(Context context, FragmentManager manager, int containerId) { 
    super.setup(); 
    mContext = context; 
    mFragmentManager = manager; 
    mContainerId = containerId; 
    ensureContent(); 
    mRealTabContent.setId(containerId); 

    // We must have an ID to be able to save/restore our state. If 
    // the owner hasn't set one at this point, we will set it ourself. 
    if (getId() == View.NO_ID) { 
     setId(android.R.id.tabhost); 
    } 
} 

private void ensureContent() { 
    if (mRealTabContent == null) { 
     mRealTabContent = (FrameLayout)findViewById(mContainerId); 
     if (mRealTabContent == null) { 
      throw new IllegalStateException(
        "No tab content FrameLayout found for id " + mContainerId); 
     } 
    } 
} 

@Override 
public void setOnTabChangedListener(OnTabChangeListener l) { 
    mOnTabChangeListener = l; 
} 

public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { 
    tabSpec.setContent(new DummyTabFactory(mContext)); 
    String tag = tabSpec.getTag(); 

    TabInfo info = new TabInfo(tag, clss, args); 

    if (mAttached) { 
     // If we are already attached to the window, then check to make 
     // sure this tab's fragment is inactive if it exists. This shouldn't 
     // normally happen. 
     info.fragment = mFragmentManager.findFragmentByTag(tag); 
     if (info.fragment != null && !info.fragment.isDetached()) { 
      FragmentTransaction ft = mFragmentManager.beginTransaction(); 
      ft.detach(info.fragment); 
      ft.commit(); 
     } 
    } 

    mTabs.add(info); 
    addTab(tabSpec); 
} 

@Override 
protected void onAttachedToWindow() { 
    super.onAttachedToWindow(); 

    String currentTab = getCurrentTabTag(); 

    // Go through all tabs and make sure their fragments match 
    // the correct state. 
    FragmentTransaction ft = null; 
    for (int i=0; i<mTabs.size(); i++) { 
     TabInfo tab = mTabs.get(i); 
     tab.fragment = mFragmentManager.findFragmentByTag(tab.tag); 
     if (tab.fragment != null && !tab.fragment.isDetached()) { 
      if (tab.tag.equals(currentTab)) { 
       // The fragment for this tab is already there and 
       // active, and it is what we really want to have 
       // as the current tab. Nothing to do. 
       mLastTab = tab; 
      } else { 
       // This fragment was restored in the active state, 
       // but is not the current tab. Deactivate it. 
       if (ft == null) { 
        ft = mFragmentManager.beginTransaction(); 
       } 
       ft.detach(tab.fragment); 
      } 
     } 
    } 

    // We are now ready to go. Make sure we are switched to the 
    // correct tab. 
    mAttached = true; 
    ft = doTabChanged(currentTab, ft); 
    if (ft != null) { 
     ft.commit(); 
     mFragmentManager.executePendingTransactions(); 
    } 
} 

@Override 
protected void onDetachedFromWindow() { 
    super.onDetachedFromWindow(); 
    mAttached = false; 
} 

@Override 
protected Parcelable onSaveInstanceState() { 
    Parcelable superState = super.onSaveInstanceState(); 
    SavedState ss = new SavedState(superState); 
    ss.curTab = getCurrentTabTag(); 
    return ss; 
} 

@Override 
protected void onRestoreInstanceState(Parcelable state) { 
    SavedState ss = (SavedState)state; 
    super.onRestoreInstanceState(ss.getSuperState()); 
    setCurrentTabByTag(ss.curTab); 
} 

@Override 
public void onTabChanged(String tabId) { 
    if (mAttached) { 
     FragmentTransaction ft = doTabChanged(tabId, null); 
     if (ft != null) { 
      ft.commit(); 
     } 
    } 
    if (mOnTabChangeListener != null) { 
     mOnTabChangeListener.onTabChanged(tabId); 
    } 
} 

private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) { 
    TabInfo newTab = null; 
    for (int i=0; i<mTabs.size(); i++) { 
     TabInfo tab = mTabs.get(i); 
     if (tab.tag.equals(tabId)) { 
      newTab = tab; 
     } 
    } 
    if (newTab == null) { 
     throw new IllegalStateException("No tab known for tag " + tabId); 
    } 
    if (mLastTab != newTab) { 
     if (ft == null) { 
      ft = mFragmentManager.beginTransaction(); 
     } 
     if (mLastTab != null) { 
      if (mLastTab.fragment != null) { 
       ft.detach(mLastTab.fragment); 
      } 
     } 
     if (newTab != null) { 
      if (newTab.fragment == null) { 
       newTab.fragment = Fragment.instantiate(mContext, 
         newTab.clss.getName(), newTab.args); 
       ft.add(mContainerId, newTab.fragment, newTab.tag); 
      } else { 
       ft.attach(newTab.fragment); 
      } 
     } 

     mLastTab = newTab; 
    } 
    return ft; 
} 
} 
+0

J'ai une erreur sur "mTabHost = (MyFragmentTabHost) view.findViewById (android.R.id.tabhost);". Pouvez-vous expliquer pourquoi cela? – Akhil

+0

S'il vous plaît poster votre question dans un nouveau fil avec le code et je serai heureux d'aider :) – jamis0n

+0

C'était un excellent travail! Merci! – JPMagalhaes

2

Placez ce code une fois que vous avez configuré et ajouté les onglets à votre FragmentTabHost, il va supprimer, puis ajouter les onglets en tant que dernier enfant dans le TabHost. (Testé avec android.support.v13.app.FragmentTabHost gonflé de xml et mis en place avec getChildFragmentManager() dans un fragment imbriqué)

View tabs = (TabWidget) mTabHost.findViewById(android.R.id.tabs); 
ViewGroup parent = (ViewGroup) mTabHost.getChildAt(0); 
parent.removeView(tabs); 
parent.addView(tabs); 
Questions connexes