tablayout fragment's content not updating - java

I have an activity with a TabLayout. When I go to my 2nd activity where I add some datas which are used in 1st activity and I come back, I need like 5-10 sec and a lot of swipes fot allowing the 1st activity fragment to be updated.
This is how I use the
#Override
protected void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_page);
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}
setTitle("La mia settimana:");
calendar = Calendar.getInstance();
dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
choosenDate = calendar.getTime();
viewPager.setAdapter(new SectionPagerAdapter(getSupportFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
viewPager.setCurrentItem((dayOfWeek == 1 ? 7 : dayOfWeek - 1));
}
My adapter is the following:
public class SectionPagerAdapter extends FragmentPagerAdapter {
public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
choosenDate = GetDateFromDayWeek(2);
break;
case 1:
choosenDate = GetDateFromDayWeek(3);
break;
case 2:
choosenDate = GetDateFromDayWeek(4);
break;
case 3:
choosenDate = GetDateFromDayWeek(5);
break;
case 4:
choosenDate = GetDateFromDayWeek(6);
break;
case 5:
choosenDate = GetDateFromDayWeek(7);
break;
case 6:
choosenDate = GetDateFromDayWeek(8);
break;
default:
break;
}
HomePageTabFragment homePageTabFragment = new HomePageTabFragment();
Bundle args = new Bundle();
args.putString("date", globalDateFormat.format(choosenDate));
args.putInt("day", dayOfWeek);
homePageTabFragment.setArguments(args);
return homePageTabFragment;
}
#Override
public int getCount() {
return 7;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Lun";
case 1:
return "Mar";
case 2:
return "Mer";
case 3:
return "Gio";
case 4:
return "Ven";
case 5:
return "Sab";
case 6:
return "Dom";
default:
return "Giorni settimana";
}
}
}
I always call the same fragment, with a Bundle of arguments.
I'm not gonna post the fragment, because it's really long and not relevant.
I just explain what he does: He take from db all entities, he sum some data's columns and he shows those datas inside the list.
now, my problem is the following:
In the 2nd activity I add an item to a list, and I save it in local db.
When i come back to my 1st activity, the datas (which are relative to ALL entities in db) should be updated.
The datas need like 20 sec of gestures before getting updated.
How can I solve this?

Related

Swipe between fragments with help of BottomNavigationBar

I have trouble finding a good example on how to swipe between fragments with help of bottom navigatiom bar. Since FragmentStatePagerAdapter is deprecated and a new ViewPager2 is now recommended instead of the old ViewPager I want to use ViewPager2 and FragmentStateAdapter in my code instead. I have found an example of how to combine BottomNavigationBar and ViewPager here and I want to do something similar. My code have many similarities to the one in the example with the only difference that I have my code in a fragment instead of an activity. Here is a picture of how my FrontendFragment display look like. I can switch between the views using the bottomnavigationbar but I also want to be able to swipe between the views. Can someone help me or at least direct me on the right way? Here is my code:
FragmentPagerAdapter Class:
public class FragmentPagerAdapter extends FragmentStateAdapter {
private static final int mFragmentCount = 5;
public FragmentPagerAdapter(#NonNull Fragment fragment) {
super(fragment);
}
#NonNull
#Override
public Fragment createFragment(int position) {
switch (position){
case 0:
return new HomeFragment();
case 1:
return new SearchFragment();
case 2:
return new AddFragment();
case 3:
return new MessageFragment();
case 4:
return new ProfileFragment();
}
return null;
}
#Override
public int getItemCount() {
return mFragmentCount;
}
}
FrontendFragment Class:
public class FrontendFragment extends Fragment implements BottomNavigationView.OnNavigationItemSelectedListener{
private BottomNavigationView mBottomNavigationView;
private ViewPager2 mViewPager2;
private FragmentPagerAdapter mFragmentPagerAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_frontend, container, false);
loadFragment(new HomeFragment());
mBottomNavigationView = v.findViewById(R.id.bottomNavigationBar);
mBottomNavigationView.setOnNavigationItemSelectedListener(this);
return v;
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.home_icon:
selectedFragment = new HomeFragment();
break;
case R.id.search_icon:
selectedFragment = new SearchFragment();
break;
case R.id.add_icon:
selectedFragment = new AddFragment();
break;
case R.id.message_icon:
selectedFragment = new MessageFragment();
break;
case R.id.profile_icon:
selectedFragment = new ProfileFragment();
break;
}
return loadFragment(selectedFragment);
}
private boolean loadFragment(Fragment selectedFragment) {
if(selectedFragment != null){
MainActivity.sFm.beginTransaction().replace(R.id.relLayoutMiddle, selectedFragment).commit();
return true;
}
return false;
}
}
Thanks in advance!
As I'm already using BottomNav with ViewPager2 in one of my app, I can help.
Your code is partially correct which means your FragmentPagerAdapter is fine, but not your FrontEndFragment.
See, the FragmentPagerAdapter has to be set to a ViewPager2 as
//this here is the FrontEndFragment
mViewPager2.setAdapter(new FragmentPagerAdapter(this));
Then, You don't have to do the FragmentTransaction at all, you just have to change the ViewPager2's current item position through the BottomNavigationBar as
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.home_icon:
mViewPager2.setCurrentItem(0);
break;
case R.id.search_icon:
mViewPager2.setCurrentItem(1);
break;
case R.id.add_icon:
mViewPager2.setCurrentItem(2);
break;
case R.id.message_icon:
mViewPager2.setCurrentItem(3);
break;
case R.id.profile_icon:
mViewPager2.setCurrentItem(4);
break;
}
return false;
}
This is all, you don't have to deal with Fragments at all apart from the FragmentPagerAdapter. Also, don't forget to remove the loadFragment(new HomeFragment()); which is not required, nor the function loadFragment() is required.
(Optional), Furthermore, if you want to disable the Swipe Action of the ViewPager2 and want the Fragments to be selected based on the Selected BottomNav item only, then you can set setUserInputEnabled() property of ViewPager2 as false.
Next, to set the BottomNavigationBar's item as selected based on the swipe of the ViewPager2, what you've to do is,
Create a global var
MenuItem previousMenuItem;
Then, set a default item (first) to be selected of BottomNav on activity start as
mBottomNavigationView.getMenu().getItem(0).setChecked(true);
Finally, set an OnPageSelected() callback on ViewPager2 to update the selected Menu Item as:
mViewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (previousMenuItem != null) {
previousMenuItem.setChecked(false);
}
else {
mBottomNavigationView.getMenu().getItem(0).setChecked(false);
}
mBottomNavigationView.getMenu().getItem(position).setChecked(true);
previousMenuItem = mBottomNavigationView.getMenu().getItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
}
});
What you're doing here is that you're setting default item to previousMenuItem and then on swiping to a different page, deselecting the previousMenuItem and selecting the new one, which means updating the BottomNav based on ViewPager's current item. This is the complete code you require to acheive your objective.
If you want to swipe between views, a simple solution would be to store all views in your parent view, but set all layouts for views except the initial view to android:visibility="gone". Make sure to set the initial view layout to android:visibility="visible" though. Now on you button clicks, you will have to implement onClick such that they turn on/ off view visibilities accordingly. For example, store views in order and control them via array index. But the whole thing you're trying to do is generally not a good design pattern in my opinion.
Why don't you load another Activity onClick instead of crowding your single activity? This will cause load time issues. Even if the views are non-visible, it's just an overall hassle to maintain all that in one place.

Navigate From Activity to TabLayout / ViewPager Fragment

I am trying to figure out how to navigate from an activity to a fragment that is hosted by a separate activity.
Even more complex is the destination activity hosts a TabLayout / ViewPager with 3 separate fragments. Here is the code for the adapter associated with the TabLayout / ViewPager. I am trying to navigate to the "NewFragment" section of the TabLayout / ViewPager:
public class SectionPagerAdapter extends FragmentPagerAdapter {
public SectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new TrendingFragment();
case 1:
return new FollowingFragment();
case 2:
return new NewFragment();
default:
return new TrendingFragment();
}
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getResources().getString(R.string.trending_text);
case 1:
return getResources().getString(R.string.following_text);
case 2:
return getResources().getString(R.string.new_text);
default:
return getResources().getString(R.string.trending_text);
}
}
}
I would think I would have to use an intent, but where I get confused is how I would ensure that the activity loads the NewFragment instead of the first fragment in the tab, the TrendingFragment.
You could try with something like this.
In the first activity:
int position = the fragment position in the target activity you want to open;
Intent intent = new Intent(getActivity(), TargetActivity.class);
intent.putExtra("fragmentPosition", position);
startActivity(intent);
Int the second activity, after view pager initialization:
Intent intent = getIntent();
int fragmentPosition = intent.getIntExtra("fragmentPosition");
viewPager.setCurrentItem(fragmentPosition);
Hope it helps

How to properly initialise fragment to null?

So here's the code:
private void selectItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new DoctorFragment();
break;
case 2:
fragment = new HospitalFragment();
break;
case 3:
fragment = new SpecialClinicFragment();
break;
case 4:
fragment = new PharmacyFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
//the parameter "fragment" in this line of code gives an error message.
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
getActionBar().setTitle(mNavigationDrawerItemTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
Log.e("MainActivity", "Error in creating fragment");
}
It seems like I haven't properly initialised fragment instance.
The error message was "Wrong 2nd argument type" but I'm pretty sure I put in the right parameter.
Problem is not with the argument.You have used Fragment from
android.support.v4 library but you are making transaction on android.app.fragment.
Solution:
import android.app.fragment instead of android.support.v4.fragment
Because you cannot mix up with support.v4 library and android.app.*

SlidingTabLayout, Restarts fragment On case 4 to 1?

my SlidingTabLayout restarts my fragment dashboard activity when switching from fragment tags to fragment dashboard, or position 4 to 0.
Here is the code that I have written so far, can anyone shed some light on the situation ?
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
//2 steps creating a fragment, create the fragment class and create the UI for it
Fragment fragment = null;
//we dont want it to return our place holder Fragment instead we want to switch bewtween 3
//create a switch case based on the position applied or the fragment selected
switch (position) {
case HOME:
fragment = Dashboard.newInstance("","");
break;
case TAGS:
fragment = Tags.newInstance("","");
break;
case MY_RECENT:
fragment = MyPosts.newInstance("","");
break;
case TOP:
fragment = Top.newInstance("", "");
break;
}
return fragment;
}
#Override
public int getCount() {
// Show 3 total pages.
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Home";
case 1:
return "Top";
case 2:
return "Recent";
case 3:
return "Tags";
}
return null;
}
}
You have to load all fragment in one time, you should call this method
int size=4;
viewPager.setOffscreenPageLimit(size);
after set adapter, size is the no of fragment which you want to load first time

Set a ContentView in the navigationdrawer

I'm kinda new into android programming, and I couldn't find the answer on the internet.
I have set up a Navigation drawer in Android Studio, and I want to change the content view if that section is selected, for example, if I select a view "Tools" in the navigation drawer, I want that you can see the layout "Tools" but that you also can go back to the navigation drawer. I have tried to put setContentView into the case 1, etc but that gave an error.
I have tried this code for the setContentView:
public class MainActivity extends Activity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
private NavigationDrawerFragment mNavigationDrawerFragment;
/**
* Used to store the last screen title. For use in {#link #restoreActionBar()}.
*/
private CharSequence mTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getFragmentManager().findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
}
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
.commit();
}
public void onSectionAttached(int number) {
switch (number) {
case 1:
//This is where I thought I could implement the setContentView
setContentView(R.layout.activity_tools);
mTitle = "Tools";
break;
case 2:
mTitle = "Weapons";
break;
case 3:
mTitle = "Mobs";
break;
case 4:
mTitle = "Food";
break;
case 5:
mTitle = "Blocks";
break;
}
}
ContentView is not what you want to change on drawer item selection. ContentView sets your activity layout (the one which holds NavigationDrawer view). What you really want is to replace fragments.Lets say you have a different fragment with its own layout for every item in the navigation menu. In this case you could implement something like:
public void onNavigationDrawerItemSelected(int position) {
Fragment fragment;
Bundle args = new Bundle();
String tag;
switch (position) {
case 1:
fragment = new FragmentTools();
tag = "Tools";
args.putString(KEY_FRAGMENT_TITLE, tag);
break;
case 2:
fragment = new FragmentWeapons();
tag = "Weapons";
args.putString(KEY_FRAGMENT_TITLE, tag);
break;
case 3:
...
}
FragmentTransaction transaction = getFragmentManager().beginTransaction();
fragment.setArguments(args);
transaction.replace(R.id.fragment_container, fragment, tag);
transaction.commit();
}
The above is just an example. You select which fragment to show and set its arguments. Of cource it could be the same fragment with different layouts. In that case you could pass layout id as an argument, or select appropriate layout in Fragment itself based on its title.

Categories