Android - tablayout with custom view tabs - drawable selector cannot be applied - android

I am trying to set up custom tabs in a tablayout using compile 'com.android.support:design:25.3.1' in gradle.
I want to use selectors so that when a tab is clicked it changes based on its state.
So I've tried the following unsuccessfully :
this is my activity xml:
<ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"
style="#style/MyCustomTabLayout"
/>
here is the style i use for the tabLayout:
<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
<item name="tabIndicatorColor">#android:color/transparent</item>
</style>
which hides the underline.
here is one of my selectors for my home tab:
here is the custom view i have for each tab:
<ImageView
android:id="#+id/iv_imgview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
tools:src="#drawable/home_tab_selector"
/>
<TextView
android:id="#+id/tv_tab_name"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="HOME"
/>
and here is the portion of code that creates the tablayout:
for (int i = 0; i < NUM_OF_TABS; i++)
tabLayout.addTab(tabLayout.newTab());
adapter = new LandingPagerAdapter(getApplicationContext(),getSupportFragmentManager(), tabLayout.getTabCount());
//Adding adapter to pager
viewPager.setAdapter(adapter);
tabLayout.addOnTabSelectedListener(this);
tabLayout.setupWithViewPager(viewPager);
// Iterate over all tabs and set the custom view
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
tab.setCustomView(adapter.getTabView(i));
}
tabLayout.getTabAt(0).select();
and finally here is the getTabView method responsible for applying the selector and custom view:
public class LandingPagerAdapter extends FragmentStatePagerAdapter {
private final Context context;
//integer to count number of tabs
int tabCount;
private Fragment mCurrentFragment;
private String[] tabTitles = new String[]{"Home", "tab2"};
// configure tab icons
int[] imageTabResId = {
R.drawable.home_tab_selector,
R.drawable.tab_two_selector,;
//Constructor to the class
public LandingPagerAdapter(Context context, FragmentManager fm, int tabCount) {
super(fm);
this.context = context;
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeContainerFragment tab1 = new TabHomeContainerFragment();
return tab1;
case 1:
TabTwoContainerFragment tab2 = new TabTwoContainerFragment();; //Todo: these should all be containers
return tab2;
default:
return null;
}
}
//Overriden method getCount to get the number of tabs
#Override
public int getCount() {
return tabCount;
}
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
public View getTabView(int position) {
// Given you have a custom layout in `res/layout/custom_tab.xml` with a TextView and ImageView
View v = LayoutInflater.from(context).inflate(R.layout.custom_landingpagetab, null);
TextView tv = (TextView) v.findViewById(R.id.tv_tab_name);
tv.setText(tabTitles[position]);
ImageView img = (ImageView) v.findViewById(R.id.iv_imgview);
img.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(),imageTabResId[position]));
return v;
}
}
Notice in getTabView i am setting the image resource to be the selector in the array in the class field.
but nothing happens on the device on api 24 i have been testing on.

I'm using support library 27.1.1 and facing the same problem. After some research I found that the state_selected must be defined clearly. See code below:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ic_chat_disabled" android:state_selected="false"/>
<item android:drawable="#drawable/ic_chat_enabled" android:state_selected="true"/>
</selector>
android:state_selected="false" is must have!

i ended up dropping the selector approach and just getting my customView from the tab. then i can change its view elements. i had a set of images in an array for selected and another for unselected.
then when the tabs switched i switch between the images based on tab position:
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
ImageView iv = (ImageView) tab.getCustomView().findViewById(R.id.iv_imgview);
TextView tv = (TextView) tab.getCustomView().findViewById(R.id.tv_tab_name);
iv.setImageDrawable(ContextCompat.getDrawable(this, imageTabResId_selected[tab.getPosition()]));
tv.setTextColor(ContextCompat.getColor(this, R.color.black));
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
ImageView iv = (ImageView) tab.getCustomView().findViewById(R.id.iv_imgview);
TextView tv = (TextView) tab.getCustomView().findViewById(R.id.tv_tab_name);
iv.setImageDrawable(ContextCompat.getDrawable(this, imageTabResId[tab.getPosition()]));
tv.setTextColor(ContextCompat.getColor(this, R.color.tabs_default_text));
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}

Related

How to design tabitems, without having them in a .xml file

I want to design my tabitems from a tablayout, but the tabs are not made in my .xml file. I don't know exactly where my tabs get generated, but it looks like it happens in a adapter
Normally you would make a drawable to design views like buttons, but can I do this also for tabs in a tabLayout?
My MainActivity doesn't create tabItems on startup, and I'm only gathering the data for the fragments here
#Override
protected void onCreate(Bundle savedInstance)
{
super.onCreate(savedInstance);
recentCardItems = new ArrayList<>();
followingCardItems = new ArrayList<>();
//This method sets the views in the abstract class DrawerLayoutActivity
setMenuLayoutElements(R.layout.activity_main, R.id.toolbar_main, R.id.drawer_layout_main);
setCardAdapterToReviewList();
configureFireStoreToLoadNewReviewsIntoList();
}
My adapter class, with the tabs "All" and "Following"
final int PAGE_COUNT = 2;
private String tabTitles[] = new String[] { "All", "Following" };
private Context context;
private List<CardItem> cardItemsRecent;
private List<CardItem> cardItemsFollowing;
private RecyclerViewFragment fragmentRecent;
private RecyclerViewFragment fragmentFollowing;
public RecyclerFragmentAdapter(FragmentManager fm, Context context, List<CardItem> cardItemsRecent, List<CardItem> cardItemsFollowing) {
super(fm);
this.context = context;
this.cardItemsRecent = cardItemsRecent;
this.cardItemsFollowing = cardItemsFollowing;
this.fragmentRecent = RecyclerViewFragment.newInstance(cardItemsRecent, R.layout.fragement_recyclerview_home, R.id.recyclerView);
this.fragmentFollowing = RecyclerViewFragment.newInstance(cardItemsFollowing, R.layout.fragment_recyclerview_following, R.id.reyclerViewFollowing);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
Fragment fragmentToReturn;
switch (position)
{
case 0:
fragmentToReturn = fragmentRecent;
break;
case 1:
fragmentToReturn = fragmentFollowing;
break;
default:
fragmentToReturn = null;
}
return fragmentToReturn;
}
//this getPageTitle method seems like it generates the titles of my tabs
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
public RecyclerViewFragment getFragmentRecent() {
return fragmentRecent;
}
public RecyclerViewFragment getFragmentFollowing() {
return fragmentFollowing;
}
As shown here my xml.file doesn't have tabitems
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
Also here in this image you can see it
I'm expecting a tabitem which I can give an #drawable shape, so it has a custom made layout, like a white background or something.
This is what my MainActivity shows at the moment
you can directly add tabs to tablayout using addTab method.
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.addTab(new TabLayout.newTab().setText("All"));
tabLayout.addTab(new TabLayout.newTab().setText("Following"));

android viewpager with tablayout - how to add other fragments inside of a tab?

so i have the classic viewpager in a tablayout that looks something like this:
My viewPagerAdapter class looks like this:
public class HomePagerAdapter extends FragmentPagerAdapter {
int mNumOfTabs;
public HomePagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeFragment tab1 = new TabHomeFragment();
return tab1;
case 1:
TabShopFragment tab2 = new TabShopFragment();
return tab2;
case 2:
TabMeFragment tab3 = new TabMeFragment();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
So now on one of the tabs i need to add a fragment on top of it. so its a search fragment really. i do a search in the tab bar and i want the back end search results to appear in only ONE of the tabs (the first one). but i want the search results displayed in a fragment called searchFragmentResults and i want it to be laid out on top of the first tab. Then when user hits the back button it will just go back to the original content in the first tab. Is this possible with view pager ?
so visually when i hit the search icon on the first tabs tabBar it should bring up a searchView and when i search for the users query it should bring up a another fragment with the results but only in the tab that it started from. Here is an example:
i cant call fragtransaction.replace(somecontentview, somefragment); (or its add method) because i did not add them to a contentview. i let the viewpager do it for me. So how is this achieved ?
i figured out how to do this. The tab should be a fragment who's purpose is to only contain other fragments. the idea is based off of this SO. But i had a need to do it for a viewPager. Lets go through the steps. first the viewpager adapter:
public class HomePagerAdapter extends FragmentStatePagerAdapter {
//integer to count number of tabs
int tabCount;
private Fragment mCurrentFragment;
private String[] tabTitles = new String[]{"tab0", "tab1", "tab2", "tab3"};
//Constructor to the class
public HomePagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeContainerFragment tab1 = new Tab0ContainerFragment();
return tab1;
case 1:
TabShopFragment tab2 = new Tab1ContainerFragment();
return tab2;
case 2:
TabMeFragment tab3 = new Tab2ContainerFragment();
return tab3;
case 3:
TabBagFragment tab4 = new Tab3ContainerFragment();
return tab4;
default:
return null;
}
}
//Overriden method getCount to get the number of tabs
#Override
public int getCount() {
return tabCount;
}
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
//* this is key to get the current tab to pop the fragments afterwards**/
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
Lets go into a container to see how it would look:
add this to your xml for all the containers (along with anything else you want visually but they ALL must have the same id of container_framelayout:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="#+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" />
</android.support.design.widget.CoordinatorLayout>
you dont have to put it in a coordinatorLayout i just find it fixes some bugs and works well.
In your fragments base class i copied almost the same code from the SO i mentioned above but slight modification if you want to add tag or not:
public void replaceFragment(Fragment fragment, boolean addToBackStack,String tag) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment,tag);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
Now lets look at the activities layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabTextColor="#color/black"
app:tabSelectedTextColor="#android:color/darker_gray"
/>
Now i'll show you how to set up the tablayout in the activity hosting the tablayout:
its standard:
public class HomePageActivity implements TabLayout.OnTabSelectedListener {
private final int NUM_OF_TABS = 4;
#BindView(R.id.pager)
public ViewPager viewPager;
public HomePagerAdapter adapter;
#BindView(R.id.tabLayout)
TabLayout tabLayout;
#NonNull
#Override
public HomePagePresenter createPresenter() {
return new HomePagePresenter();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homepage);
ButterKnife.bind(this);
initView();
}
private void initView() {
for (int i = 0; i < NUM_OF_TABS; i++)
tabLayout.addTab(tabLayout.newTab());
adapter = new HomePagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
//Adding adapter to pager
viewPager.setAdapter(adapter);
tabLayout.addOnTabSelectedListener(this);
tabLayout.setupWithViewPager(viewPager);
// configure tab icons
int[] imageTabResId = {
R.drawable.welcome1,
R.drawable.welcome2,
R.drawable.welcome3,
R.drawable.welcome1};
for (int i = 0; i < imageTabResId.length; i++) {
tabLayout.getTabAt(i).setIcon(imageTabResId[i]);
}
}
/** this is key. we get the current fragment showing and pop it **/
#Override
public void onBackPressed() {
boolean isPopFragment = false;
isPopFragment = ((BaseFragment) adapter.getCurrentFragment()).popFragment();
if (!isPopFragment) {
finish();
}
}
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
}
I guess the major part is onBackPress getting the current fragment.

Custom tabs with TabLayout

I have a problem with implementing custom tabs, and I know i could've just used the setCompoundDrawablesWithIntrinsicBounds for just TextView in my Layout file, but I need to show 2 another ImageViews in one Layout file.I have a custom layout for it, which I inflate like this:
public class TabsAdapter extends FragmentPagerAdapter {
private int mPageCount;
private Context mContext;
private int[] stringResID = { R.string.serverString, R.string.localString, R.string.commonString, R.string.searchString };
private int[] imagesResID = { R.drawable.tab1, R.drawable.tab2, R.drawable.tab3, R.drawable.tab4};
public TabsAdapter(FragmentManager fm, int pageCount, Context context) {
super(fm);
mPageCount = pageCount;
mContext = context;
}
public View getTabView(int position) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_tab, null);
TextView tv = (TextView) view.findViewById(R.id.titleTab);
tv.setText(stringResID[position]);
ImageView img = (ImageView) view.findViewById(R.id.tabImage);
img.setImageDrawable(ContextCompat.getDrawable(mContext, imagesResID[position]));
return view;
}
#Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position + 1);
}
#Override
public int getCount() {
return mPageCount;
}
}
And my layout file:
<?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">
<TextView
android:id="#+id/titleTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ololo"
android:layout_centerInParent="true"/>
<ImageView
android:id="#+id/tabImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_above="#+id/titleTab"/>
</RelativeLayout>
And call it from MainActivity like this:
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
TabsAdapter pagerAdapter =
new TabsAdapter(getSupportFragmentManager(), 4,MainActivity.this);
viewPager.setAdapter(pagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
if(tab != null) {
tab.setCustomView(pagerAdapter.getTabView(i));
}
}
So here's the question: what am I doing wrong? Becaus this code just gives me text in tabs, without ImageView. Please help if you tried to do something like this.

Grid layout within tabs

I'm new to Android and therefore faced such problem.
How can I change layout from:
To:
XML fragment_main:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.snbgearassistant.MainActivity$PlaceholderFragment" >
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
So I need these tabs having grid layout with different content.
You must use a GridView inside the ViewPager. So, in your MainActivity, you would have this layout.
Create the activity_main.xml layout
This is the main layout. Everything will live inside of it, including your fragments and tabs.
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.myapp.gridview.MainActivity" />
Create your MainActivity.java class
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener
{
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Here we load the xml layout we created above
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// 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.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter
{
public SectionsPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position)
{
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return new PlaceholderFragment();
}
#Override
public int getCount()
{
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position)
{
Locale l = Locale.getDefault();
switch (position)
{
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
}
Don't forget to create your strings for these R.string.title_section1, ... strings on your code, or you will have an error.
Now we must create a layout for the fragment (the page that will be displayed inside the tab), and it must contain a GridView.
Create a fragment_main.xml layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:stretchMode="columnWidth"
android:numColumns="2" />
</FrameLayout>
Now let's define the fragment class that will take care of inflating this layout and handling the views.
Create a fragment to inflate the GridView layout: PlaceHolderFragment.java
/**
* A placeholder fragment containing a the gridview
*/
public class PlaceholderFragment extends Fragment
{
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Here we inflate the layout we created above
GridView gridView = (GridView) rootView.findViewById(R.id.gridview);
gridView.setAdapter(new MyAdapter(MainActivity.this.getApplicationContext()));
return rootView;
}
}
Now we must create an adapter class to handle each item of the GridView, this way you can manage the behavior of each one.
Create the Adapter to support the GridView items: MyAdapter.java
As you can see here, we are adding some items to the GridView by adding them to an ArrayList of the type Item defined in the end of the adapter class.
private class MyAdapter extends BaseAdapter
{
private List<Item> items = new ArrayList<Item>();
private LayoutInflater inflater;
public MyAdapter(Context context)
{
inflater = LayoutInflater.from(context);
items.add(new Item("Image 1", Color.GREEN));
items.add(new Item("Image 2", Color.RED));
items.add(new Item("Image 3", Color.BLUE));
items.add(new Item("Image 4", Color.GRAY));
items.add(new Item("Image 5", Color.YELLOW));
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int i)
{
return items.get(i);
}
#Override
public long getItemId(int i)
{
return items.get(i).colorId;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup)
{
View v = view;
ImageView picture;
TextView name;
if(v == null)
{
v = inflater.inflate(R.layout.gridview_item, viewGroup, false);
v.setTag(R.id.picture, v.findViewById(R.id.picture));
v.setTag(R.id.text, v.findViewById(R.id.text));
}
picture = (ImageView)v.getTag(R.id.picture);
name = (TextView)v.getTag(R.id.text);
Item item = (Item)getItem(i);
picture.setBackgroundColor(item.colorId);
name.setText(item.name);
return v;
}
private class Item
{
final String name;
final int colorId;
Item(String name, int drawableId)
{
this.name = name;
this.colorId = drawableId;
}
}
}
Now to make the GridView items keep with the correct width, aligned side by side, we use a custom class to define the measured dimension.
Why this needs to be done? According to #kcoppock's answer:
Basically, in Android's ImageView class, there's no way to simply specify "hey, keep a square aspect ratio (width / height) for this view" unless you hard code width and height. You could do some manual adjustment of LayoutParams in the adapter's getView, but frankly, it's much simpler to let ImageView handle all the measurements, and just override the results to say "Whatever the width ends up being, make my height stay the same". You never have to think about it, it's always square, and it just works as expected. Basically this is the easiest way to keep the view square.
Create a class SquareImageView.java
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class SquareImageView extends ImageView
{
public SquareImageView(Context context)
{
super(context);
}
public SquareImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
}
}
Now we must define the XML layout for the GridView items.
Create a XML layout gridview_item.xml
As you can see, here we add two items to the layout. One is a element of the type SquareImageView (the class we created above) and the TextView which is a label for each image.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.myapp.gridview.SquareImageView
android:id="#+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
/>
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:layout_gravity="bottom"
android:textColor="#android:color/white"
android:background="#55000000"
/>
</FrameLayout>
And here it is, I tested the code and this is the final result. Of course you would change those colors for your images, but this is the approach you should follow.
Note: To set images instead of colors to the GridView item, in your getView() method of the MyAdapter class use setImageResource(int) instead of setBackgroundColor(int).
Answer Given By rogcg is very good and nice. But the Images for each fragment is same. I like to add some codes in the mainactivity which has viewpager.I think we can use fragment instead of activity, Here is the code.The same code as the Main Activity given by rogcg. Add these codes too.
In Layout for mainfragment add ActionBarlayout,toolbar and slidingtablayout
In Mainfragment,add
private List<Fragment> mFragments = new Vector<Fragment>();
in oncreate(), create three fragments ,
mFragments.add(new HomeFragment());
mFragments.add(new Title1());
mFragments.add(new Title2());
mFragments.add(new Title3());
in onCreateView(),add
mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
tabLayout = (SlidingTabLayout) v.findViewById(R.id.tabanim_tabs);
tabLayout.setViewPager(mViewPager);
in SectionPageAdapter class,add
#Override
public Fragment getItem(int position) {
return mFragments.get(position+1);
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position)
{
case 0:
return getString(R.string.English).toUpperCase(l);
case 1:
return getString(R.string.Tamil).toUpperCase(l);
case 2:
return getString(R.string.Hindi).toUpperCase(l);
}
return null;
}
Now add any view in Title1() fragment as you usage and add any things in it I think this message was useful. please vote for me. Thank you.

Divider not working for TitlePageIndicator with viewpagerindicator & actionbarsherlock

I noticed with the latest version of ViewPagerIndicator, ICS style dividers are supported, I tried to follow the issue and solution, but no matter what I do I can't get the divider to show up on my options on the actionbar for the TitlePageIndicator. I added the IcsLayout as the container, put divider, showDividers, and other properties, but am still getting nothing. Here's my layout (oddly enough, if I switch the IcsLayout to the viewpager indicator one, the app crashes):
<com.actionbarsherlock.internal.widget.IcsLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.sosick.android.brink"
android:layout_width="match_parent"
android:divider="#ffffff"
android:showDividers="middle"
android:dividerPadding="8dp"
android:dividerHeight="10dp"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.viewpagerindicator.TitlePageIndicator
android:id="#+id/tpi_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
textColor="#color/text_light"
android:background="#drawable/ab_stacked_solid_brink"
app:topPadding="10dp"
app:footerPadding="15dp"
app:footerColor="#a4ded7"
app:footerIndicatorHeight="2dp"
app:footerIndicatorStyle="underline"
app:footerLineHeight="2dp"
app:selectedBold="false" />
<android.support.v4.view.ViewPager
android:id="#+id/vp_pages"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</com.actionbarsherlock.internal.widget.IcsLinearLayout>
You need to declare divider params in styles, rather than in layout xml.
../res/values/styles.xml:
<style name="StyledIndicators" parent="#android:style/Theme.Light">
<item name="vpiIconPageIndicatorStyle">#style/CustomIconIndicator</item>
</style>
<style name="CustomIconIndicator" parent="Widget.TabPageIndicator">
<item name="android:divider">#drawable/custom_tab_indicator_divider</item>
<item name="android:showDividers">middle</item>
<item name="android:dividerPadding">10dp</item>
</style>
In manifest for your activity:
<activity
android:name=".SampleIconsDefault"
android:label="Icons/Default"
android:theme="#style/StyledIndicators">
</activity>
Following code snippets are mainlyfrom Android Developer site. There is also a very good example app/project.
Use ViewPage as a container for your layout, e.g. res/layout/activity_main.xml:
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Implement ABS' ActionBar.TabListener in your class, add and extend FragmentPagerAdapter or FragmentStatePagerAdapter from support library e.g.:
public class TheDesertFoxActivity extends SherlockFragmentActivity
implements ActionBar.TabListener {
private AppSectionsPagerAdapter mAppSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
// Set up action bar
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set up the ViewPager, attaching the adapter
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When swiping between different app sections, select the corresponding tab
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar
for (int i = 0; i < mAppSectionsPagerAdapter.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
// listener for when this tab is selected.
actionBar.addTab(actionBar.newTab()
.setText(mAppSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
public static class AppSectionsPagerAdapter extends FragmentPagerAdapter {
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
Fragment fragment = new MyTabsFragment();
Bundle args = new Bundle();
args.putInt(MyTabsFragment.TAB_ID, i);
fragment.setArguments(args);
return fragment;
}
}
#Override
public int getCount() {
return <YOUR_TAB_COUNT>;
}
}
public static class MyTabsFragment extends Fragment {
public static final String TAB_ID = "tab_id";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
int layoutId = -1;
switch (getArguments(getInt(TAB_ID))) {
case 0:
layoutId = R.layout.fragment_first_tab;
break;
case 1:
layoutId = R.layout.fragment_second_tab;
break;
...
...
...
default:
layoutId = R.layout.fragment_default_tab;
}
View rootView = inflater.inflate(layoutId, container, false);
return rootView;
}
}
}
That's it. Dividers will be put by ViewPager for you. You do not have to add them yourself.

Categories

Resources