I have an activity with two fragments in it (both dynamically created), one of which is a ListFragment. I have implemented an onListItemClick handler in the activity. When an item is clicked, I want to replace both fragments with other fragments, and populate a TextView. However, after replacing the fragments I can't seem to get the View object I need to manipulate the TextView in the new Details fragment -- it returns null. Here is some relevant code (onListItemSelected is the handler that processes onListItemClick in the main activity).
#Override
public void onListItemSelected(int index) {
inflateCheckinFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
cif = new checkInFragment();
fragmentTransaction.replace(R.id.action_container, cif, "ACTIONS");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit()
FragmentTransaction fragmentTransaction2 = fm.beginTransaction();
gdf = new GeolocDetailsFragment();
fragmentTransaction2.replace(R.id.fragment_container, gdf, "DETAILS");
fragmentTransaction2.addToBackStack(null);
fragmentTransaction2.commit();
View gdfView = gdf.getView();
TextView tv = (TextView) gdfView.findViewById(R.id.textPOI);
tv.setText(printPOI(poiList.get(index)));
}
I ended up just setting up the data in the onListItemSelected method. selectedPOI is a private class member.
public void onListItemSelected(int index) {
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.action_container, cif, TAG_CHECKIN);
fragmentTransaction.replace(R.id.fragment_container, gdf, TAG_DETAILS);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
selectedPOI = poiList.get(index);
}
Then in the GeolocDetailsFragment class, I set up a handler to be called in the Activity in the Fragment's onCreateView method to set the TextView value.
public class GeolocDetailsFragment extends Fragment {
private TextSetter textSetter;
public interface TextSetter {
public String getActivityText();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.geoloc_details_fragment, container, false);
TextView detailsText = (TextView) view.findViewById(R.id.textPOI);
detailsText.setText(textSetter.getActivityText());
return view;
}
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
textSetter = (TextSetter) activity;
}
catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnGetPOIListener");
}
}
}
Finally, I implemented getActivityText() in the main activity to get the string to pass to the TextView.
#Override
public String getActivityText() {
return printPOI(selectedPOI);
}
You should make use of the Fragments in a fashion like this, making the TextView public in your fragment helps the Activity to access it directly, and there fore change the value.
Class GeolocDetailsFragment extends Fragments{
public TextView tv;
onCreateView(){
tv= (TextView) rootView.findViewById(R.id.textPOI);
}
}
//IN YOUR ACTIVITY
#Override
public void onListItemSelected(int index) {
gdf = new GeolocDetailsFragment();
gdf.tv.setText(printPOI(poiList.get(index)));
}
Related
I try to replace one fragment by another and get this error. I updated all libraries to latest version, but looks like I have mistake in the code while probably I don't understand something...
java.lang.IllegalStateException: FragmentManager has not been attached to a host.
at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1727)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:321)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:286)
call from parent adapter feed:
private void clickId (View v, String idAuthor) {
new PrivateMessageShow();
}
class PrivateMessageShow
public class PrivateMessageShow extends FragmentActivity {
private FragmentTransaction fragmentTransaction;
private FragmentManager fragmentManager;
public PrivateMessageShow () {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.navigation_privateconversation, new PrivateMessageFragment(), "tag");
fragmentTransaction.addToBackStack("tag");
fragmentTransaction.commit();
}
}
Class PrivateMessageFragment which fails:
public class PrivateMessageFragment extends Fragment {
RecyclerView recyclerView;
public PrivateMessageFragment() {
}
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_private_message, container, false);
final Context mycontext = getActivity();
recyclerView = root.findViewById(R.id.recyclerViewPrivateMessage);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mycontext);
recyclerView.setLayoutManager(layoutManager);
return root;
}
}
You need to call fragment transaction code in Activity's onCreate method
Rename constructor, keep it as a method as below -
public void loadFragment () {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.navigation_privateconversation, new
PrivateMessageFragment(), "tag");
fragmentTransaction.addToBackStack("tag");
fragmentTransaction.commit();
}
Call this method in onCreate of PrivateMessageShow acitivity.
so my code is supposed to support both phone and tablet (tablet with fragments). I know how to inflate the fragment and set the necessary values in the MessageFragment class but I am supposed to do this in the MessageDetails class instead. I don't know how to do that.
ChatWindow class has my code that launches based on if I am on the phone or tablet:
myDisplay.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(isTablet){
MessageFragment mFragment = new MessageFragment();
Bundle bundle = new Bundle();
String idString = String.valueOf(id);
bundle.putString("message_id", idString);
String message = cursor.getString(cursor.getColumnIndex(ChatDatabaseHelper.KEY_MESSAGE));
bundle.putString("message_value", message);
mFragment.setArguments(bundle);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.frme, mFragment).addToBackStack(null) .commit();
} else { Intent intent = new Intent(ChatWindow.this, MessageDetails.class);
String idString = String.valueOf(id);
String message = cursor.getString(cursor.getColumnIndex(ChatDatabaseHelper.KEY_MESSAGE));
intent.putExtra("message_id", idString);
intent.putExtra("message_value", message);
startActivity(intent); } //for phone
}
});
Here is my onCreateView code for the MessageFragment Class:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup parent, #Nullable Bundle savedInstanceState) {
// Inflate the xml file for the fragment
View rootView = inflater.inflate(R.layout.activity_message_details, parent, false);
return rootView;
}
And Finally, this is my MessageDetails class where I am supposed to inflate the fragment for tablet and assign values (you can see the code for phone layout is already there).
public class MessageDetails extends Activity {
String id;
String message;
MessageFragment mfragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_details);
Bundle bundle;
TextView delMsg;
TextView delId;
Button delBtn;
bundle = getIntent().getExtras();
setId(bundle.getString("message_id"));
setMessage(bundle.getString("message_value"));
//Missing Fragment Inflater code
delMsg = (TextView) findViewById(R.id.delMsg);
delId = (TextView) findViewById(R.id.delId);
delBtn = (Button) findViewById(R.id.delBtn);
delMsg.setText(message);
delId.setText(id);
delBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MessageDetails.this, ChatWindow.class);
intent.putExtra ("delete_id", id);
setResult(RESULT_OK);
startActivityForResult(intent, 33);
finish();
}
}
);
}
public void setId(String delId) {
delId = id;
}
public void setMessage(String delMessage) {
delMessage = message;
}
public String getId() {
return id;
}
public String getMessage() {
return message;
}
}
If you want to embed the fragment based on some business logic, then you can try
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
or, If the fragment is already present in your activity's layout xml file, the fragment will be instantiated whenever the activity's layout is inflated by the system and the onCreateView method of the fragment will be called.
As per the official documentation,
When the system creates this activity layout, it instantiates each fragment specified in the layout and calls the onCreateView() method for each one, to retrieve each fragment's layout. The system inserts the View returned by the fragment directly in place of the element.
Please follow the official documentation from the below link for better understanding the Fragment lifecycle.
https://developer.android.com/guide/components/fragments.html#Creating
Since MessageDetails is an Activity. You can try something like this:
getLayoutInflater().inflate(your_xml_layout)
I have an Activity with a ViewPager, each page of the ViewPager has a Fragment.
Inside my Screen3Fragment I have a LinearLayout (lly_fragments) where I am showing some other fragments. I start by showing the fragment Screen3_1
public class Screen3Fragment extends Fragment {
private FragmentManager manager;
private FragmentTransaction transaction;
public static Screen3Fragment newInstance() {
final Screen3Fragment mf = new Screen3Fragment();
return mf;
}
public Screen3Fragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3, container, false);
Screen3_1Fragment frag31 = new Screen3_1Fragment();
manager = getChildFragmentManager();
transaction = manager.beginTransaction();
transaction.add(R.id.lly_fragments,frag31,"frag31");
transaction.addToBackStack("frag31");
transaction.commit();
return v;
}
}
This works fine without problems. Problem comes when, from within frag31 (which is inside Screen3Fragment), I want to call fragt32, for that I do the following.
public class Screen3_1Fragment extends Fragment {
private ImageButton imgbt_timer;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3_1,container,false);
imgbt_timer = (ImageButton) v.findViewById(R.id.bT_scr31_timer);
imgbt_timer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getChildFragmentManager().beginTransaction()
.replace(R.id.lly_fragments, new Screen3_2Fragment(), "frag32")
.commit();
}
});
return v;
}
}
As I read in other answers, the line transaction.replaceshould do the trick and replace the existing frag31 by the given frag32 inside the same given container lly_fragments.
However, I get java.lang.IllegalArgumentException: No view found for id..... I am not sure why.
getFragmentManager() will return always attributes from parent, in most cases the activities. getChildFragmentManager() wil return parent attributes (in your case, Screen3Fragment attributes). It should be used when you add a fragment inside a fragment.
In your case, Screen3Fragment should be added using getFragmentManager() and Screen3_1Fragment should be added using getChildFragmentManager() because Screen3_1Fragment is Screen3Fragment child. Screen3Fragment is the parent.
I recomand you to use always getFragmentManager() with add method, not replace because your parent will be the same.
getChildFragmentManager() can be used when you add a ViewPager inside a fragment.
You can use the callback, as following :
that worked for me, I hope my answers helps you
1) create a interface
public interface ChangeFragmentListener {
void onChangeFragmentLicked(int fragment);
}
2) implement the interface and transaction methods in your activity:
public class MainActivity extends AppCompatActivity implements ChangeFragmentListener {
FragmentTransaction fragmentTransaction;
Fragment1 fragment1;
Fragment2 fragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
fragment1 = new Fragment1();
fragment1.setChangeFragmentListener(this);
fragment2 = new Fragment2();
fragment2.setChangeFragmentListener(this);
initListeners();
}
void changeToFrag1() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container,fragment1, "");
fragmentTransaction.commit();
}
void changeToFrag2() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container, fragment2, "");
fragmentTransaction.commit();
}
#Override
public void onChangeFragmentLicked(int fragment) {
switch (fragment){
case 1:
changeToFrag1();
break;
case 2:
changeToFrag2();
break;
}
}
3) Create object from the interface to handle the callback:
public class Fragment1 extends Fragment {
private ChangeFragmentListener changeFragmentListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
view.findViewById(R.id.fragment1_textView).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
changeFragmentListener.onChangeFragmentLicked(2);
}
});
return view;
}
public Fragment1 setChangeFragmentListener(ChangeFragmentListener changeFragmentListener) {
this.changeFragmentListener = changeFragmentListener;
return this;
}
}
I have a supported fragment activity which will load diff fragments. The fragment has some textView with id = "score" and I want to get its handle but findViewById for score's textView returns null. Why so?
textView is placed in fragment
public class MyActivity extends extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks{
private TextView scoreBoardTextView = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
scoreBoardTextView = (TextView) findViewById(R.id.score); //this returns null
}
#Override
public void onNavigationDrawerItemSelected(int position) {
//set fragment
}
}
Note:
Directly accessing fragment's views outside fragment is not a good idea. You should use fragment callback interfaces to handle such cases and avoid bugs. The following way works but it is not recommended as it is not a good practice.
If you want to access the TextView of Fragment inside its parent Activity then you should define a method inside your Fragment class like this:
public class MyFragment extends Fragment {
TextView mTextView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_main, container, false);
mTextView = (TextView) view.findViewById(R.id.textView1);
return view;
}
public void setTextViewText(String value){
mTextView.setText(value);
}
}
Now you can use this inside your Activity like this:
myFragment.setTextViewText("foo");
here myFragment is of type MyFragment.
If you want to access the whole TextView then you can define a method like this inside MyFragment.java:
public TextView getTextView1(){
return mTextView;
}
By this you can access the TextView itself.
Hope this Helps. :)
It is possible with following way:
Keep reference of inflated view in the Fragment like this :
public class MyFragment extends SherlockFragment{
MainMenuActivity activity;
public View view;
public MyFragment(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if ( getActivity() instanceof MainMenuActivity){
activity = (MainMenuActivity) getActivity();
}
view = inflater.inflate(R.layout.aboutus, container, false);
return view;
}
}
Create a function in the Activity, like this:
public class MainMenuActivity extends SherlockFragmentActivity {
SherlockFragment fragment = null;
public void switchContent(SherlockFragment fragment) {
this.fragment = fragment;
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.mainmenu, fragment)
.commit();
invalidateOptionsMenu();
}
Its purpose is to keep reference of current fragment. Whenever you wanna switch fragment, you call above function, like this (from fragment):
activity.switchContent( new MyFragment_2());
Now you've current fragment reference. So you can directly access Fragment's views in Activity like this: this.fragment.view
You have no need of reference of Fragment view to get its components in Activity. As you can directly access layout components of a Fragment in parent Activity.
Simply you can access any component by this
findViewById(R.id.child_of_fragment_layout);
In order to access the TextView or Button or whatever in your fragment you need to do the following:
public class BlankFragment extends Fragment {
public View view;
public TextView textView;
public Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view =inflater.inflate(R.layout.fragment_blank, container, false);
textView = (TextView)view.getRootView().findViewById(R.id.textView_fragment1);
return view;
}
public void changeTextOfFragment(String text){
textView.setText(text);
view.setBackgroundResource(R.color.colorPrimaryDark);
}
Once that is done in your MainActivity or any other where you want to access your TextView from your Fragment you should make sure to set up the fragment in your OnCreate() method other ways it will most likely throw nullPointer. So your activity where you want to change the TextView should look smth like this:
public class MainActivity extends AppCompatActivity {
private Button button1;
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
BlankFragment blankFragment = new BlankFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button)findViewById(R.id.button1);
changeFragment();
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment1,blankFragment);
fragmentTransaction.commit();
}
private void changeFragment(){
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
blankFragment.changeTextOfFragment("Enter here the text which you want to be displayed on your Updated Fragment");
}
});
}
Hope this helps :)
You can access with getView method of Fragment class.
For example You have a TextView in Your MyFragment with id of "text_view" In Your Activity make a Fragment of Yours:
MyFragment myFragment = new MyFragment();
And when You need a child just call getView and then find Your childView.
View view = myFragment.getView();
if (view !=null) {
view.findViewById(R.id.text_view).setText("Child Accessed :D");
}
Note: if you want the root view of your fragment, then myFragment.getView(); is simply enough.
Just put in fragment instead of putting in activity:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new_work_order,
container, false);
TextView scoreBoardTextView = (TextView) rootView.findViewById(R.id.score);
return rootView;
}
Only doing this:
((Your_Activity) this.getActivity()).YouyActivityElements;
If your TextView placed inside Fragment that case you cannot access TextView inside your Fragment Parent Activity you can set the interface for intercommunication between Fragment and Activity and send Data when you click on TextView or anyother thing which you want to happend
You can't access Fragment element in Parent Activity, But You can pass values to your Fragment by following way.
in your onNavigationDrawerItemSelected method of MyActivity do the following
int myScore = 100;
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager
.beginTransaction()
.replace(R.id.container,
MyFragment.newInstance(myScore)).commit();
}
And in MyFragment class create a method called newInstance like following
private static final String SCORE = "score";
public static MyFragment newInstance(int score) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putInt(SCORE, score);
fragment.setArguments(args);
return fragment;
}
And in MyFragment's onCreateView() method
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
TextView textView = (TextView) rootView
.findViewById(R.id.score);
textView.setText(Integer.toString(getArguments().getInt(
SCORE)));
return rootView;
}
That's All, I hope this will help you. If not please let me know.
The score textView is in the layout of fragment, it's not in the layout of the MyActivity, i.e. R.layout.activity_home. So you could find the score textview in that fragment once you inflate the corresponding layout file.
It returns null cause the TextView is an element of the Fragment, not the Activity.
Please note that the idea of using Fragment is to encapsulate a module inside the Fragment, which means the Activity should not have direct access to it's properties. Consider moving your logic where you get the TextView reference inside the Fragment
Simply declare TextView as public in fragment, initialize it by findViewById() in fragment's onCreateView(). Now by using the Fragment Object which you added in activity you can access TextView.
You need to call method findViewById from your fragment view.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
scoreBoardTextView = (TextView) mNavigationDrawerFragment.getView().findViewById(R.id.score);
}
This way works for me.
I suggest you to make the textview part of your activity layout. Alternately you can have the textview as a separete fragment. Have a look at my question here. Its similar to yours but in reverse direction. Here's a stripped down version of code I used in my project. The explanation are along the code.
The Activity Class
public class MainActivity extends ActionBarActivity {
PlaceFragment fragment;
TextView fragmentsTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Bundle bundle = new Bundle();
bundle.putString("score", "1000");
fragment = PlaceFragment.newInstance(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, fragment);
ft.addToBackStack(null);
ft.commit();
// method 1
// fragment is added some ways to access views
// get the reference of fragment's textview
if (fragment.getTextView() != null) {
fragmentsTextView = fragment.getTextView();
}
// method 2
// using static method dont use in production code
// PlaceFragment.textViewInFragment.setText("2000");
// method 3
// let the fragment handle update its own text this is the recommended
// way wait until fragment transaction is complete before calling
//fragment.updateText("2000");
}
}
The fragment class:
public class PlaceFragment extends Fragment {
public TextView textViewInFragment;// to access via object.field same to
// string.length
// public static TextView textViewInFragment;//to access via
// PlaceFragment.textView dont try this in production code
public PlaceFragment() {
}
public static PlaceFragment newInstance(Bundle bundle) {
PlaceFragment fragment = new PlaceFragment();
fragment.setArguments(bundle);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_place, container, false);
textViewInFragment = (TextView) view
.findViewById(R.id.textViewInFragment);
return view;
}
#Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
if (getArguments() != null) {
textViewInFragment.setText(getArguments().getString("score"));
}
}
public TextView getTextView() {
if (textViewInFragment != null) {
return textViewInFragment;// returns instance of inflated textview
}
return null;// return null and check null
}
public void updateText(String text) {
textViewInFragment.setText(text);// this is recommended way to alter
// view property of fragment in
// activity
}
}
Communication from activity to fragment is straight forward. This is because activity contains fragment. Keep the fragment object and access its property via setters and getters or the public fields inside it. But communication from fragment to activity requires an interface.
why you don't access it directly from your FragmentPagerAdapter,
SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
subAccountFragment.requestConnectPressed(view);
and here is the full example:
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Locale;
public class TabsActivity extends ActionBarActivity implements ActionBar.TabListener {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabs);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
ActionBar.Tab tab = actionBar.newTab();
View tabView = this.getLayoutInflater().inflate(R.layout.activity_tab, null);
ImageView icon = (ImageView) tabView.findViewById(R.id.tab_icon);
icon.setImageDrawable(getResources().getDrawable(mSectionsPagerAdapter.getPageIcon(i)));
TextView title = (TextView) tabView.findViewById(R.id.tab_title);
title.setText(mSectionsPagerAdapter.getPageTitle(i));
tab.setCustomView(tabView);
tab.setTabListener(this);
actionBar.addTab(tab);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_tabs, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_logout) {
finish();
gotoLogin();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public ProfileFragment profileFragment;
public SubAccountFragment subAccountFragment;
public ChatFragment chatFragment;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
profileFragment = new ProfileFragment();
subAccountFragment = new SubAccountFragment();
chatFragment = new ChatFragment();
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return profileFragment;
case 1:
return subAccountFragment;
case 2:
return chatFragment;
}
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 getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
public int getPageIcon(int position) {
switch (position) {
case 0:
return R.drawable.tab_icon_0;
case 1:
return R.drawable.tab_icon_1;
case 2:
return R.drawable.tab_icon_2;
}
return 0;
}
}
public void gotoLogin() {
Intent intent = new Intent(this, LoginActivity.class);
this.startActivity(intent);
}
public void requestConnectPressed(View view){
SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
subAccountFragment.requestConnectPressed(view);
}
}
If the view is already inflated (e.g. visible) on the screen then you can just use findViewById(R.id.yourTextView) within the activity as normal and it will return the handle to the text view or null if the view was not found.
I just use methods to access fragment views from parent activity, because we create a new fragment class object to insert the fragment. So I do like this.
class BrowserFragment : Fragment(), Serializable {
private lateinit var webView: NestedScrollWebView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
webView = view.findViewById(R.id.web_view)
}
fun getWebView(): WebView {
return webView
}
}
In MainActivity
val browserFragment = BrowserFragment()
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.browser_fragment_placeholder, browserFragment)
fragmentTransaction.commit()
val webView = browserFragment.getWebView()
I have an ImageView. I want to move from one fragment to another fragment on a click of an Imageview, the same way like we can move from one activity to another using
Intent i=new Intent(MainActivity.this,SecondActivity.class);
startActivity(i);
How can I do this? Can anyone explain to me step by step?
My codes are as follows:
mycontacts.class
public class mycontacts extends Fragment {
public mycontacts() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View v = super.getView(position, convertView, parent);
ImageView purple=(ImageView)v.findViewById(R.id.imageView1);
purple.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//how to go to tasks fragment from here???
}
});
return view;
}
}
tasks.class
public class tasks extends Fragment {
public tasks() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout_one, container,
false);
return view;
}
}
purple.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new tasks();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
You write the above code...there we are replacing R.id.content_frame with our fragment.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_profile, container, false);
notification = (ImageView)v.findViewById(R.id.notification);
notification.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fr = getFragmentManager().beginTransaction();
fr.replace(R.id.container,new NotificationFragment());
fr.commit();
}
});
return v;
}
Add this code where you want to click and load Fragment.
Fragment fragment = new yourfragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
When you are inside an activity and need to go to a fragment use below
getFragmentManager().beginTransaction().replace(R.id.*TO_BE_REPLACED_LAYOUT_ID*, new tasks()).commit();
But when you are inside a fragment and need to go to a fragment then just add a getActivity(). before, so it would become
getActivity().getFragmentManager().beginTransaction().replace(R.id.*TO_BE_REPLACED_LAYOUT_ID*, new tasks()).commit();
as simple as that.
The *TO_BE_REPLACED_LAYOUT_ID* can be the entire page of activity or a part of it, just make sure to put an id to the layout to be replaced. It is general practice to put the replaceable layout in a FrameLayout .
inside your onClickListener.onClick, put
getFragmentManager().beginTransaction().replace(R.id.container, new tasks()).commit();
In another word, in your mycontacts.class
public class mycontacts extends Fragment {
public mycontacts() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View v = super.getView(position, convertView, parent);
ImageView purple = (ImageView) v.findViewById(R.id.imageView1);
purple.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
getFragmentManager()
.beginTransaction()
.replace(R.id.container, new tasks())
.commit();
}
});
return view;
}
}
now, remember R.id.container is the container (FrameLayout or other layouts) for the activity that calls the fragment
You can move to another fragment by using the FragmentManager transactions. Fragment can not be called like activities,. Fragments exists on the existence of activities.
You can call another fragment by writing the code below:
FragmentTransaction t = this.getFragmentManager().beginTransaction();
Fragment mFrag = new MyFragment();
t.replace(R.id.content_frame, mFrag);
t.commit();
here "R.id.content_frame" is the id of the layout on which you want to replace the fragment.
You can also add the other fragment incase of replace.
If you're looking for the Kotlin version of the above code, you can do it in this way, and you call replaceFragment(RequiredFragment()) at onClickListener or wherever you want.
private fun replaceFragment(fragment: Fragment) {
val transaction = activity!!.supportFragmentManager.beginTransaction()
transaction.replace(R.id.frame, fragment)
transaction.commit()
}
private boolean loadFragment(Fragment fragment) {
if (fragment != null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fl_fragment_container, fragment)
.commit();
return true;
}
return false;
}
in kotlin, put inside of your current running fragment button.setOnClickListener
val bpfragment = TwoFragment()
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.fragment_container, bpfragment)?.commit()
val fragment = YourFragment3()
val fm : FragmentManager= requireActivity().supportFragmentManager
val ft: FragmentTransaction = fm.beginTransaction()
ft.replace(R.id.container, fragment)
ft.commit()
(activity as MainActivity).binding.viewPager.setCurrentItem(2)
We can use this one-
purple.setOnClickListener(view1 -> {
Fragment fragment = new task();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frame, fragment);
transaction.addToBackStack(null);
transaction.commit();
});