TabWidget changr bottom line color - android

i want to change color of tabwidget background. How can i change color of blue line??
My code is:
public class MainActivityNew extends ActionBarActivity implements
ActionBar.TabListener {
private FragmentTabHost mTabHost;
private int oldButtonId = 1;
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private Database db;
private FrameLayout frame;
// Tab titles
private String[] tabs = {"Новости", "Мои купоны"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
private void initialization() {
frame = (FrameLayout) findViewById(R.id.content_frame);
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getSupportActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(), actionBar, frame, viewPager);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.content_frame);
///////////////Add now 16/01/2014
Bundle b = new Bundle();
mTabHost.getTabWidget().setDividerDrawable(R.color.tabTransparent);
View tabIndicator = LayoutInflater.from(this).inflate(R.layout.tab_indicator_new,mTabHost.getTabWidget(), false);
ImageView icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageDrawable(getResources().getDrawable(R.drawable.news_icon_selector));
mTabHost.addTab(mTabHost.newTabSpec("1")
.setIndicator(tabIndicator),
FragmentNews.class, b);
tabIndicator = LayoutInflater.from(this).inflate(R.layout.tab_indicator_new,mTabHost.getTabWidget(), false);
icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageDrawable(getResources().getDrawable(R.drawable.catalog_icon_selector));
mTabHost.addTab(mTabHost.newTabSpec("2")
.setIndicator(tabIndicator), FragmentCatalog.class, b);
tabIndicator = LayoutInflater.from(this).inflate(R.layout.tab_indicator_center,mTabHost.getTabWidget(), false);
icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageDrawable(getResources().getDrawable(R.drawable.my_cards_icon_selector));
mTabHost.addTab(mTabHost.newTabSpec("3").
setIndicator(tabIndicator),FragmentMyCards.class, b);
tabIndicator = LayoutInflater.from(this).inflate(R.layout.tab_indicator_new,mTabHost.getTabWidget(), false);
icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageDrawable(getResources().getDrawable(R.drawable.near_icon_selector));
mTabHost.addTab(mTabHost.newTabSpec("4").
setIndicator(tabIndicator),FragmentNear.class, b);
tabIndicator = LayoutInflater.from(this).inflate(R.layout.tab_indicator_new,mTabHost.getTabWidget(), false);
icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageDrawable(getResources().getDrawable(R.drawable.settings_icon_selector));
mTabHost.addTab(mTabHost.newTabSpec("5").
setIndicator(tabIndicator), FragmentSettingsPartOne.class, b);
mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
#Override
public void onTabChanged(String tabId) {
setActivityView(Integer.valueOf(tabId));
Log.d("tabs", "tabID=" + tabId);
}
});
////////////////////end of adding
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
setButtonsColor(1, 3);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
viewPager.setCurrentItem(tab.getPosition());
}
public void setActivityView(int newButtonId) {
switch (newButtonId) {
case 1:
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.show();
viewPager.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, 0, 8.0f));
frame.setLayoutParams(new LinearLayout.LayoutParams(0, 0, 0f));
break;
default:
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.hide();
frame.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, 0, 8.0f));
viewPager.setLayoutParams(new LinearLayout.LayoutParams(0, 0, 0f));
break;
}
}
#Override
protected void onResume() {
initialization();
db = Database.getInstance(this);
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
super.onResume(); /
}
}
I have read this i try next
TabWidget widget = mTabHost.getTabWidget();
for(int i = 0; i < widget.getChildCount(); i++) {
View v = widget.getChildAt(i);
// Look for the title view to ensure this is an indicator and not a divider.
TextView tv = (TextView)v.findViewById(android.R.id.title);
if(tv == null) {
continue;
}
// v.setBackgroundResource(R.drawable.your_tab_selector_drawable);
v.setBackgroundColor(Color.RED);
}
But it only change background color of bottom tabs.

Use android.support.design.widget.TabLayout instead
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/actionbar"
app:tabIndicatorColor="#color/tab_indicator_color" // this is what you want
app:tabIndicatorHeight="3dp" // tab indicator height
app:tabSelectedTextColor="#color/white"
app:tabTextColor="#color/font_color_white70"/>
This has backward compatibility also

Related

ActionBar Tab with Custom View not switching

I have the following ActionBar with custom tabs:
If I want to switch tabs by clicking in the red areas below it works:
but if I click inside the custom view it doesn't switch the view (i.e. if i click in the below red areas):
(apologies for the bad drawings! -_-)
Here's the code (including setOnClickListener's) which I have tried:
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
if(actionBar != null) {
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
final int position = i;
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
View rootView = layoutInflater.inflate(R.layout.tabs_add_item, null);
if(rootView != null) {
FontTextView tv = (FontTextView) rootView.findViewById(R.id.tab_title);
tv.setText(mSectionsPagerAdapter.getPageTitle(i));
RelativeLayout rl = (RelativeLayout) rootView.findViewById(R.id.tab);
rl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("ADDITEM", "layout Clicked");
mViewPager.setCurrentItem(position);
}
});
rootView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("ADDITEM", "view Clicked");
mViewPager.setCurrentItem(position);
}
});
actionBar.addTab(
actionBar.newTab()
.setCustomView(rootView)
.setTabListener(this));
}
}
}
The relevant setTabListener's:
#Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
Log.i("ADDITEM", "TAB CLICKED");
mViewPager.setCurrentItem(tab.getPosition());
View v = tab.getCustomView();
if(v != null){
FontTextView tv = (FontTextView) v.findViewById(R.id.tab_title);
tv.setCustomFont(getApplicationContext(), "fonts/seguisb.ttf");
}
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
View v = tab.getCustomView();
if(v != null){
FontTextView tv = (FontTextView) v.findViewById(R.id.tab_title);
tv.setCustomFont(getApplicationContext(), "fonts/segoeui.ttf");
}
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
and of course the custom tab layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tab"
xmlns:vers="http://schemas.android.com/apk/res-auto"
android:clickable="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:padding="0dp">
<uk.verscreative.smart5_a_day.views.widget.FontTextView
android:id="#+id/tab_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:inputType="textCapCharacters"
android:textColor="#color/white"
android:text="TEXT"
android:singleLine="true"
vers:customTypeface="fonts/segoeui.ttf"
/>
</RelativeLayout>
If you guys need any more detail let me know! Thanks in advance!
I realised that my custom text view was match_parenting so I changed the setOnClickListener to this:
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
final int position = i;
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
View rootView = layoutInflater.inflate(R.layout.tabs_add_item, null);
if(rootView != null) {
FontTextView tv = (FontTextView) rootView.findViewById(R.id.tab_title);
tv.setText(mSectionsPagerAdapter.getPageTitle(i));
tv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mViewPager.setCurrentItem(position);
}
});
actionBar.addTab(
actionBar.newTab()
.setCustomView(rootView)
.setTabListener(this));
}
}
add it works now!

ViewPager not showing page content / not refreshing after changing the view

I am using ViewPager / FragmentPagerAdapter in one of my application fragments to display different listviews in each page (see the picture below) :
The problem is that after i change the current view (Fragment) and i reopen it again, the listview isn't rendered (see the picture below) :
The behaviour is random, sometimes the listview are shown when i slide between different tabs/pages.
Here is my fragment code :
public class AstucesFragment extends Fragment implements ActionBar.TabListener {
ActionBar actionBar;
AppSectionsPagerAdapter mAppSectionsPagerAdapter;
ViewPager mViewPager;
public static String[] tabslist = new String[5];
public AstucesFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_astuces, container, false);
tabslist[0] = getActivity().getResources().getString(R.string.astuces_quotidien);
tabslist[1] = getActivity().getResources().getString(R.string.astuces_resto);
tabslist[2] = getActivity().getResources().getString(R.string.astuces_loisirs);
tabslist[3] = getActivity().getResources().getString(R.string.astuces_transports);
tabslist[4] = getActivity().getResources().getString(R.string.astuces_tous);
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getActivity().getSupportFragmentManager());
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mViewPager = (ViewPager) view.findViewById(R.id.astuces_pager);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
actionBar.addTab(
actionBar.newTab()
.setCustomView(R.layout.fragment_astuces_tabs_quotidien)
.setTabListener(this));
actionBar.addTab(
actionBar.newTab()
.setCustomView(R.layout.fragment_astuces_tabs_resto)
.setTabListener(this));
actionBar.addTab(
actionBar.newTab()
.setCustomView(R.layout.fragment_astuces_tabs_loisirs)
.setTabListener(this));
actionBar.addTab(
actionBar.newTab()
.setCustomView(R.layout.fragment_astuces_tabs_transports)
.setTabListener(this));
actionBar.addTab(
actionBar.newTab()
.setCustomView(R.layout.fragment_astuces_tabs_tous)
.setTabListener(this));
return view;
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
Log.i("AstucesFragment","onTabSelected()");
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
Log.i("AstucesFragment","onTabReselected()");
}
/**
* A {#link android.support.v4.app.FragmentPagerAdapter} that returns a fragment corresponding to one of the primary
* sections of the app.
*/
public static class AppSectionsPagerAdapter extends FragmentPagerAdapter {
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Log.i("AppSectionsPagerAdapter","Page ID : "+i);
// The other sections of the app are dummy placeholders.
Fragment fragment = new AstucesListFragment();
Bundle args = new Bundle();
args.putString(AstucesListFragment.ARG_PAGE_CAT, tabslist[i]);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return tabslist.length;
}
#Override
public CharSequence getPageTitle(int position) {
return tabslist[position];
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
}
/**
* A dummy fragment representing a section of the app, but that simply displays dummy text.
*/
public static class AstucesListFragment extends Fragment {
public static final String ARG_PAGE_CAT = "page_cat";
private List<Astuce> astuceList = new ArrayList<Astuce>();
private ListView listView;
private AstuceAdapter adapter;
private AstuceDAO astuceDAO;
public AstucesListFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_astuces_page, container, false);
Bundle args = getArguments();
Log.i("AstucesListFragment","onCreateView()");
String theme = "";
if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_quotidien)) theme = "Q";
else if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_resto)) theme = "R";
else if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_loisirs)) theme = "L";
else if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_transports)) theme = "T";
else theme = "";
astuceDAO = new AstuceDAO();
astuceList = astuceDAO.findAstuceByTheme(theme);
listView = (ListView) rootView.findViewById(R.id.astuces_list);
adapter = new AstuceAdapter(getActivity(), astuceList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
return rootView;
}
}
}
How can i fix this problem ?
If you want your fragments to maintain its state even after changing the tabs,
Try this,
mViewPager.setOffscreenPageLimit(5); //as you have 5 fragments
But this will make the activity to initialize all the fragments at the same time when the activity is invoked.
Another method is to use FragmentStatePagerAdapter instead of FragmentPagerAdapter. Refer,
http://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html
You are not comparing strings correctly. When comparing two strings you need to use equals() method instead of == operator. So in onCreateView() in AstucesListFragment replace
if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_quotidien)) theme = "Q";
else if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_resto)) theme = "R";
else if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_loisirs)) theme = "L";
else if (args.getString(ARG_PAGE_CAT) == getString(R.string.astuces_transports)) theme = "T";
else theme = "";
with
if (args.getString(ARG_PAGE_CAT).equals(getString(R.string.astuces_quotidien))) theme = "Q";
else if (args.getString(ARG_PAGE_CAT).equals( getString(R.string.astuces_resto))) theme = "R";
else if (args.getString(ARG_PAGE_CAT).equals( getString(R.string.astuces_loisirs))) theme = "L";
else if (args.getString(ARG_PAGE_CAT).equals( getString(R.string.astuces_transports))) theme = "T";
else theme = "";
This may solve your problem as the results of == operators will be inconsistent as both the strings may or may not point to same object.

How to change every tab indicator different Color?

I am working on Android app that have 6 tabs and I want each tab indicator to have a different color
I am using styling System but cant change all tab indicators back
I want something like this
Please note that I'm using this code for tabs in activity:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "tab1","tab2","tab3","tab4","tab5","tab6" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
}
for (int i=0;i<=actionBar.getTabCount();i++)
{
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}

ActionBar Tabs are not displayed

I'm implementing ActionBar tabs according to official guide.
I have a fragment that is added to activity. In that fragment I'm creating tabs:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
Tab tab = actionBar.newTab()
.setText("One")
.setTabListener(new TabListener<DemoFragment>(
this, "1", DemoFragment.class));
actionBar.addTab(tab);
tab = actionBar.newTab()
.setText("Two")
.setTabListener(new TabListener<DemoFragment>(
this, "2", DemoFragment.class));
actionBar.addTab(tab);
}
But these tabs are never displayed. Nor content of DemoFragment. Even though at runtime getActionBar().getTabCount() returns correct count of tabs. And I see that DemoFragment is initialized. All I see is ActionBar.
What am I doing wrong?
I'm not using any support libraries as I'm developing for minSdk=14.
Update
IF YOUR NOT USING ANY SUPPORT LIBRARY THIS SHOULD WORK
otherwise you will have to use the getSupportActionBar() and above mentioned dependencies.
Try something more like this:
// Get the Instance of the Action Bar, set Navigation Mode, remove title
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
// One tab
actionBar.addTab(actionBar.newTab() .setText("One")
.setTabListener(new TabListener<DemoFragment>(
this, "1", DemoFragment.class)));
// Two tab
actionBar.addTab(actionBar.newTab()
.setText("Two")
.setTabListener(new TabListener<DemoFragment>(
this, "2", DemoFragment.class)));
Edit to Post - Working Code that I have used for a demo
Here is code from a demo Application That i wrote using Android sdk 14 Just like you are.
public class MainActivity extends Activity {
// String Titles
static String [] titles = {"Fragment 1", "Fragment 2"};
static String [] fragmentClasses = {Fragment1.class.getName(), Fragment2.class.getName()};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SimpleTabListener.SetUpTabNavigation(this, fragmentClasses, titles);
}
And here is the SimpleTabListener Class
public class SimpleTabListener implements TabListener {
Context m_context;
String m_fragmentClassName ;
Fragment m_fragment = null;
public SimpleTabListener(Context context, String tabFragmentClassName)
{
m_context = context;
m_fragmentClassName = tabFragmentClassName;
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft)
{
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
{
if(m_fragment == null)
{
m_fragment = Fragment.instantiate(m_context, m_fragmentClassName);
ft.add(android.R.id.content, m_fragment);
}else
{
ft.attach(m_fragment);
}
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
{
// TODO Auto-generated method stub
if(m_fragment != null){
// TODO Auto-generated method stub
ft.detach(m_fragment);
}
}
public static void SetUpTabNavigation(Activity activity, String [] classNames, String [] tabTitles){
ActionBar actionBar = activity.getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener listener;
for(int i = 0; i < tabTitles.length; i++)
{
listener = new SimpleTabListener(activity, classNames[i]);
actionBar.addTab(actionBar.newTab().setText(tabTitles[i]).setTabListener(listener));
}
}
}
Frament1.class
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.fragment_1, container, false);
}
}
Fragment 2.class
public class Fragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.fragment2, container, false);
}
}

(ActionBar) Tabs + Pager + detail Fragments inside ViewPager container

For ActionBarSherlock I would like to have (Action Bar) Tabs + Pager. I use Fragments inside that pager container. I already got the examples of http://actionbarsherlock.com/ working, but I can't manage to get a details fragment inside that pager container when I would click on let's say a listitem in the first fragment.
Is it impossible to have something like this:
Activity with Tabs and pager container
Fragment A inside pager container under Tab1
Click on something in Fragment A and show Fragment B in same pager container under Tab1.
Fragment A is then not visible, only Fragment B is visible, but also all the Tabs.
At the moment I think only a new activity (which would hold Fragment B inside it) can be started after clicking something in Fragment A.
Here is my solution for the (Tabs + Fragment + ViewPager) it is works for me as i wanted,
hope that works for you as well
here is the xml file
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="5" />
<FrameLayout
android:id="#+id/fragment_details"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="4.3" />
</LinearLayout>
here is the code for MainActivity.java I'll post relevant code only so you'll have to manage it
public class MainActivity extends FragmentActivity implements
DialogInterface.OnDismissListener, TabDataResponder {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
artistTab = getSupportActionBar().newTab().setText(
R.string.tab_name_artist);
albumTab = getSupportActionBar().newTab().setText(
R.string.tab_name_album);
songTab = getSupportActionBar().newTab().setText(
R.string.tab_name_songs);
map = new HashMap<String, Integer>();
mViewPager = (ViewPager) findViewById(R.id.pager);
FrameLayout deatil = (FrameLayout) findViewById(R.id.fragment_details);
mDualPane = (deatil != null) && (deatil.getVisibility() == View.VISIBLE);
mTabsAdapter = new TabsAdapter(this, getSupportActionBar(), mViewPager);
if (savedInstanceState != null) {
flag = true;
index = savedInstanceState.getInt("index");
}
setUpTabView();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("index", getSupportActionBar()
.getSelectedNavigationIndex());
}
private void setUpTabView() {
mTabsAdapter.addTab(artistTab, ArtistFragment.class, null);
mTabsAdapter.addTab(albumTab, AlbumFragment.class, null);
mTabsAdapter.addTab(songTab, SongFragment.class, null);
getSupportActionBar().setSelectedNavigationItem(index);
}
public static class TabsAdapter extends FragmentPagerAdapter implements
ViewPager.OnPageChangeListener, ActionBar.TabListener {
private FragmentActivity mContext;
private ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<String> mTabs = new ArrayList<String>();
private TabDataResponder responder;
public TabsAdapter(FragmentActivity activity, ActionBar actionBar,
ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = actionBar;
mViewPager = pager;
// TabDataResponder is an interface which is implemented in MainActivity
// You can find implementation # the last
responder = (TabDataResponder) activity;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
//I have used map to save state of the fragment
map.put(SongFragment.TYPE_FRAGMENT.trim(), 0);
map.put(AlbumFragment.TYPE_FRAGMENT.trim(), 0);
map.put(ArtistFragment.TYPE_FRAGMENT.trim(), 0);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
mTabs.add(clss.getName());
// mArgs.add(args);
mActionBar.addTab(tab.setTabListener(this));
notifyDataSetChanged();
}
#Override
public int getCount() {
return mTabs.size();
}
#Override
public Fragment getItem(int position) {
return Fragment
.instantiate(mContext, mTabs.get(position), /*
* mArgs.get(
* position)
*/null);
}
#Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Log.i(TAG, "PageSelected....");
mActionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
Log.i(TAG, "ScrollSateChanged....");
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
String a = null;
if (mDualPane) {
a = mTabs.get(tab.getPosition());
responder.loadData(a, map.get(a));
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
Log.i(TAG, "Tab is released now....");
}
}
#Override
public void onDismiss(DialogInterface dialog) {
setUpTabView();
}
//This interface must be call from fragment class
//# the time of event you want to show detail
// pass the class name in the type argument using class.getName() method
#Override
public void loadData(String type, int index) {
DetailFragment viewer = (DetailFragment) getSupportFragmentManager()
.findFragmentById(R.id.fragment_details);
if (mDualPane) {
if (viewer == null || viewer.getShownIndex() != index
|| viewer.getTypeFragment() != type) {
DetailFragment df = DetailFragment.newInstance(index, type);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_details, df)
.setTransition(
FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.commit();
map.put(type.trim(), index);
}
} else {
Intent intent = new Intent();
intent.setClass(MainActivity.this, DetailActivity.class);
intent.putExtra("index", index);
intent.putExtra("type", type);
startActivity(intent);
}
}
}
and here is how i deal with detail fragment not very efficient but kind of working
public class DetailFragment extends Fragment{
public static DetailFragment newInstance(int index, String TYPE_FRAGMENT) {
DetailFragment f = new DetailFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
args.putString("type", TYPE_FRAGMENT);
f.setArguments(args);
return f;
}
public int getShownIndex() {
return getArguments().getInt("index", 0);
}
public String getTypeFragment(){
String a = getArguments().getString("type");
return a;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//template is blank layout
View view = inflater.inflate(R.layout.template, container, false);
if(getTypeFragment().equals(ArtistFragment.TYPE_FRAGMENT)){
view = null;
view = inflater.inflate(R.layout.artist_details, container, false);
//....
}
else if(getTypeFragment().equals(AlbumFragment.TYPE_FRAGMENT)){
//do's for album fragment
}
else if(getTypeFragment().equals(SongFragment.TYPE_FRAGMENT)){
//do's for song fragment
}
return view;
}
}
do not save the state of tab in their individual fragment it will conflict, we are already doing it here
EDIT:
Cheered too soon. Now the details_container is not a viewpager and I cannot use it to 'swipe tabs'.
Found it! Just had to define two FrameLayouts, with in the first one the ViewPager and in the second the details fragments can be 'loaded'. This is done by adding fragments dynamically and replace them.
First the two FrameLayouts:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fadingEdge="none" >
<FrameLayout
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
<FrameLayout
android:id="#+id/details_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Then replace a fragment dynamically:
// Create new fragment and transaction
Fragment detailsFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment container view with this fragment
// and add the transaction to the back stack
transaction.replace(R.id.details_container, detailsFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Very simple and I don't understand why it took me hours to figure this out..
I still did not find a possibility to have a Pager container where fragments should be loaded in and also keep the (ActionBar) Tabs. I have however found a really dirty solution to acomplish this, with starting intens (Main Activity with the Tabs) and finishing the previous ones when the backbutton doesn't need it anymore.
I adapted the code from ABS: Support Demos - Tabs and Pager. But again it's really dirty:
LoaderCursorSupport.CursorLoaderListFragment under Tab2
#Override public void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent();
intent.setClass(getActivity(), ActionBarTabsPager.class);
intent.putExtra("index", position);
intent.putExtra("fragment", "details");
intent.putExtra("tab", 1);
ActionBarTabsPager.mPreviousActivity = getActivity();
startActivity(intent);
ActionBarTabsPager (Main Activity with Tabs)
public class ActionBarTabsPager extends FragmentActivity {
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
static Activity mPreviousActivity;
static Activity mActivity;
static int mTabPosition = -1;
static Boolean mTabRefreshed = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.actionbar_tabs_pager);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = getSupportActionBar().newTab().setText("Tab 1");
ActionBar.Tab tab2 = getSupportActionBar().newTab().setText("Tab 2");
ActionBar.Tab tab3 = getSupportActionBar().newTab().setText("Tab 3");
ActionBar.Tab tab4 = getSupportActionBar().newTab().setText("Tab 4");
String fragment = "";
try {
Bundle bundle = this.getIntent().getExtras();
fragment = bundle.getString("fragment");
mTabPosition = bundle.getInt("tab");
} catch (Exception ex) {
}
mViewPager = (ViewPager) findViewById(R.id.pager);
mTabsAdapter = new TabsAdapter(this, getSupportActionBar(), mViewPager);
mTabsAdapter.addTab(tab1, FragmentStackSupport.CountingFragment.class);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ECLAIR) {
mTabsAdapter.addTab(tab2, FragmentStackSupport.CountingFragment.class);
mTabsAdapter.addTab(tab3, FragmentStackSupport.CountingFragment.class);
mTabsAdapter.addTab(tab4, FragmentStackSupport.CountingFragment.class);
} else {
if (!fragment.contains("details")) {
mTabsAdapter.addTab(tab2, LoaderCursorSupport.CursorLoaderListFragment.class);
} else {
mTabsAdapter.addTab(tab2, ExampleFragment.class);
}
mTabsAdapter.addTab(tab3, LoaderCustomSupport.AppListFragment.class);
mTabsAdapter.addTab(tab4, LoaderThrottleSupport.ThrottledLoaderListFragment.class);
}
if (savedInstanceState != null) {
getSupportActionBar().setSelectedNavigationItem(savedInstanceState.getInt("index"));
}
if (mTabPosition > -1) {
mTabsAdapter.setPrimaryItem(mTabPosition);
mActivity = this;
}
}
Inside this Class there's a TabsAdapter
public static class TabsAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, ActionBar.TabListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<String> mTabs = new ArrayList<String>();
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mTabPosition > -1 && mTabRefreshed) {
int tabPosition = tab.getPosition();
if (mTabPosition != tabPosition) {
if (mPreviousActivity != null) {
mPreviousActivity.finish();
mTabRefreshed = false;
mPreviousActivity = null;
mTabPosition = -1;
Intent intent = new Intent();
intent.setClass(mContext, ActionBarTabsPager.class);
intent.putExtra("fragment", "home");
intent.putExtra("tab", tabPosition);
mActivity.startActivity(intent);
mActivity.finish();
}
}
}
mViewPager.setCurrentItem(tab.getPosition());
}
Can this be done simpler? Or should I just give up on having Tabs together with fragment history? This was done before Android 3.0 with ActivityGroups and Activities, but it seems this can't be done with fragments.
I found the other good example of the same implementation in hear... https://github.com/UweTrottmann/SeriesGuide
In this example under package com.battlelancer.seriesguide.ui
you can find UpcomingRecentActivity.java, and UpcomingFragment.java
and layout upcoming_multipan.xml
this example works for me...
I got one problem while adding different content for detail-fragment the different tabs, it gives me class-cast-exception
so i implemented a common detalFragment class and created separate layout in onCreateView method
but the only one problem i found is layout is not changing on tab switched, may be need to do it by implementing some listener
I'll tell you when i found the answer.

Categories

Resources