Actionbar.removealltabs() leaving behind the tabs space - java

Actionbar.removealltabs removes all my tabs. However, the remaining space used to hold the tabs are still there. As a result my actionbar looks like a very tall actionbar with a empty bottom half.
Using support actionbar with appcompatactivity.
I've tried calling Actionbar.removealltabs in both my fragment and Mainactivity... same result.
Tabs pre-destruction
Tabs Destroyed, leaving behind it's empty space
How it originally looked before adding tabs. This is my desired result
Here's my Fragment that created the tabs.
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViewPager = view.findViewById(R.id.reddit_search_pager);
mActionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
setViewPager();
setTabs();
}
public void setTabs() {
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
};
for (int i = 0; i < 3; i++) {
String tabTitle = "";
switch (i) {
case 0:
tabTitle = TAB_TITLE_SUBREDDITS;
break;
case 1:
tabTitle = TAB_TITLE_POSTS;
break;
case 2:
tabTitle = TAB_TITLE_USERS;
break;
}
mActionBar.addTab(
mActionBar.newTab()
.setText(tabTitle)
.setTabListener(tabListener));
}
}
Here's my primary MainActivity pre-existing modification's to the toolbar.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NetworkingUtils myClass = new NetworkingUtils(this);
ActionBar actionbar = getSupportActionBar();
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setHomeAsUpIndicator(R.drawable.ic_action_menu);

When I am working with ListViews I usually use adapters. With adapters you have to call yourAdapter.notifyDataSetChaged() every time you make a new change on your list so the list can update normally. Maybe that is what is happening to you so try to call some method like the one I showed above and it will maybe update and clear the empty space.

I fixed it by using another way to use tabs, the Tablayout as described in this video. https://www.youtube.com/watch?v=zQekzaAgIlQ. I had to make my own Toolbar instead of the default theme one.
I have no idea why Android is suggesting a deprecated and buggy way to implement tabs on their official website instead of this. In fact, the TabLayout examples provided in the Youtube video are all 404 not found.

Related

Select third page as default in TabLayout + ViewPager2

I'm trying to make third tab as default, but below piece of code does not work:
public class MessagesFragment extends Fragment {
private FragmentsAdapter fragmentsAdapter;
private ViewPager2 viewPager;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_messages, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
fragmentsAdapter = new FragmentsAdapter(this);
viewPager = view.findViewById(R.id.pager);
viewPager.setAdapter(fragmentsAdapter);
viewPager.setCurrentItem(2);
TabLayout tabLayout = view.findViewById(R.id.tab_layout);
TabLayoutMediator.TabConfigurationStrategy tabConfigurationStrategy = new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
switch (position) {
case FragmentsAdapter.MESSAGES_NEW:
tab.setText(R.string.navMessagesNew);
break;
case FragmentsAdapter.MESSAGES_READ:
tab.setText(R.string.navMessagesRead);
break;
case FragmentsAdapter.SETTINGS:
tab.setText(R.string.navSettings);
break;
default:
throw new IllegalArgumentException("There is no fragment for that position = " + position);
}
}
};
new TabLayoutMediator(tabLayout, viewPager, tabConfigurationStrategy).attach();
}
}
I'm using TabLayout and ViewPager2. All the time 1st tab is default.
Can anyone advise how to make a 3rd of my tab as default?
Thanks
I had the same problem, it looks like there is a problem with viewPager2, if you set the tab as soon as you add attach the TabLayoutMediator (using setCurrentItem) it has a weird behavior, select the tab but doesn't update the page of the viewPager.
But if you do it later, in a button or after a couple of seconds calling the method viewPager.setCurrentItem(2) works fine, in may case since I have to know to which tab I have to go I asked to my viewModel to tell me with tab I have to display and when the observer is nofity the tab is changing correctly.
At least for me this works but I can see the first tab load (the deault tab 0) and then the tab change for the one I selected, since this is not viable for me, I change to use viewPager (instead of viewPager2) and set it to the tabLayout as usual, tab_layout.setupWithViewPager(view_pager).
With the regular viewPager works fine.
Your code is correct:
viewPager.setCurrentItem(2);
viewPager.setCurrentItem(2, false);
tabLayout.getTabAt(2).select();
tabLayout.selectTab(tabLayout.getTabAt(2));
these are the same things
viewPager.setCurrentItem(2)
Modify to
viewPager.t.post {
viewPager.setCurrentItem(2, true)
}

No view found for id when using Fragments

I've done everything I can find to fix my problem, it's the same as many others with the fragmentmanager that can't find a view.
Tried everything I have found online and could think about.
Heres my MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MenuFragment menuFragment = new MenuFragment();
FragmentManager fmStart = getSupportFragmentManager();
FragmentTransaction fmTrans = fmStart.beginTransaction();
fmTrans.add(R.id.fragmentContainerID, menuFragment);
fmTrans.commitAllowingStateLoss();
}
public void addFragment(Fragment fragment, boolean addToBackStack, String tag) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (addToBackStack) {
ft.addToBackStack(tag);
}
ft.replace(R.id.fragmentContainerID, fragment, tag);
ft.commitAllowingStateLoss();
}
}
The error I get is the same as many others:
java.lang.IllegalArgumentException: No view found for id 0x7f080073 (se.iteda.hangman:id/fragmentContainerID) for fragment MenuFragment{d8a58aa (60d879ee-e84c-425e-a1a1-8e9be9c3b3a8) id=0x7f080073}
What I want to do is load a fragment at the start (MenuFragment) and in that fragment, I have 2 buttons that change fragments.
Ok. I opened your project in Github.
Error is here:
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
....
fmTrans.add(R.id.fragmentContainerID, menuFragment);
....
}
You are adding the fragment into fragmentContainerID. However, that view was not added to the Activity (leading to the view not found error).
So, in order to fix, I think you just need to apply the layout to the main activity. Something like:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this after super.onCreate()
setContentView(R.layout.activity_main);
.....
}
EDIT
And as I said in one of my comments, I think you don't need the code below at MenuFragment.java. I think you can remove it.
MenuFragment menuFragment = new MenuFragment();
((MainActivity)getActivity()).addFragment(menuFragment, true, "Menu");

setChecked and setSelected in CheckBox not working

I have an Activity which has 5 fragments in pager. I used
viewPager.setOffscreenPageLimit(fragmentList.size());
to be able to create all fragment in one time
I also have a listener which will pass parameter(object) to all fragment once I have a newIntent.
in one of my fragment I have CheckBox which should be selected according to the parameter from activity.
and other views which I were able to change the value of their texts and background.
just this check box I have set it on But when I see it, I have see it is off, all other events works well.
here is the activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme_PopupOverlay);
setContentView(R.layout.activity_configurations);
ViewPager viewPager = findViewById(R.id.container);
TabLayout tabLayout = findViewById(R.id.tabs);
setNdef(getIntent().getExtras());
String type = getNdef().getString("id");
List<Fragment> fragmentList = createFragments(type);
SectionsPagerAdapter pagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), fragmentList);
viewPager.setAdapter(pagerAdapter);
fillTableLayout(tabLayout, type);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
viewPager.setOffscreenPageLimit(fragmentList.size());
readNfcDialog = createReadDialog();
writeNfcDialog = createWriteDialog();
readNfcDialog.show();
setForeground();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
ClassNfcTag wepTag = new ClassNfcTag(intent);
String type = wepTag.defineClassTag();
OmsRepeaterTag omsRepeaterTag = new OmsRepeaterTag(intent);
byteMap = omsRepeaterTag.readTag();
if (byteMap != null) {
setTagOmsConfiguration(OmsConfiguration.fromByteArray(byteMap));
for (OmsListener listener : onReceiveOmsList) {
listener.gotOms(getInTagOmsConfiguration());
}
}
}
and here is one of the fragments
#Override
public void gotOms(OmsConfiguration configuration) {
setConfiguration(configuration);
if (isAdded()) {
boolean status = getConfiguration().getDeleteRsl();
delete.setChecked(status);
delete.setSelected(status);
}
}
as a solution I have tried to use Switch instead of CheckBox and it worked well.
and I also tried to set the pager to start from exactly the fragment which has the CheckBox and it also work.
viewPager.setCurrentItem(checkBoxFragmentPosition);
I also tried to debug the code and It shows me that the checkBox is checked and when I tried to change it to checked by touching it (programmatically it is checked, in UI I see it unchecked) it change itself from unchecked to unchecked .and then with the next touch changed to checked.
just for the people who will read this question, simply this was an unresolved bug in android.
For my case I used an toggleButton instead checkBox.

Android ViewPager Bug on Swipe

I have this weird issue with the viewPager. When I swipe from one fragment to the next and then swipe back, the layout is correct, but when pressing an element (Listview item for example), the previous java code still did not update with the view. I don't know if I can explain this any better, as it works when I play with the swipe until the fragment works like its supposed to. here is my code:
Main.Java:
public class Main extends FragmentActivity {
SectionsPagerAdapter mAdapter;
ViewPager mViewPager;
// for alert transitions
AlertDialog dialog;
// share button
private ShareActionProvider mShareActionProvider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// set up button
getActionBar().setDisplayHomeAsUpEnabled(true);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAdapter);
mViewPager.setPageTransformer(true, new DepthPageTransformer());
}
#Override
public void onBackPressed() {
if (mViewPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1);
}
}
}
SectionsPagerAdapter.java:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new Important();
case 1:
return new Propositions();
case 2:
return new Information();
}
return null;
}
#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 ("Important Dates").toUpperCase(l);
case 1:
return ("Props").toUpperCase(l);
case 2:
return ("Information").toUpperCase(l);
}
return null;
}
}
The Fragments all use the onCreateView() method.
Thanks in advance for your help!
Maybe a late response, but I've experienced the same issue.
The problem was the DepthPageTransformer you are using from the Android Developers example for PageTransformer.
There is a bug with stacking fragments and layer priority, I assume. By fixing the custom PageTransformer will fix your "swipe back" issue. Or if you don't mind the animation, just remove your custom PageTransformer and use the default animation (by adding nothing).

Navigation Drawer onNavigationDrawerItemSelected called before MainActivity onCreate?

I have setup a new project with the template implementation of Navigation Drawer Fragment and a MainActivity.
It provides me with the following relevant methods:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
token = intent.getStringExtra(EXTRA_TOKEN);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mNavigationDrawerFragment.activityMain = this;
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
}
My MainActivity is started by a splash activity which gets a saved access token via the EXTRA_TOKEN.
This is the override of the Navigation Drawer item select listener in the MainAcitivity:
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
onSectionAttached(position + 1);
switch(position) {
case 0:
fragmentManager.beginTransaction()
.replace(R.id.container, FeedFragment.newInstance(token, ""))
.commit();
break;
case 1:
fragmentManager.beginTransaction()
.replace(R.id.container, PeopleFragment.newInstance("", ""))
.commit();
break;
case 2:
if(qbloggedin) {
fragmentManager.beginTransaction()
.replace(R.id.container, MessagesFragment.newInstance(token, ""))
.commit();
}
break;
default:
break;
}
}
It starts three different fragments depending on which item is selected in the NavDrawer. While instantiating the new fragments, the token string is passed into its constructor, which is saved in the fragment's class for further use.
On the first start of the App however, it seems that onNavigationDrawerItemSelected is called before onCreate! This results me passing a null value token into the fragments, causing them to be all messed up.
How is this possible? As I understand it, the NavigationDrawerFragment should not have been setup yet!
I set breakpoints on both onCreate and on onNavigationDrawerItemSelected switch position = 0. onNavigationDrawerItemSelected is indeed hit before onCreate.
How can I make sure to get the token first before trying to handle the onNavigationDrawerItemSelected?
Any help would be appreciated.
I believe I figured this out as it was happening to me for anyone who searches this and can't find the answer.
If you use the Android Studio DrawerActivity then there is boilerplate code that they create for you. In this code in the activity_main.xml or whichever XML your DrawerActivity sets as its' content view, there is a tag.
When setContentView() is called in onCreate(), this fragment is automatically created and so technically onCreate() is still being called first but then the onNavigationDrawerItemSelected() method is called before anything else in create. Since setContentView is typically kept up top, this causes problems when trying to store the state of the fragments in your drawer.
Simply move any code that checks for savedInstanceBundle above setContentView() and it will fix the problem.
Example with comments:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// THIS IS WHERE YOU CHECK FOR SAVED INSTANCE
// Check for frag
if (savedInstanceState != null) {
Log.i(TAG, "Get QuestionDayFragment");
mQuestionDaysFragment = (QuestionDaysFragment) getSupportFragmentManager().getFragment(savedInstanceState, QUESTION_DAY_FRAGMENT);
}
// View injection
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
// THIS IS WHERE THE CODE WAS BEFORE
// THIS WOULD BE CALLED AFTER onNavigationDrawerItemSelected()
// Singleton injection
LifeboxApplication.graph().inject(this);
// Toolbar
setSupportActionBar(mToolbar);
// FB
uiHelper = new UiLifecycleHelper(this, callback);
uiHelper.onCreate(savedInstanceState);
// Drawer
mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
mNavigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout));
}
You could move the intent to a constructor and save your tokens there like so:
Intent i;
......
public FragmentConstructor() {
i = getIntent();
token = intent.getStringExtra(EXTRA_TOKEN);
}
What I had to do to make it work was to check if the page has loaded before executing onNavigationDrawerItemSelected
private Boolean loaded=false;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Your code here
this.loaded=true;
}
public void onNavigationDrawerItemSelected(int position) {
if (!this.loaded){
return;
}
I also agree with using a boolean to check if onCreate() has finished loading. My only other suggestions is that for a quick fix you can use onSectionAttached(int number) to process each item selected instead of onNavigationDrawerItemSelected.

Categories