Add icons to TabItems - android

I am having trouble displaying the icons in tabsitem. They are displayed in the xml but not when the application runs.
This is the xml code. You can see that there are android:icon in the TabItem tag but it does not appears at the aplication screen.
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="0dp"
android:layout_height="61dp"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tabMode="scrollable"
app:tabTextColor="#color/colorAccent">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/ic_tabicon_principal"
android:text="Left" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="#drawable/ic_tabicon_radio"
android:text="Left2" />
</com.google.android.material.tabs.TabLayout>
This is the tabsPager.java code:
public class tabsPager extends FragmentStatePagerAdapter {
String [] titles = {"Inicio", "Radio"};
public tabsPager (FragmentManager fm)
{
super(fm);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
BlankFragment fragment = new BlankFragment();
return fragment;
case 1:
BlankFragment4 fragment4 = new BlankFragment4();
return fragment4;
}
return null;
}
#Override
public int getCount() {
return 2;
}
}

Ok so you need to set the icons in code. There are two ways to use a TabLayout
define all the tabs as a complete layout, and react to events like a tab being selected
use an adapter and create the tabs dynamically
You're using the second option, which is why you have to provide the tab titles - the adapter is generating tabs dynamically. So you have to set them all up in code, including the icons. From the docs:
Further customization of the dynamically-created TabItems (such as setting icons) needs to be done separately:
val tab = tabLayout.getTabAt(index)
tab?.icon = drawable
So yeah, I'm assuming the ones you add in XML just get discarded as soon as you set the adapter on the TabLayout. You could keep them and use the OnTabSelectedListener approach, and use that to control a ViewPager, but obviously just setting up an array of icon resource IDs and applying those to what you have is easier

Related

How to update only one Fragment (page/item) of a ViewPager?

I have a ViewPager with a PagerTitleStrip which is filled with a FragmentStatePagerAdapter which is filled with fragments which contains just a single text. These texts are stored in a array of texts with 11 positions, one per each fragment of the ViewPager.
The problem is that some of the texts in the array are being updated each X seconds, so I must find the way of update ONLY the fragment corresponding to that text. When I update the array of texts, I know the position of that array, so i know the number of the fragment inside the viewpager which must be updated. but there is a problem, I don't know a way to update just that fragment.
I only know how to update all of them at same time, using notifyDataSetChanged() and returning POSITION_NONE at getItemPosition of my FragmentStatePagerAdapter. This strategy does not work, because all of them are updated and the same time and this generates an abnormal behaviour (scroll is lost in the page you are seeing, if you are swipping between pages when the notifyDataSet function is called you loss your swip movement, etc...)
So I need help with this, because I'm totally lost with how to solve this.
This is my current source code:
This is my adapter:
public class CollectionPagerAdapter extends FragmentStatePagerAdapter {
public CollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new ObjectFragment();
Bundle args = new Bundle();
args.putString(ObjectFragment.ARG_TEXT, children[i]);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return infoTitlesArray.length;
}
#Override
public CharSequence getPageTitle(int position) {
return infoTitlesArray[position];
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
The ViewPager which has the problem:
<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">
<android.support.v4.view.PagerTitleStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingTop="4dp"
android:paddingBottom="4dp"
style="#style/CustomPagerTitleStrip"/>
</android.support.v4.view.ViewPager>
Layout of the fragment:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarSize="5dip"
style="#style/CustomScrollBar">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="left"
android:textSize="16sp"
android:padding="5dp"
style="#style/CustomTextView"/>
</ScrollView>
Thank you very much.
Fragment of a ViewPager can be found by using tag,
In Activity
Fragment fragmentToShow = getSupportFragmentManager().findFragmentByTag(
mCollectionPagerAdapter.getFragmentTag(R.id.pager, position));
In FragmentStatePagerAdapter
public String getFragmentTag(int viewPagerId, int fragmentPosition) {
// This is the format in which FragmentStatePagerAdapter internally set's the fragment tag.
return "android:switcher:" + viewPagerId + ":" + fragmentPosition;
}

'No view found for id' exception while adding tabs in dialog - android

I have an activity in which I want to show a dialog with 2 tabs. I have the following code on button click which will show the dialog:
Dialog dialog = new Dialog(this);
// select_category is having ViewPager and TabLayout inside of a Framelayout
dialog.setContentView(R.layout.select_category);
ViewPager objViewPager = (ViewPager) dialog.findViewById(R.id.viewPager);
objViewPager.setAdapter(new MyTabsAdapter(getSupportFragmentManager()));
TabLayout mTabLayout = (TabLayout) dialog.findViewById(R.id.tabLayout);
mTabLayout.setTabTextColors(getResources().getColorStateList(R.color.tabcolors));
mTabLayout.setupWithViewPager(objViewPager);
dialog.show();
Adaper for ViewPager is as,
public class MyTabsAdapter extends FragmentPagerAdapter {
String[] tabs = {"FIRST", "SECOND"};
public MyTabsAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0: {
// for now, returning plain fragment for simplicity
return new Fragment();
}
case 1: {
return new Fragment();
}
default:
return null;
}
}
}
select_category.xml is,
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background"
android:theme="#style/NoActionBarTheme">
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/view_pager_top_margin"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary" />
</FrameLayout>
When I run this code I'm getting IllegalArgumentException as,
java.lang.IllegalArgumentException: No view found for id 0x7f0a00da
(com.myapp:id/viewPager) for fragment Fragment
The TabLayout I'm using is from Google's design support library (android.support.design.widget.TabLayout).
I have no idea where I'm getting wrong. Please help!
Any tutorial / guide suggestion would be appreciated.
I read the documentation on FragmentPagerAdapter # FragmentPagerAdapter. In the webpage, the getItem() is coded differently than your code. Their suggestion is:
#Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
Notes:
You also have to define the static method newInstance.
I think you have to extend (subclass) a Fragment. In the above webpage, it subclass ListFragment.

why fragment doesn`t show up with ViewPagerIndicator

I have a activity whose content view is a fragment, I added viewpager and viewpagerindicator to this activity. I created an FragmentPagerAdapter for the pager, the adapter constructs three fragments for displaying three tabs. But when I run the project, only see the pager title shows up. Why doesn`t the three fragments show up?
I created the pager and indicator on create of the Activity lifecycle.
public class BrowserActivity extends SherlockFragmentActivity
implements ReposFragment.OnFileSelectedListener, StarredFragment.OnStarredFileSelectedListener, OnBackStackChangedListener {
super.onCreate(savedInstanceState);
setContentView(R.layout.seadroid_main);
adapter = new SeafileTabsAdapter(getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
TabPageIndicator indicator = (TabPageIndicator)findViewById(R.id.indicator);
indicator.setViewPager(pager);
indicator.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(final int position) {
currentPosition = position;
supportInvalidateOptionsMenu();
disableUpButton();
}
#Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
});
the adapter constructs three fragments for displaying three tabs view
class SeafileTabsAdapter extends FragmentPagerAdapter implements
IconPagerAdapter {
public SeafileTabsAdapter(FragmentManager fm) {
super(fm);
}
private ReposFragment reposFragment = null;
private ActivitiesFragment activitieFragment = null;
private StarredFragment starredFragment = null;
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
if (reposFragment == null) {
reposFragment = new ReposFragment();
}
return reposFragment;
case 1:
if (starredFragment == null) {
starredFragment = new StarredFragment();
}
return starredFragment;
case 2:
if (activitieFragment == null) {
activitieFragment = new ActivitiesFragment();
}
return activitieFragment;
default:
return new Fragment();
}
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.tabs_library).toUpperCase();
case 1:
return getString(R.string.tabs_starred).toUpperCase();
case 2:
return getString(R.string.tabs_activity).toUpperCase();
default:
return null;
}
}
#Override
public int getIconResId(int index) {
return ICONS[index];
}
#Override
public int getCount() {
return ICONS.length;
}
}
the layout file seadroid_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.viewpagerindicator.TabPageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
UPDATE
I have found that ViewPager tutorials used LineaLayout as the root container. So is it necessary to change FragmentLayout to be LineaLayout here. When I changed to LineaLayout, the app crashed, and the log is
12-02 07:01:13.636: E/AndroidRuntime(3807): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.seafile.seadroid2/com.seafile.seadroid2.ui.activity.BrowserActivity}: android.view.InflateException: Binary XML file line #21: Error inflating class LineaLayout
12-02 07:01:13.636: E/AndroidRuntime(3807):at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
Try switching the root view in your XML to LinearLayout. Right now you are using FrameLayout, which has the effect of putting your ViewPager on top of your TabPageIndicator. Also, since the layout_height is 0, you're not going to see your fragments. I suspect this is your problem -- clearly you meant to use LinearLayout.
Also, be careful with your SeafileTabsAdapter class. Right now it is caching the fragments, which seemed logical to me when I started using FragmentPagerAdapter too. However, FragmentPagerAdapter caches the fragments too, so you have a danger of a memory leak with this approach. If you want to call getItem directly, without auto-creating a fragment each time, then you can first call findFragmentByTag to see if the fragment is there yet. The string Android uses for the tag can be found in the source, or in this SO question:
Replace Fragment inside a ViewPager
Hope this helps. I'm still a bit confused about your code, because in the description you say you have a ViewPager inside a fragment, but the posted code seems to show a ViewPager inside your activity.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.viewpagerindicator.TabPageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
I hope this answers your concern in your comment. If you instead mean that the sherlock code is expecting a FrameLayout as the root view (this would surprise me, although I haven't used it), then all you need to do is put the LinearLayout above as a child of the FrameLayout you had before. Does that make sense?

replace SherlockFragment with another one

I am using Jake Wharton's TabPageIndicator with ViewPager. Each tab is a fragment that extends from SherlockFragment. In one fragment, on item click, I would like to replace a current fragment with another WITHIN THE SAME TAB. Visually, the current fragment disappears, no exception is thrown, but I get an empty space where the new fragment should be.
Code I am using to replace the fragment is:
SherlockFragment frag = new AboutFragment();
getSherlockActivity().getSupportFragmentManager()
.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(R.id.pager_content, frag, "dialogAbout")
.hide(this)
.addToBackStack(null)
.commit();
What is the correct way to replace this?
My main_activity xml is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.viewpagerindicator.TabPageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:background="#000000" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1">
<FrameLayout android:id="#+id/pager_content"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</android.support.v4.view.ViewPager>
</LinearLayout>
and in my MainActivity I have set an adapter to viewPager. Adapter extends from FragmentPagerAdapter and looks like follows:
private class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
index = position % CONTENT.length;
switch (index) {
case FRAG_TAG_DEPOSIT:
return new DepositFragment();
case FRAG_TAG_HISTORY:
return new HistoryFragment();
case FRAG_TAG_LOCATIONS:
return new LocationsFragment();
case FRAG_TAG_SETTINGS:
return new SettingsFragment();
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position) {
return getString(CONTENT[position % CONTENT.length]).toUpperCase();
}
#Override
public int getCount() {
return CONTENT.length;
}
}
What I don't understand here is - in which containter is the fragment returned from the adapter placed? I don't specifally notify where to put it, I simply state which fragment should be put at which position. Could this be the reason replacement fails?
Since you are using ViewPager to load your fragments, you don't need to change the fragment manually. Just set the fragment that you want to switch to using the setCurrentItem like this where num is the index of the fragment that you want to switch to.
viewPager.setCurrentItem(num);

FragmentPagerAdapter using ViewPagerIndicator not working

I have decided for remaking UI of my app by using ViewPagerIndicator and TitlePageIndicator, but I have following problems:
1) Fragments that are for each page are not displayed.
2) Swipe betwen two pages does not work.
I am using ActionBarSherlock as I did with tabs.
I have not changed anything in Fragmens since it has workrd fine when I was using tabs and I have written following code:
public class CustomFragmentAdapter extends FragmentPagerAdapter {
private final String[] TITLES = new String[] {
"General",
"Companies",
"Discounts"
};
public final int NUM_TITLES = TITLES.length;
public CustomFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Log.v("POSITION", "position: "+position);
switch (position) {
case 0:
return new General();
case 1:
return new Companies();
case 2:
return new Discounts();
}
return null;
}
#Override
public int getCount() {
return NUM_TITLES;
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position % NUM_TITLES].toUpperCase();
}
}
and
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager()));
TitlePageIndicator indicator = (TitlePageIndicator) findViewById(R.id.indicator);
indicator.setViewPager(mViewPager);
indicator.setCurrentItem(0);
and my XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.viewpagerindicator.TitlePageIndicator
android:id="#+id/indicator"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<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="0dp"
android:layout_weight="1"
/>
As I have seen most of the tutorials and examples are quiet similar to my code, but I still can't make it work. I have tried almost everything. It was also not working when I have put there some dummy fragments with just some TextView. I also have tried to remove ViewPagerIndicator and try only ViewPager, but it was not working for me.
I am probably missing something, but I can't find it.
Thank you very much in advance for your advices.
One difference I see from a similar Activity of mine is that you're not setting the current item of the pager:
mViewPager.setCurrentItem(0, false);
I have found the problem which was missing android:orientation="vertical" in activity layout xml

Categories

Resources