I am implementing some code from Google (the SlidingTabLayout
and SlidingTabStrip
, found easily online) and I'm trying to use it with ViewPager
to get sliding tabs in my Fragment
. The thing is, I am using PagerAdapter
as an extension in my main tab fragment class, which is used for my adapter to show the view of what's in the tabs. I am able to get a basic view of the tabs working in my fragment CuteCollectionFragment.java
, but when I click on them, they take usually 2 clicks for the new tab to be highlighted, plus you cannot swipe to get to the new tab. My suspicion is that because the base code, which is normally meant for a main activity, must be put in a Fragment
(because of my Navigation Drawer
), it is conflicting with my Navigation Drawer
, which is already sliding. But that's just a guess.
Basically, I must use Fragments
, not activities. But how are they conflicting and how do I fix that? All examples online I found want you to use FragmentPagerAdapter
instead of PagerAdapter
as the extension for my adapter, but I can't do that because it requires you to use a FragmentManager
that is support v.4. I can't use that in my CuteMainActivity
(the one that has my nav drawer code) because then I can't click on each nav drawer menu item and go to a Fragment
, I get red errors on my switch statement on the Fragment fragment
part, which says my fragments must all extend FragmentActivity
, but they can't with a nav drawer, they MUST extend Fragment
!
Anyway, gosh this is so confusing. Mainly I just want to know 2 things:
Why are my tabs not sliding (and why do they require 2 clicks)
How do I hook up my inner
TabsAdapter
class to show my tab classes (which are allFragments
). I have my tab fragment classes/xmls all ready (e.g. PhotoTab.java, VideoTab.java, etc), but how do I hook those up to their views in the tabs?
Here is my entire project if you wanted to just run and have a look for yourself. ICollectCute app
I will only include below my Fragment
that I am trying to put the slider tab code in, plus the xmls they draw from. If you need more files, let me know. The only other ones you might need (but probably not) are the Google classes called SlidingTabLayout
and SlidingTabStrip
or perhaps my CuteMainActivity
where I put all the Navigation Drawer code. But the main place to look for additions/errors is my CuteCollectionFragment
class, since the sliding tabs need to implement there.
I had help getting the code I have from this S.O. post.
Thanks for your help!
CuteCollectionFragment.java
package org.azurespot.cutecollection;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.azurespot.R;
/**
* Created by mizu on 1/26/15.
*/
public class CuteCollectionFragment extends Fragment {
static final String LOG_TAG = "SlidingTabsBasicFragment";
private SlidingTabLayout mSlidingTabLayout;
private ViewPager mViewPager;
FragmentManager fragmentManager;
View photoView;
View videoView;
View audioView;
View textView;
private static final int PHOTO_TAB = 0;
private static final int VIDEO_TAB = 1;
private static final int AUDIO_TAB = 2;
private static final int TEXT_TAB = 3;
public CuteCollectionFragment(){}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_cute_collection,
container, false);
photoView = inflater.inflate(R.layout.photo_tab,
container, false);
videoView = inflater.inflate(R.layout.video_tab,
container, false);
audioView = inflater.inflate(R.layout.audio_tab,
container, false);
textView = inflater.inflate(R.layout.text_tab,
container, false);
// Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
fragmentManager = getActivity().getFragmentManager();
mViewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
mViewPager.setAdapter(new TabsAdapter());
mSlidingTabLayout = (SlidingTabLayout) rootView.findViewById(R.id.sliding_tabs);
mSlidingTabLayout.setViewPager(mViewPager);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//
}
class TabsAdapter extends PagerAdapter {
/**
* @return the number of pages (tabs) to display
*/
@Override
public int getCount() {
return 5;
}
/**
* @return true if the value returned from
* {@link #instantiateItem(ViewGroup, int)} is the same object
* as the {@link View} added to the {@link ViewPager}.
*/
@Override
public boolean isViewFromObject(View view, Object o) {
return o == view;
}
// BEGIN_INCLUDE (pageradapter_getpagetitle)
/**
* Return the title of the item at {@code position}. This is important
* as what this method returns is what is displayed in the
* {@link SlidingTabLayout}.
* <p>
* Here we construct one using the position value, but for real
* application the title should refer to the item's contents.
*/
@Override
public CharSequence getPageTitle(int position) {
return "Item " + (position + 1);
}
// END_INCLUDE (pageradapter_getpagetitle)
/**
* Instantiate the {@link View} which should be displayed at
* {@code position}. Here we inflate a layout from the apps resources
* and then change the text view to signify the position.
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
// Inflate a new layout from our resources
View view = getActivity().getLayoutInflater().inflate(R.layout.pager_item,
container, false);
// Add the newly created View to the ViewPager
container.addView(view);
// Retrieve a TextView from the inflated View, and update it's text
TextView title = (TextView) view.findViewById(R.id.item_title);
title.setText(String.valueOf(position + 1));
// Log.i(LOG_TAG, "instantiateItem() [position: " + position + "]");
// Return the View
return view;
}
/**
* Destroy the item from the {@link ViewPager}. In our case this is
* simply removing the {@link View}.
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
// Log.i(LOG_TAG, "destroyItem() [position: " + position + "]");
}
}
}
fragment_cute_collection.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#2198bb" >
<!--<android.support.v7.widget.Toolbar-->
<!--xmlns:app="http://schemas.android.com/apk/res-auto"-->
<!--android:id="@+id/toolbar"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content"-->
<!--android:minHeight="?attr/actionBarSize"-->
<!--app:theme="@style/ThemeOverlay.AppCompat.ActionBar">-->
<org.azurespot.cutecollection.SlidingTabLayout
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!--</android.support.v7.widget.Toolbar>-->
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:background="@android:color/white" />
</RelativeLayout>
pager_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:id="@+id/item_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Page:"/>
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="80sp" />
</LinearLayout>
Here is one of my adapter classes. Each tab will have their own class and adapter class. This is one (although not hooked up with the CuteCollectionFragment.java yet, because I don't know how):
PhotoTab.java
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import org.azurespot.R;
/**
* Created by mizu on 2/8/15.
*/
public class PhotoTab extends Fragment{
private GridView gridView;
private GridViewPhotoAdapter gvPhotoAdapter;
public PhotoTab(){}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.photo_tab, container, false);
// with fragments, make sure you include the rootView when finding id
gridView = (GridView) v.findViewById(R.id.photo_grid);
// Create the Custom Adapter Object
gvPhotoAdapter = new GridViewPhotoAdapter(getActivity());
// Set the Adapter to GridView
gridView.setAdapter(gvPhotoAdapter);
return v;
}
}
The adapter for PhotoTab.java, GridViewPhotoAdapter.java
package org.azurespot.cutecollection;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import org.azurespot.R;
/**
* Created by mizu on 2/5/15.
*/
public class GridViewPhotoAdapter extends ArrayAdapter {
public Context context;
public ImageView mediaPhoto;
public GridViewPhotoAdapter(Context context) {
super(context, 0);
this.context = context;
}
public int getCount() {
return 24;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null)
{
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(R.layout.photo_grid_row, parent, false);
mediaPhoto = (ImageView) row.findViewById(R.id.photo_view);
mediaPhoto.setImageResource(R.drawable.ic_collection_add);
}
return row;
}
}