Show/Hide Fragment instead of replace - java

I have 3 and more fragments and I want to access them with the drawer.
So that when I click on "Profile" the current fragment(i.e. Home) should hide and "Profile" fragment should show and vice versa..
Right now its working with "replace fragment" but,
Instead of replace I want to show/hide them when I click on the drawer button.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//my coding
replace(new HomeFragment());
init();
}
private void init() {
mDrawer = (FlowingDrawer) findViewById(R.id.drawerlayout);
iv_Menu = findViewById(R.id.iv_Menu);
ll_Home = findViewById(R.id.ll_Home);
ll_Profile = findViewById(R.id.ll_Profile);
ll_Setting = findViewById(R.id.ll_Setting);
ll_Share = findViewById(R.id.ll_Share);
ll_Logout = findViewById(R.id.ll_Logout);
iv_Menu.setOnClickListener(this);
ll_Home.setOnClickListener(this);
ll_Profile.setOnClickListener(this);
ll_Setting.setOnClickListener(this);
ll_Share.setOnClickListener(this);
ll_Logout.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.iv_Menu:
mDrawer.openMenu(true);
break;
case R.id.ll_Home:
replace(new HomeFragment(),"Home");
mDrawer.closeMenu(true);
break;
case R.id.ll_Profile:
replace(new ProfileFragment(),"Profile");
mDrawer.closeMenu(true);
break;
case R.id.ll_Setting:
startActivity(new Intent(this, SimplPreach.class));
mDrawer.closeMenu(true);
break;
case R.id.ll_Share:
Toast.makeText(this, "Share.", Toast.LENGTH_SHORT).show();
mDrawer.closeMenu(true);
break;
case R.id.ll_Logout:
Toast.makeText(this, "Logout.", Toast.LENGTH_SHORT).show();
mDrawer.closeMenu(true);
break;
}
}
private void replace(Fragment fragment, String s) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fl_Main,fragment);
transaction.addToBackStack(s);
transaction.commit();
}
private void replace(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fl_Main,fragment);
transaction.commit();
}
I have been searching from hours but nothing is working,
How can I use show hide instead of replace ..
Please help me..

FragmentTransaction has the following methods you can use.
show(Fragment fragment)
hide(Fragment fragment)
add(int containerViewId, Fragment fragment, String tag)
And I think you don't need to call transaction.addToBackStack(s) in your case.

Related

chip navigation bar animation not works

i used this GitHub library in my code for bottom navigation.chip navigation bar
i tried to make it floating up after starting the program.but when run the program it is disappeared but when clicking in the buttons place . on click listener works but i couldn't see the navigation bar
this is the click listener ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btmNav = findViewById(R.id.btmNav);
layout = findViewById(R.id.cntBTM);
animMove = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.slide_up);
btmNav.startAnimation(animMove);
//////////////*
if (savedInstanceState == null) {
NewsFragment newsFragment = new NewsFragment();
fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragmentContainer, newsFragment)
.commit();
}
btmNav.setOnItemSelectedListener(new ChipNavigationBar.OnItemSelectedListener() {
#Override
public void onItemSelected(int id) {
Fragment fragment = null;
switch (id) {
case R.id.home:
fragment = new WebFragment();
break;
case R.id.activity:
fragment = new ActivityFragment();
break;
case R.id.settings:
fragment = new SettingFragment();
break;
}
if (fragment != null) {
fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragmentContainer, fragment)
.commit();
} else {
Log.e(TAG, "Error in creating fragment");
}
}
});
and this in main activity
<com.ismaeldivita.chipnavigation.ChipNavigationBar
android:id="#+id/btmNav"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_margin="12dp"
android:background="#drawable/rounded"
android:elevation="5dp"
android:outlineAmbientShadowColor="#color/colorAccent"
app:cnb_menuResource="#menu/bottom_menu"
app:cnb_unselectedColor="#fff"
Use this library https://github.com/ismaeldivita/chip-navigation-bar
Dont forget to add maven in settings.graddle
maven { url 'https://jitpack.io' }
And dont forget to add this dependency to your build.graddle file
implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.6.0'
add your build.gradle implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.3.72'

How to use onBackPress button in fragment on Android

In my application I have NavigationView and into this NavigationView I have set menu for open some fragments!
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="320dip"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#000"
android:fitsSystemWindows="true"
app:headerLayout="#layout/tester_drawer_header"
app:itemIconTint="#fff"
app:itemTextColor="#fff"
app:menu="#menu/tester_drawer_main"/>
I want when click on this menu open one fragment and I want when go to nested fragments and press onBack button open first fragment not open backStack fragments!
I write below codes, but after click on back button back fragments from backStack, but I want just open first fragment!
MyActivity codes:
public class TesterDashboardActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tester_dashboard);
loadFragment(new TesterTestListFragment(), userName);
}
#Override
public void onBackPressed() {
fragmentBackCount = getSupportFragmentManager().getBackStackEntryCount();
if (fragmentBackCount <= 1) {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
//finishAffinity();
super.onBackPressed();
}
} else {
getSupportFragmentManager().popBackStack();
}
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.nav_home:
loadFragment(new TesterTestListFragment(), userName);
break;
case R.id.nav_billing:
loadFragment(new TesterFinanceFragment(), context.getString(R.string.menu_billing));
break;
case R.id.nav_edit_profile:
loadFragment(new TesterProfileFilterEditFragment(), context.getString(R.string.menu_edit_profile));
break;
case R.id.nav_bank:
loadFragment(new TesterShebaFragment(), context.getString(R.string.menu_bank));
break;
case R.id.nav_report:
loadFragment(new TesterReportsFragment(), context.getString(R.string.menu_report));
break;
case R.id.nav_setting:
loadFragment(new TesterSettingFragment(), context.getString(R.string.menu_setting));
break;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void loadFragment(Fragment fragment, String toolbarTitle) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.testerFragment, fragment,TAG_FRAGMENT);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
toolbar.setTitle(toolbarTitle);
}
How can I fix it?
In your code I found when the fragmentBackCount>1 you just call getSupportFragmentManager().popBackStack(); once, so you will see top fragment on backstack.
I think you should call getSupportFragmentManager().popBackStack();, fragmentBackCount-1 time to reach the first fragmnet
else {
for(int i=0;i<fragmentBackCount-1;i++)
getSupportFragmentManager().popBackStack();
}
When you are transitioning between Fragments, call addToBackStack() as part of your
FragmentTransaction:
FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();

Fragment Transaction shows Tabs Fragment below

I'm making an app that has launches with a Swiping Tabs Fragment, but I also want to have a Preferences menu using Fragment Transaction. When I press the Settings button in my app, the preferences menu does appear and is interactive, but the layout seems to be transparent showing the Tabs below. Is there anything that can be done to fix this, or is there a better method?
Code that calls the Preferences Menu from the Options:
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getFragmentManager().popBackStackImmediate();
break;
case R.id.logout:
FirebaseAuth.getInstance().signOut();
finish();
startActivity(new Intent(this, Activity_Main.class));
break;
case R.id.action_settings:
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new Fragment_Settings()).addToBackStack(null)
.commit();
break;
}
return true;
}
Code that calls Tabs Fragments:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new Fragment_Flower();
case 1:
// Games fragment activity
return new Fragment_Overview();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 2;
}
}
Initialising Transaction in onCreate:
startService(new Intent(this, SensorListener.class));
if (b == null) {
// Create new fragment and transaction
Fragment newFragment = new Fragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
//Replace whatever is in the fragment_container view with this
// fragment,
// and add the transaction to the back stack
transaction.replace(android.R.id.content, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
Any help will be greatly appreciated!
Just set background color in your layout file. It may avoid transparent backgound.

Getting Actionbar Tabs to Stick on Fragment

I currently have a MainActivity.java which should be the only activity class. Though in that activity class I have a nav-drawer which links to other fragment views.
Currently the main issue Im facing is implementing tabs under a fragment and making them just be available for only that fragment and subfragments. I ran my application and the tabs appeared, but they also appear on other fragments after I visit the TeamsAndDriversFragment.
In my MainActivity.java I have the following function which helps point to the fragments it will generate once someone clicks on them in the nav-drawer:
/**
* Diplaying fragment view for selected nav drawer list item
* */
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new TimeAndScoringFragment();
break;
case 1:
fragment = new ScheduleFragment();
break;
case 2:
fragment = new StandingsFragment();
break;
case 3:
fragment = new TeamsAndDriversFragment();
break;
case 4:
fragment = new NewsFragment();
break;
default:
break;
}
if (fragment != null) {
// Create a fragment transaction object to be able to switch fragments
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.frame_container, fragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
Here is my current TeamsAndDriversFragment class where I have an actionbar navigation with tabs:
public class TeamsAndDriversFragment extends Fragment implements TabListener {
private List<Fragment> fragList = new ArrayList<Fragment>();
#Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
ActionBar bar = getActivity().getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab mTeamsTab = bar.newTab();
mTeamsTab.setText("Teams");
mTeamsTab.setTabListener(this);
bar.addTab(mTeamsTab);
Tab mDriversTab = bar.newTab();
mDriversTab.setText("Drivers");
mDriversTab.setTabListener(this);
bar.addTab(mDriversTab);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Fragment f = null;
TabFragment tf = null;
if(fragList.size() > tab.getPosition()) {
fragList.get(tab.getPosition());
}
if(f == null) {
tf = new TabFragment();
Bundle data = new Bundle();
data.putInt("idx", tab.getPosition());
tf.setArguments(data);
fragList.add(tf);
} else {
tf = (TabFragment) f;
}
ft.replace(android.R.id.content, tf);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if(fragList.size() > tab.getPosition()) {
ft.remove(fragList.get(tab.getPosition()));
}
}
}
In the displayView() method simply remove all tabs from the ActionBar, this way you'll always have a clean ActionBar with the exception of the TeamsAndDriversFragment fragment:
private void displayView(int position) {
getSupportActionBar().removeAllTabs();
// ...
}

How to save and reuse same instance of fragments?

I have recently started using fragments have created a demo app which looks like this:
Clicking on each button switches between fragment 1, Fragment 2, and Fragment 3.
What I am trying to accomplish is to only have 1 instance of each Fragment and reuse that. (Please note that all the fragments are created and added dynamically). Currently I am doing this by creating a HashMap of fragment and placing each instance and grabbing it from there.
So my questions are:
Is there a better way of doing this:
By using FragmentManager's putFragment(...) method? putFragment (Bundle bundle, String key, Fragment fragment) I can't figure out how to use it in my case. If anyone can give me an example of how to use this method.
Is it expensive to hold onto a reference of each fragment in my activity? Does this keep all the fragments alive? I am using soft reference to tackle this but I am not sure if this is the proper way of doing this. Please point me towards any alternative way of doing this or let me know if this is best way to accomplish this.
Thanks in advance.
Here is my code:
UPDATE:
I am trying to reuse fragments from the back stack, trying to only add them if it does not exists in the back stack. The code below gives me the Illegal state exception after I navigate away from fragment one -> come back to it -> then try to press back button:
10-28 13:21:40.255: ERROR/MessageQueue-JNI(3548): java.lang.IllegalStateException: Fragment already added: FragmentOne{423db570 #0 id=0x7f050006 fragOne}
public class MainActivity extends Activity implements View.OnClickListener {
private Button btnOne;
private Button btnTwo;
private Button btnThree;
/* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initialize();
if(findViewById(R.id.fl) != null){
if(savedInstanceState != null)
return;
}
FragmentManager.enableDebugLogging(true);
updateView("fragOne");
}
private void initialize(){
btnOne = (Button) findViewById(R.id.button1);
btnTwo = (Button) findViewById(R.id.button2);
btnThree = (Button) findViewById(R.id.button3);
btnOne.setOnClickListener(this);
btnTwo.setOnClickListener(this);
btnThree.setOnClickListener(this);
fragHolder = new HashMap<String, SoftReference<Fragment>>();
}
private void updateView(String tag){
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment frag = getFragmentManager().findFragmentByTag(tag);
boolean addToStack = true;
if(frag == null){
if(tag.equals("fragOne"))
frag = new FragmentOne();
else if(tag.equals("fragTwo"))
frag = new FragmentTwo();
else if(tag.equals("fragThree"))
frag = new FragmentThree();
}else{
//Don't add to back stack
addToStack = false;
}
ft.replace(R.id.fl, frag, tag);
if(addToStack)
ft.addToBackStack(null);
ft.commit();
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button1:
updateView("fragOne");
break;
case R.id.button2:
updateView("fragTwo");
break;
case R.id.button3:
updateView("fragThree");
break;
}
}
}
To demonstrate a FragmentTransaction, the following sample might be helpful to you.
First, you want to do all your initialization stuff in the onCreate() of your activity, which you have right, but we'll make a few changes.
public class MainActivity extends Activity implements View.OnClickListener {
private Button btnOne;
private Button btnTwo;
private Button btnThree;
/* Called when the activity is first created.*/
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initialize();
if(findViewById(R.id.fl) != null)
{
if(savedInstanceState != null)
{
FragmentTransaction trans = getFragmentManager().beginTransaction();
//This is where we add our first fragment
trans.add(R.id.fl, new FragmentOne());
trans.commit();
}
}
}
private void initialize()
{
btnOne = (Button) findViewById(R.id.button1);
btnTwo = (Button) findViewById(R.id.button2);
btnThree = (Button) findViewById(R.id.button3);
btnOne.setOnClickListener(this);
btnTwo.setOnClickListener(this);
btnThree.setOnClickListener(this);
}
public void onClick(View view)
{
//Here is where we'll actually transfer the fragments
FragmentTransaction trans = getFragmentManager().beginTransaction();
switch(v.getId()){
case R.id.button1:
trans.replace(R.id.fl, new FragmentOne());
trans.addToBackStack(null);
trans.commit();
break;
case R.id.button2:
trans.replace(R.id.fl, new FragmentTwo());
trans.addToBackStack(null);
trans.commit();
break;
case R.id.button3:
trans.replace(R.id.fl, new FragmentThree());
trans.addToBackStack(null);
trans.commit();
break;
}
}
This will allow you to easily transition from one Fragment to the next.
The FragmentManager does it's own memory management. It will kill/recreate or keep in memory your instances according to its logic. You can ensure your fragment's state is save using onSaveInstanceState()
Or you can for force the system to keep your instance alive using setRetainInstance(true) on your Fragment.
This is how you create a transaction.
FragmentTransaction fragmentTransaction = context.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.layout, new MyFragment(), f.getClass().getName());
fragmentTransaction.commit();

Categories