I'm new to kotlin and I'd like to create the following code in kotlin:
Fragment fragment = null;
switch(id) {
case R.id.nav_new:
fragment = new FragAllPosts();
break;
case R.id.nav_about:
fragment = new FragAuthors();
break;
case R.id.nav_tags:
fragment = new FragTags();
break;
}
if (fragment != null) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
The fragments are very basic and don't contain any parameters yet.
How can I achieve the above in kotlin? Thanks!
You can take the following code snippet as example:
var fragment: Fragment? = null
when(id) {
R.id.nav_new -> fragment = FragAllPosts()
R.id.nav_about -> fragment = FragAuthors()
R.id.nav_tags -> fragment = FragTags()
}
if(null != fragment) {
val ft = fragmentManager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
Hope it helps!!!
var fragment: Fragment? = null
when (id) {
R.id.nav_new -> fragment = FragAllPosts.newInstance()
R.id.nav_about -> fragment = FragAuthors.newInstance()
R.id.nav_tags -> fragment = FragTags.newInstance()
}
// activity use supportFragmentManager
// fragment use childFragmentManager
fragment?.apply {
supportFragmentManager?.beginTransaction()?.replace(R.id.content_frame, this)?.commit()
}
// Example class fragment create newInstance function
class FragAllPosts : Fragment() {
companion object {
fun newInstance(bundle: Bundle? = null): FragAllPosts = FragAllPosts().apply {
arguments = bundle
}
}
}
Related
public void selectFrag(View view) {
Fragment fr = null;
if (view == findViewById(R.id.ivSize)) {
fr = new SizeFragment();
} else if (view == findViewById(R.id.ivFrame)) {
fr = new FramesFragment();
} else if (view == findViewById(R.id.ivMat)) {
fr = new MatFragment();
} else if (view == findViewById(R.id.ivGlass)) {
fr = new GlassTypeFragment();
Bundle bundle = new Bundle();
bundle.putString("inside_width", insideWidth);
bundle.putString("inside_height", insideHeight);
// set Fragmentclass Arguments
fr.setArguments(bundle);
}
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fr);
fragmentTransaction.commit();
}
every time i click on buttion new fragment is created.
I have two resume my previous fragment on button click instead of creating new.
Add your fragments to backstack and when you would like to show again one of them get it from the backstack.
Just retain the instance and the onResume will be hit instead of onCreate.
//MEMBER VARIABLES OF THE CLASS
Fragment sizeFragment = new SizeFragment;
Fragment framesFragment = new FramesFragment;
Fragment matFragment = new MatFragment;
Fragment glassTypeFragment = new GlassTypeFragment;
Fragment selectedFragment = null
private void updateFragment(View view){
if (view == findViewById(R.id.ivSize)) {
selectedFragment = sizeFragment;
} else if (view == findViewById(R.id.ivFrame)) {
selectedFragment = framesFragment;
} else if (view == findViewById(R.id.ivMat)) {
selectedFragment = matFragment;
} else if (view == findViewById(R.id.ivGlass)) {
selectedFragment = glassTypeFragment;
Bundle bundle = new Bundle();
bundle.putString("inside_width", insideWidth);
bundle.putString("inside_height", insideHeight);
// set Fragmentclass Arguments
fr.setArguments(bundle);
}
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, selectedFragment);
fragmentTransaction.commit();
}
I think it's also worth mentioning that doing a findById each time to compare which fragment to show is a bit heavy in searching xml, I'm sure you can find a better architecture to know which one should be showing, but maybe I'm wrong.
Hope this helps.
Happy Coding.
I am trying to talk to the fragments from activity.
Here in my MainActivity I am adding multiple fragments ok so for fine.
My main requirement is I don't want to add if fragment is already added.
So how can we check this condition?
Please help me some one.
code:-
private void intializingFragments(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
private View.OnClickListener intialization() {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
int getId = v.getId();
if (getId == R.id.first) {
intializingFragments(new Fragment1());
} else if (getId == R.id.second) {
intializingFragments(new Fragment2());
} else if (getId == R.id.third) {
intializingFragments(new Fragment3());
}
}
};
}
You can use findFragmentByTag() or findFragmentById() functions to get a fragment. If mentioned methods are returning null then that fragment does not exist.
Fragment fragmentA = fragmentManager.findFragmentByTag("frag1");
if (fragmentA == null) {
// not exist
} else {
// fragment exist
}
for example:- http://wiki.workassis.com/android-load-two-fragments-in-one-framelayout/
You may find fragment in fragmentmanager:
List<Fragment> frags = getSupportFragmentManager().getFragments();
for (Fragment f : frags) {
<find what you want>...
}
Or you may add fragment with tag:
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frame, new MyFragment(), "frag1")
.commit();
And find by tag
getSupportFragmentManager().findFragmentByTag("frag1");
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment topFragment = fragmentManager.findFragmentById(R.id.container);
FragmentA fragmentA = new FragmentA();
if(topFragment!= null)
{
transaction.remove(topFragment);
transaction.add(R.id.container, fragmentA, "FA");
transaction.commit();
}
else
{
transaction.add(R.id.container, fragmentA, "FA");
transaction.commit();
}
try this
private void intializingFragments(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment topFragment = fragmentManager.findFragmentById(R.id.container);
if(topFragment!= null)
{
fragmentTransaction.remove(topFragment);
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
else
{
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
How to check whether a fragment exists, without knowing its resource ID or tag:
// MyActivity.kt
val exists: Boolean = supportFragmentManager
.fragments
.filterIsInstance<MyFragment>()
.isNotEmpty()
There are many ways by which you can track the last added fragment. The simplest one is by finding the tag within fragment manager. Here is the sample code of it:
public boolean isFragmentPresent(String tag) {
Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
if (frag instanceof HomeFragment) {
return true;
} else
return false;
}
Alternatively, you can use your own variable to check whether the last added fragment is the same as the current fragment. Here is the sample code for it:
public boolean isCurrentFragment(Fragment fragment) {
if (fragment instanceof HomeFragment && getLastAddedFragment() instanceof HomeFragment) { // getLastAddedFragment() is a method which return the last added fragment instance
return true;
} else
return false;
}
And you can use it like:
if (isCurrentFragment(new HomeFragment())) {
// Last added Fragment is the HomeFragment
}
You can go for popBackStack Pop the last fragment transition from the manager's fragment back stack. If there is nothing to pop, false is returned. enter link description here
You can get the list of previously added fragments from the fragment manager. Then just check whether the list contains your fragment object or not.
getSupportFragmentManager().getFragments().contains(yourFragment);
This one doesn't work
!getSupportFragmentManager().getFragments().contains(fragment)
This works for me
getSupportFragmentManager().findFragmentByTag(fragment::class.java.getSimpleName()) == null
I only know how to add fragment and remove.
also show and hide.
I just want to initialize fragment.
onCreate {
getFragmentManager().beginTransaction().add(R.id.top_container, new AuthProgressDialog(), AuthProgressDialog.class.getSimpleName()).commit();
getFragmentManager().beginTransaction().hide( getFragmentManager().findFragmentByTag(AuthProgressDialog.class.getSimpleName()) ).commit();
}
This is bad code, isn't it?
If you have any idea, please let me know.
Thanks.
This is sample method which you can define inside your FragmentActivity and call from any of the fragment. in which if you want to allowing adding to backstack than just remove comment line from transaction.addToBackStack("back"); and check popup backstack as per your requirement inside FragmentActivity.
public void displayView(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new FormFragment();
break;
case 1:
fragment = new HomeFragment();
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager
.beginTransaction();
if (position != 0)
// transaction.addToBackStack("back");
transaction.replace(R.id.main_ll_container, fragment).commit();
} else {
Log.e("MainActivity", "Error in creating fragment");
}
}
Use this code :
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment fraggy = new DummyFragment();
fragmentTransaction.add(R.id.fragment_container, fraggy);
fragmentTransaction.commit();
I have three fragments and a Navigation drawer in my app viz, HomeFragment,DetailFragment and CountryFragment. Now when Iam in HomeFragment(Default fragment), I check a condition, if it returns false, I want to redirect to the CountryFragment without replacing the fragment.
Initially, in the host activity Iam doing something like this:-
HomeActivity.
private Android.Support.V4.App.Fragment mCurrentFragment = new SupportFragment();
private Stack<Android.Support.V4.App.Fragment> mStackFragments;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView (Resource.Layout.homelayout);
Android.Support.V4.App.FragmentTransaction tx = SupportFragmentManager.BeginTransaction();
tx.Add(Resource.Id.main, homeFragment);
tx.Add(Resource.Id.main, countryFragment);
tx.Hide(countryFragment);
tx.Add(Resource.Id.main, detailFragment);
tx.Hide(detailFragment);
CurrentFragment = homeFragment;
tx.Commit();
}
void MenuListView_ItemClick (object sender, AdapterView.ItemClickEventArgs e)
{
Android.Support.V4.App.Fragment fragment = null;
switch (e.Id)
{
case 0:
ShowFragment(homeFragment);
break;
case 1:
ShowFragment(countryFragment);
break;
case 2:
ShowFragment(detailFragment);
break;
}
}
public void ShowFragment(SupportFragment fragment)
{
if (fragment.IsVisible)
{
return;
}
var trans = SupportFragmentManager.BeginTransaction();
fragment.View.BringToFront();
mCurrentFragment.View.BringToFront();
trans.Hide(mCurrentFragment);
trans.Show(fragment);
trans.AddToBackStack(null);
mStackFragments.Push(mCurrentFragment);
trans.Commit();
mCurrentFragment = fragment;
}
Next in HomeFragment Iam doing something like :-
public void BtnCompleteSubmit_Click(object sender, EventArgs e)
{
dlgAlert.Dismiss();
CountryFragment countryFrag = new CountryFragment ();
// Create new fragment and transaction
var myActivity = (HomeActivity)this.Activity;
myActivity.ShowFragment(countryFrag );
}
This does go to the ShowFragment() of the HomeActivity, but the view for the fragment is null even thought the View was created initially while the NavigationDrawer was created. How do I solve this? any help is appreciated.
What you can do is create all fragment with a String Tag name associated.
Then add it your fragment transcation using fragment manager.
After if you want to shift between the fragments, then write an if else statement and find the fragment by tag method.
if (mFragManager.findFragmentByTag("FRAG_HOME") != null)
showFragment(mFragManager.findFragmentByTag("FRAG_HOME"));
else
showFragment(new homeFragment(), "FRAG_HOME");
In you show Fragment method:
public void ShowFragment(Fragment fragment, String tag)
{
mFragTransaction= mFragManager.BeginTransaction();
if (fragment.isAdded())
mFragTransaction.show(fragment);
else
mFragTransaction.add(ResId, fragment, tag).setBreadCrumbShortTitle(tag);
mFragTransaction.addToBackStack(tag);
mFragTransaction.commit();
}
I have something like this inside my activity:
#Override
public void onNavigationDrawerItemSelected(int position) {
Fragment fragment = null;
switch (position+1) {
case 1: {
fragment = new Fragment_Login();
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.container, fragment)
.commit();
break;
}
case 2: {
SwipeRefreshListFragment swipeFragment = new Fragment_List_Of_Assessments();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, swipeFragment)
.commit();
break;
}
case 3: {
fragment = new Fragment_Report();
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.container, fragment)
.commit();
break;
}
case 4: {
fragment = new Fragment_Settings();
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.container, fragment)
.commit();
break;
}
default:
break;
}
}
The program automatically loads case1, but when case2 is selected, getSupportFragmentManager loads the Fragment on top of case1. I guess there are some problem with using both supportFragmentManager and FragmentManager. They seem to have their own stack. The problem is that I cannot use only either one of them because the SwipeToRefresh Android example uses ListView which needs support.v4.Fragment which needs the old FragmentManager. So how is it possible to integrate both FragmentManagers together?
I have accomplished something like this when using PreferenceFragment (not supported by support library version). In order to achieve this I kept inside my Activity a pair of boolean (isLastFragmentSupportType and lastFragmentShowed) and also a String (lastFragmentTag).
At the beginning your Activity will have both of them to false. And when you add a new Fragment you use these 2 boolean to know if you need to clean the other FragmentManager or not. I'll use your code as an example:
#Override
public void onNavigationDrawerItemSelected(int position) {
Fragment fragment = null;
switch (position+1) {
case 1: {
if(isLastFragmentSupportType && lastFragmentShowed)
{//As your last fragment was a support type you need to clear your supportFragmentManager
android.support.v4.app.Fragment fr_v4 = getSupportFragmentManager().findFragmentByTag(lastFragmentTag);
getSupportFragmentManager().beginTransaction().remove(fr_v4).commit();
}
fragment = new Fragment_Login();
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.container, fragment,TAG1)
.commit();
lastFragmentTag = TAG1;
lastFragmentShowed = true;
isLastFragmentSupportType = false;
break;
}
//And so on with the others
You need to check what type (support or not) of fragment you are going to use, and check these variables to see if the last fragment was of a different type. If that is the case clean the other fragmentmanager to "clear" the screen so they wont overlap.
Also use TAGS to identify and retrieve your current fragments so you do not need to have Fragment variables over your code.
Finally use onSavedInstanceState so as to keep these values in case you need them.
Hope it helps :)
This answer is inspired from answer by zozelfelfo.
Use these two methods to replace fragments instead of getFragmentManager.beginTransaction.replace...
private void replaceFragment(Fragment fragment, String fragmentTag) {
if(lastFragmentShowed && isLastFragmentSupportType) {
android.support.v4.app.Fragment fr_v4 = getSupportFragmentManager().findFragmentByTag(lastFragmentTag);
getSupportFragmentManager().beginTransaction().remove(fr_v4).commit();
}
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, fragment, fragmentTag)
.commit();
lastFragmentTag = fragmentTag;
lastFragmentShowed = true;
isLastFragmentSupportType = false;
}
private void replaceFragment(android.support.v4.app.Fragment fragment, String fragmentTag) {
if(lastFragmentShowed && !isLastFragmentSupportType) {
Fragment fr = getFragmentManager().findFragmentByTag(lastFragmentTag);
getFragmentManager().beginTransaction().remove(fr).commit();
}
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, fragment, fragmentTag)
.commit();
lastFragmentTag = fragmentTag;
lastFragmentShowed = true;
isLastFragmentSupportType = true;
}
I'm using BottomNavigationView as Tab Bar and switching fragments as tabs. All but one fragment are Support Fragments (and last one is PreferenceFragment). I'm using "hide-add-show" rather than "remove-replace". So, status of fragments in other tabs can be preserved.
Original function to switch:
private Fragment lastFragment = null;
private void switchFragment(Fragment fragment) {
if (lastFragment != fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (null != lastFragment) {
transaction.hide(lastFragment);
}
lastFragment = fragment;
if (!fragment.isAdded()) {
transaction.add(R.id.fragment_container, fragment);
}
transaction.show(fragment).commitAllowingStateLoss();
}
}
I don't use tag nor boolean, just want to keep a reference to last fragment object. So, when switching, just call switchFragment() with instance of any fragment:
private Object lastFragment = null;
private void switchFragment(Object fragment) {
if (lastFragment != fragment) {
if (null != lastFragment) {
if (lastFragment instanceof android.support.v4.app.Fragment) {
hideFragment((android.support.v4.app.Fragment) lastFragment);
} else if (lastFragment instanceof android.app.Fragment) {
hideFragment((android.app.Fragment) lastFragment);
}
}
lastFragment = fragment;
if (fragment instanceof android.support.v4.app.Fragment) {
showFragment((android.support.v4.app.Fragment) fragment);
} else if (fragment instanceof android.app.Fragment) {
showFragment((android.app.Fragment) fragment);
}
}
}
So, this function still do the same things but switch between Support Fragment and Native Fragment by checking the target class. Helper functions:
// Support Version:
private void hideFragment(android.support.v4.app.Fragment fragment) {
getSupportFragmentManager().beginTransaction().hide(fragment).commit();
}
private void showFragment(android.support.v4.app.Fragment fragment) {
android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (!fragment.isAdded()) {
transaction.add(R.id.fragment_container, fragment);
}
transaction.show(fragment).commitAllowingStateLoss();
}
// Native Version:
private void hideFragment(android.app.Fragment fragment) {
getFragmentManager().beginTransaction().hide(fragment).commit();
}
private void showFragment(android.app.Fragment fragment) {
android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction();
if (!fragment.isAdded()) {
transaction.add(R.id.fragment_container, fragment);
}
transaction.show(fragment).commitAllowingStateLoss();
}
To avoid confusion, I removed the import so classes require full names.