I'm trying to display a ListFragment that'll show user comments from within another Fragment. For testing purposes, I'm calling the ListFragment using an "onClick" method from within the parent Fragment. However, I can't seem to get the ListFragment to show, as it has no "show" method. Are there any obvious problems with my code that I can fix?
This is the method called when I click a button to show the ListFragment.
private void showComments(JSONArray comments) {
ListFragment newFragment = CommentsFragment.newInstance(comments);
}
And here is the ListFragment itself.
public class CommentsFragment extends ListFragment {
public static CommentsFragment newInstance(JSONArray passedComments) {
CommentsFragment f = new CommentsFragment();
ArrayList<String> adapter = convertJSON(passedComments);
Bundle args = new Bundle();
args.putStringArrayList("adapter", adapter);
f.setArguments(args);
return f;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle args = new Bundle();
ArrayList<String> commentsArray = args.getStringArrayList("adapter");
ArrayAdapter<String> commentsAdapter = new ArrayAdapter<String>(
getActivity(), R.layout.comments_list,
commentsArray);
setListAdapter(commentsAdapter);
}
You have to commit the ListFragment with a FragmentManager, and also have a layout in the XML that will contain it.
Firstly add a FrameLayout to the XML where you want the ListFragment placed, and afterwards use getChildFragmentManager() to get a FragmentManager, that you can place the ListFragment with.
Try like this
private void showComments(JSONArray comments) {
ListFragment newFragment = CommentsFragment.newInstance(comments);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(android.R.id.content, newFragment);
fragmentTransaction.commit();
}
Related
I am storing some values in array list now i want to pass the same array list object to fragment from an activity. So how can i send the array list object from an activity and receive the same object in fragment.
Try this code in your activity, It is a code snippet from my working application.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
yourArrayList.add("test");
yourArrayList.add("test2")
Bundle bundle = new Bundle();
bundle.putStringArrayList("arrayList", yourArrayList);
yourFragment yourFragment = new yourFragment();
yourFragment.setArguments(bundle);
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.main_container, yourFragment);
fragmentTransaction.commit();
}
In your fragment you can access the value like this
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayList<String> values = getArguments().getStringArrayList("arrayList");
}
pass activity should follow this lines
Bundle bundle = new Bundle();
bundle.putStringArrayList("valuesArray", namesArray);
namesFragment myFragment = new namesFragment();
myFragment.setArguments(bundle);
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.main_container, myFragment);
fragmentTransaction.commit();
get Fragment inside follow this lines
ArrayList<ObjectName> arraylist = extras.getParcelableArrayList("valuesArray");
You can do this by following the usual way of Fragment-Activity communication. That is:
1) Declare a public interface within your Fragment class.
2) Inside this interface declare a getter method for your list.
3) Make your respective Activity implement this interface.
4) Inside your Fragment, do this:
#Override
public void onAttach(Context context) {
super.onAttach(context);
YourInterfaceType activity = (YourInterfaceType) context;
List<> yourList = activity.getMyList();
}
To make it more clear:
Your activity will be as follows:
public class MyActivity extends Activity implements YourInterfaceType{
#Override
public void getMyList(){
return yourList;
}
}
just put your array with setargument in Actiivty and get Array
getArgument in fragment.
Activity
Bundle bundle = new Bundle();
bundle.putStringArrayList("valuesArray", namesArray);
namesFragment myFragment = new namesFragment();
myFragment.setArguments(bundle);
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.main_container, myFragment);
fragmentTransaction.commit();
fragment
ArrayList<Model> values = getArguments().getStringArrayList("valuesArray");
I was trying out android fragments, and i could not understand this; please help
public class MainActivity extends FragmentActivity {
private static final String TAG = "MyActivity";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.fragment_container) !=null) {
if(savedInstanceState!=null){
return ;
}
ArticleFragment first_fragment = new ArticleFragment();
HeadlineFragment second_fragment = new HeadlineFragment();
first_fragment.setArguments(getIntent().getExtras());
second_fragment.setArguments(getIntent().getExtras());
FragmentTransaction manager=getSupportFragmentManager().beginTransaction();
manager.add(R.id.fragment_container, first_fragment,"first");
manager.add(R.id.yo, second_fragment,"second");
manager.commit();
}
}
now i want to remove second_fragment at a button press and replace it with another. So i tried this
if(getSupportFragmentManager().findFragmentByTag("second")!=null) {
Log.d(TAG,"found");
abc newFragment = new abc();
Bundle args = new Bundle();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.remove(getSupportFragmentManager().findFragmentByTag("second"));
transaction.add(R.id.fragment_container,newFragment,"third");
transaction.addToBackStack(null);
transaction.commit();
}
but when i press that button again and again, the if condition passes.
What is wrong here?
Don't Do removing and adding. Simply Replace second fragment with the new one. You will be done.
I have trouble understanding in FragmentTransaction.replace(id, fragment, 'string') what does .replace actually
I read somewhere that it will replace the content of view id with fragment but in my
public class MainActivity extends
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.fragment_container) !=null) {
if(savedInstanceState!=null){
return ;
}
ArticleFragment first_fragment = new ArticleFragment();
HeadlineFragment second_fragment = new HeadlineFragment();
first_fragment.setArguments(getIntent().getExtras());
second_fragment.setArguments(getIntent().getExtras());
FragmentTransaction manager=getSupportFragmentManager().beginTransaction();
manager.add(R.id.fragment_container, first_fragment,"first");
manager.add(R.id.fragment_container, second_fragment,"second");
manager.commit();
}
abc newFragment = new abc();
Bundle args = new Bundle();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment,"second");
transaction.addToBackStack(null);
transaction.commit();
}
}
it only replaces the first fragment that i added to Transaction, i.e. first_fragment.
And how do i replace a specific fragment?
The issue seems to be with R.id.fragment_container. You should have a different first argument on the line below in order to replace a fragment that is not your "first" fragment:
manager.add(R.id.fragment_container, second_fragment,"second");
I am reasonably new to fragments, so I apologise if this is quite basic.
My app contains a ViewPager to swipe between several different tabs with ListViews. On clicking one particular ListView item, I would like to open a DialogFragment displaying some options. My intention is to have the DialogFragment deal with the click event and feed the selected dialog item back to the fragment that called it. I am doing this by providing a callback to MainActivity (which contains the ViewPager) and feeding that information down to the correct ViewPager fragment.
What I have noticed is that my DialogFragment is returning null on getActivity(), which I believe is because my DialogFragment is not correctly attached to my MainActivity. How can I achieve this? I find it a little harder to navigate through this issue considering I am new to callbacks and most other examples dealing with fragments are for standard fragments, not those from ViewPager.
How can my dialog identify the correct activity? Should I be attaching the fragment to a FragmentManager? If so, should it be attached to the same FragmentManager as the ViewPager fragments?
This is my code, though I'm not sure how helpful it will be.
CalibrationFragment.java - Calling the DialogFragment. (Not sure if this is the correct way to do it.)
ModeDialogFragment modeDialog = ModeDialogFragment.newInstance(R.string.mode_calibration);
modeDialog.onCreateDialog(null);
ModeDialogFragment.java - My DialogFragment
public class ModeDialogFragment extends DialogFragment{
public static ModeDialogFragment newInstance(int title) {
ModeDialogFragment frag = new ModeDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
public void onAttach(Activity activity){
super.onAttach(activity);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
final Context mContext = getActivity();
getActivity().getFragmentManager().beginTransaction().add(newInstance(R.string.mode_calibration), "my_fragment").commit();
// Trying to add my dialog to the MainActivity, not working.
final CharSequence[] modeItems = {
"Option 1", "Option 2", "Option 3"
};
final int checkedItem = 2; // Make final for now, resolve this later
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(getResources().getString(R.string.mode_calibration));
builder.setSingleChoiceItems(modeItems, checkedItem, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
// Handle the selection here
((MainActivity)getActivity()).updateModeData();
}
});
return(builder.create());
}
}
MainActivity.java
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
// Initialise variables
private Context mContext;
// [Others...]
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialisation
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
}
public Fragment findFragmentByPosition(int position) {
int viewId = R.id.pager;
//FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
return getSupportFragmentManager().findFragmentByTag(
makeFragmentName(viewId, position));
}
// Needed to identify a fragment from ViewPager
private static String makeFragmentName(int viewId, int position)
{
return "android:switcher:" + viewId + ":" + position;
}
public void updateModeData(){
// Make call to the fragment to deal with the data
CalibrationFragment calFragment = (CalibrationFragment) findFragmentByPosition(3);
((CalibrationFragment) calFragment).doUpdateModeData();
}
}
Any help or guidance would be appreciated!
EDIT: The problem was indeed that I was not adding the fragment to a FragmentManager and calling it correctly. This is the code I used. My code still does not run through in its entirety, but for the purpose of this question, my DialogFragment can now access MainActivity.
CalibrationFragment.java - Calling DialogFragment
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ModeDialogFragment modeDialog = ModeDialogFragment.newInstance(R.string.mode_calibration);
String title = makeFragmentName(R.id.pager, 3); // makeFragmentName as specified in MainActivity.java
modeDialog.show(ft, title);
ModeDialogFragment.java is the same as before, but with the following line removed:
getActivity().getFragmentManager().beginTransaction().add(newInstance(R.string.mode_calibration), title).commit();
You shouldn't call onCreateDialog by yourself. Just call show method with FragmentTransaction:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ModeDialogFragment modeDialog = ModeDialogFragment.newInstance(R.string.mode_calibration);
modeDialog.show(ft, null);
Right usage of DialogFragment is described here: http://developer.android.com/reference/android/app/DialogFragment.html
I just started with fragment design for HoneyComb. I created two fragments. When i click a button in the left side fragment, a new fragment is created in right side. Meanwhile when i click a button in the right fragment(ie. DetialsFragment in my code below should be replaced by another fragment.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment class="com.fragment.example.Titles"
android:id="#+id/titles" android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
<FrameLayout android:id="#+id/details" android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />
</LinearLayout>
FragmentExample.java
public class FragmentExample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Titles.java
public class Titles extends Fragment {
public FragmentTransaction ft;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.main1, null);
Button button1 = (Button)v.findViewById(R.id.button1);
button1.setText("santhosh");
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
DetailsFragment details = (DetailsFragment)
getFragmentManager().findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != 1) {
// Make new fragment to show this selection.
details = DetailsFragment.newInstance(1);
// Execute a transaction, replacing any existing
// fragment with this one inside the frame.
ft
= getFragmentManager().beginTransaction();
ft.add(R.id.details, details, "detail");
ft.setTransition(
FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
}
});
return v;
}
}
DetailsFragment.java
public class DetailsFragment extends Fragment {
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
Titles title = new Titles();
String[] titles = {"Title1", "Title2", "Title3", "Title4"};
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
public int getShownIndex() {
return getArguments().getInt("index", 0);
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
// Currently in a layout without a container, so no
// reason to create our view.
return null;
}
Button button = new Button(getActivity());
button.setText("Next");
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
return button;
}
}
Then provided your button is showing and the click event is being fired you can call the following in your click event:
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, new NewFragmentToReplace(), "NewFragmentTag");
ft.commit();
and if you want to go back to the DetailsFragment on clicking back ensure you add the above transaction to the back stack, i.e.
ft.addToBackStack(null);
Or am I missing something? Alternatively some people suggest that your activity gets the click event for the button and it has responsibility for replacing the fragments in your details pane.
Latest Stuff
Okay. So this is a very old question and has great answers from that time. But a lot has changed since then.
Now, in 2020, if you are working with Kotlin and want to change the fragment then you can do the following.
Add Kotlin extension for Fragments to your project.
In your app level build.gradle file add the following,
dependencies {
def fragment_version = "1.2.5"
// Kotlin
implementation "androidx.fragment:fragment-ktx:$fragment_version"
// Testing Fragments in Isolation
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}
Then simple code to replace the fragment,
In your activity
supportFragmentManager.commit {
replace(R.id.frame_layout, YourFragment.newInstance(), "Your_TAG")
addToBackStack(null)
}
References
Check latest version of Fragment extension
More on Fragments
You can try below code. it’s very easy method for push new fragment from old fragment.
private int mContainerId;
private FragmentTransaction fragmentTransaction;
private FragmentManager fragmentManager;
private final static String TAG = "DashBoardActivity";
public void replaceFragment(Fragment fragment, String TAG) {
try {
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(mContainerId, fragment, tag);
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.commitAllowingStateLoss();
} catch (Exception e) {
// TODO: handle exception
}
}
Use android.support.v4.app for FragmentManager & FragmentTransaction in your code, it has worked for me.
DetailsFragment detailsFragment = new DetailsFragment();
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.details,detailsFragment);
fragmentTransaction.commit();
If you have a handle to an existing fragment you can just replace it with the fragment's ID.
Example in Kotlin:
fun aTestFuction() {
val existingFragment = MyExistingFragment() //Get it from somewhere, this is a dirty example
val newFragment = MyNewFragment()
replaceFragment(existingFragment, newFragment, "myTag")
}
fun replaceFragment(existing: Fragment, new: Fragment, tag: String? = null) {
supportFragmentManager.beginTransaction().replace(existing.id, new, tag).commit()
}
Updated Answer (Working for Overlap problem as well)
#aniket-thakur(https://stackoverflow.com/users/2396539/aniket-thakur) gave correct answer. Thank you for that!
But, getFragmentManager() is deprecated, so following code did work for me.
final FragmentTransaction ft = getParentFragmentManager().beginTransaction();
ft.replace(R.id.nav_host_fragment, new GalleryFragment(), "NewFragmentTag");
ft.addToBackStack(null);
ft.commit();
it's very simple how to replace with Fragment.
DataFromDb changeActivity = new DataFromDb();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.changeFrg, changeActivity);
transaction.commit();