Android create fragment with Arguments not work - android

I want to create fragment with Arguments,
and refer to this post [ Do fragments really need an empty constructor? ].
But not work, I don't know how to fix it.
Code:
Fragment
public class TestFragment extends Fragment {
private final static String BUNDLE_TITLE = "title";
private RelativeLayout rootView;
private String title = "";
public static TestFragment newInstance(String titleName){
Bundle bundle = new Bundle();
bundle.putString(BUNDLE_TITLE,titleName);
TestFragment testFragment = new TestFragment();
testFragment.setArguments(bundle);
return testFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
if (rootView == null) {
rootView = (RelativeLayout) inflater.inflate(R.layout.find_mac, container, false);
}
return rootView;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle data = getArguments();
if(data != null){
this.title = getArguments().getString(BUNDLE_TITLE,"");
}
}
String getTitle() {
return title;
}
}
And in Activity,
#Override
protected void onStart() {
super.onStart();
TestFragment testFragment = TestFragment.newInstance("hello");
Log.d("debug","get title:"+testFragment.getTitle());
}
The Log show only "get title:",
I can't get the title "hello" word.

This is because when you calling:
TestFragment testFragment = TestFragment.newInstance("hello");
Log.d("debug","get title:"+testFragment.getTitle());
the testFragment fragment is not yet finished created. Because it is an asynchronous process.
So, you need to create a listener in activity to tell that the fragment is created, then in it, you can get the title.
You can read Communicating with Other Fragments for implementing the listener.

Related

Child Fragment is not animated on EnterTransition

After changing to the Android Navigation Component I encountered some problems with migrating my Activity Transitions to the corresponding Fragment Transitions.
Specifically, it appears that the EnterTransition of a Fragment doesn't apply to it's Child Fragments.
I've set up a test activity that contains an OuterTestFragment, which in turn consists of a TextView and another fragment, InnerTestFragment.
A button in the activity then replaces the OuterTestFragment with a new OuterTestFragment to see if the contents transition smoothly.
Here are the relevant classes:
Activity:
public class PlaygroundActivity extends AppCompatActivity {
public static final ArrayList<String> strings = new ArrayList<>();
static {
strings.add("sgdgdgsdfggggggggsdgsdfgsd\nsdsdgsdfgds\ndfgsd\nsdsdgsdfgds\ndfgsd");
strings.add("sgdgdgsdfgggg\nggggsndfgsd\nsdsdgsdfgds\ndfgsd");
strings.add("sgdgsd\nsdsdgsdfgds\ndfgsd");
strings.add("sgdgdgsdfggfgds\ndfgsd");
strings.add("sgdgdgsdfggggggggsdg");
}
int count = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playground);
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainerOuter, OuterTestFragment.getInstance("This is an inner text", "Outer text!"))
.commit();
}
public void replace(View v) {
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.addToBackStack("replaced")
.replace(R.id.fragmentContainerOuter, InnerTestFragment.getInstance(count++ >= 4 ? "Default" : strings.get(count)))
.commit();
}
}
OuterTestFragment:
public class OuterTestFragment extends TransitionedFragment {
private static final String ARG_OUTER_TEXT = "OuterTestFragment:outerText";
private static final String ARG_INNER_TEXT = "OuterTestFragment:innerText";
private String innerText;
private String outerText;
public static OuterTestFragment getInstance(String inner, String outer) {
OuterTestFragment outerFragment = new OuterTestFragment();
Bundle args = new Bundle();
args.putString(ARG_OUTER_TEXT, outer);
args.putString(ARG_INNER_TEXT, inner);
outerFragment.setArguments(args);
return outerFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
innerText = getArguments().getString(ARG_INNER_TEXT);
outerText = getArguments().getString(ARG_OUTER_TEXT);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.test_fragment_outer, container, false);
((TextView) layout.findViewById(R.id.textOuter)).setText(outerText);
getFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, InnerTestFragment.getInstance(innerText))
.commit();
return layout;
}
}
TransitionedFragment:
public abstract class TransitionedFragment extends Fragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TransitionInflater inflater = TransitionInflater.from(getContext());
setEnterTransition(inflater.inflateTransition(R.transition.default_transition));
setReenterTransition(inflater.inflateTransition(R.transition.default_transition));
setSharedElementEnterTransition(inflater.inflateTransition(R.transition.scaled_img_clip_transition));
}
}
Inner Test Fragment:
public class InnerTestFragment extends Fragment {
private static final String ARG_TEXT = "InnerTestFragment:text";
private String text;
public static InnerTestFragment getInstance(String text) {
InnerTestFragment frgmt = new InnerTestFragment();
Bundle args = new Bundle();
args.putString(ARG_TEXT, text);
frgmt.setArguments(args);
return frgmt;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
text = getArguments().getString(ARG_TEXT);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.test_fragment_inner, container, false);
((TextView) layout.findViewById(R.id.text)).setText(text);
return layout;
}
}
Any help is much appreciated, as the Transition API drives me nuts....
You may show transitions with the setEnterTransition method.
Fragment fragment = InnerTestFragment.getInstance(innerText);
Fade enterFade = new Fade(); //can be any transition, SlideTransition or Inflated Transitions
enterFade.setDuration(300); //Duration of transition in ms
fragment.setEnterTransition(enterFade);
getFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, fragment)
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
Try to add a background color to the child fragment...

how to pass string from activity to fragment?

Activity A
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ActivityA);
Bundle b = new Bundle();
b.putString("mobile", "123456789");
FragmentA fragmentA = new FragmentA ();
fragmentA .setArguments(b);}
FragmentA
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_fragmentA, container, false);
String txtMobile = getArguments().getString("mobile");
Log.i("mobile2",txtMobile);
mobile.setText(txtMobile);}
I have tried above solution but showing error that
Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
May be It's about the way you are adding fragment to the class:
Bundle b = new Bundle();
b.putString("mobile", "123456789");
FragmentA fragmentA = new FragmentA ();
fragmentA .setArguments(b);
fm.beginTransaction()
.replace(placeholder, new FragmentA(), tabId)
.commit();
can you provide more data about how did you add it ?
Create your fragment like this
public static MyFragment newInstance(String string) {
Bundle args = new Bundle();
args.putString("string",string);
MyFragment fragment = new MyFragment();
fragment.setArguments(args);
return fragment;
}
And then in Fragment onCreate use getArguments() for pulling that String. Don't forget to check getArguments() for null.
Try to fetch the argument in onCreate method of fragment with default value constructor:
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String txtMobile = getArguments().getString("mobile", "");
}
and make sure you commit the fragment transaction after settting the arguments in fragment. :)
First check that your argument is not null.
For example
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_fragmentA, container, false);
if(getArguments()!=null){
String txtMobile = getArguments().getString("mobile");
Log.i("mobile2",txtMobile);
mobile.setText(txtMobile);
}
}
try this:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null){
String txtMobile = savedInstanceState.getString("mobile");
}
}
you can use inteface to pass data from activity to fragment
In your activity
public interface FragmentRefreshListener {
void onRefresh(String mydata);
}
public FragmentRefreshListener fragmentRefreshListener;
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
Then inside your fragment add below code
((MainActivity) getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {
#Override
public void onRefresh(String mydata) {
// write your logic here
}
});
use following in your activity to pass data from activity to fragment
getFragmentRefreshListener().onRefresh("dummy text");

pass data to Fragment

I have an Activity and a simple fragment ,I try to use Bundle to pass data to the fragment, but the bundle is always null.
I can't figure out what is the problem?!
this is my Activity class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentA fragmentA =new FragmentA();
Bundle bundle=new Bundle();
bundle.putString("name","Ahmed Ezzat");
fragmentA.setArguments(bundle);
}
public void showFragment(View view) {
FragmentA fragmentA=new FragmentA();
FragmentManager manager=getSupportFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.dumper,fragmentA,"fragment A");
transaction.commit();
}
}
and this is my fragment class
public class FragmentA extends Fragment {
TextView textView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_a,container,false);
textView= (TextView) view.findViewById(R.id.tv_fragment);
Bundle bundle = this.getArguments();
String name = bundle.getString("name");
if (name!=null){
textView.setText(name);}
return view;
}
}
any help?
You never called setArguments in the showFragment method.
The Fragment in the onCreate method is never used.
You may try using the following code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showFragment(View view) {
FragmentA fragmentA=new FragmentA();
Bundle bundle=new Bundle();
bundle.putString("name","Ahmed Ezzat");
fragmentA.setArguments(bundle);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.dumper,fragmentA,"fragment A")
.commit();
}
}
You can pass data to the fragment when building the fragment, then passing it to the transaction.
public class FragmentA extends Fragment {
TextView textView;
String message;
public FragmentA(String message){
this.message = message;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_a,container,false);
textView= (TextView) view.findViewById(R.id.tv_fragment);
textView.setText(message);
return view;
}
And when attaching, you just pass it in the constructor.

How to a get a view of fragment in Android

Hello I am using Fragment in my android application. I need to get the view which I can get using.
mNoteEditText = rootView.findViewById(R.id.noteEditText);
This mNoteEditText is require to access in onBackPressed so every view reference I need to make them static variable because of Fragment class is static. I know to make every view to static variable is not good approach. How this I can make such that I dont need to make any static variable of the view.
public class NotesActivity extends Activity {
private int bookId;
private int chapterId;
private static EditText mNoteEditText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notes);
// get data from intent that sent from home activity
bookId = getIntent().getIntExtra("book_id", -1);
chapterId = getIntent().getIntExtra("book_id", -1);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new NoteFragment()).commit();
}
}
/**
* A note fragment containing a note layout.
*/
public static class NoteFragment extends Fragment {
public NoteFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_notes,
container, false);
mNoteEditText = (EditText) rootView.findViewById(R.id.noteEditText);
return rootView;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
// get database instance
MySQLiteOpenHelper db = MySQLiteOpenHelper.getInstance(this);
Notes note = new Notes();
note.setBookId(bookId);
note.setChapterId(chapterId);
note.setNote(mNoteEditText.getText().toString());
}
}
Please help and thanks in advance.
A Fragment has a Method called getView(). With it you can get the View of the Fragment as long as it is attached to an Activity.
View view = fragment.getView();
But if you are looking for a View inside the Fragment you can also just get it with findViewById() from the Activity. Again the Fragment has to be attached to the Activity for this to work.
BUT you should not do that. Nothing outside the Fragment should have anything to do with something inside the Fragment. Write public methods in the Fragment to interact with it. Try something like this:
public static class NoteFragment extends Fragment {
private EditText noteEditText;
public NoteFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_notes, container, false);
this.noteEditText = (EditText) rootView.findViewById(R.id.noteEditText);
return rootView;
}
// I added the following 3 methods to interact with the Fragment
public boolean isEmpty() {
final String text = this.noteEditText.getText().toString();
return text.isEmpty();
}
public String getText() {
return this.noteEditText.getText().toString();
}
public void setText(String text) {
this.noteEditText.setText(text);
}
}
And now in your Activity you can do this:
public class NotesActivity extends Activity {
private int bookId;
private int chapterId;
private NoteFragment noteFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notes);
// get data from intent that sent from home activity
bookId = getIntent().getIntExtra("book_id", -1);
chapterId = getIntent().getIntExtra("book_id", -1);
if (savedInstanceState == null) {
this.noteFragment = new NoteFragment();
getFragmentManager().beginTransaction().add(R.id.container, this.noteFragment).commit();
}
// Now you can interact with the Fragment
this.noteFragment.setText("some text");
...
if(!this.noteFragment.isEmpty()) {
String note = this.noteFragment.getText();
...
}
}
}

How to send data from Activity to Fragment

I know there are many topics about this here. I have also read documentation many times but I can't find the best way to pass data from activity to fragment.
I want to be able to show the results of my Searchable activity in two differents layouts (list and map) using swipe Views with tabs. I have to pass 2 data to the fragments: "currentLocation" which is the current user location and "result" which is a list of objects.
I have omited some parts of my code to make it more understandable.
SearchableActivity.java
public class SearchableActivity extends ActionBarActivity implements TabListener {
List<PlaceModel> result = new ArrayList<PlaceModel>();
private SearchView mSearchView;
private String currentLocation;
AppSectionsPagerAdapter mAppSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_searchable);
final ActionBar actionBar = getSupportActionBar();
actionBar.setHomeButtonEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
actionBar.addTab(actionBar.newTab().setText("List").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Map").setTabListener(this));
// get currentLocation here
handleIntent(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
final String query = intent.getStringExtra(SearchManager.QUERY);
// get result here
}
}
#Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction arg1) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
}
PlaceListFragment.java
public class PlaceListFragment extends Fragment {
ListView listViewData;
PlaceAdapter placeAdapter;
List<PlaceModel> result = new ArrayList<PlaceModel>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list, container, false);
Bundle args = getArguments();
listViewData = (ListView) rootView.findViewById(android.R.id.list);
// I will pass result and currentLocation here
placeAdapter = new PlaceAdapter(getActivity(), R.layout.fragment_list_item, result, currentLocation);
listViewData.setAdapter(placeAdapter);
return rootView;
}
}
AppSectionsPagerAdapter.java
public class AppSectionsPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 2;
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int arg0) {
Bundle data = new Bundle();
switch(arg0) {
case 0:
PlaceListFragment fragment1 = new PlaceListFragment();
fragment1.setArguments(data);
return fragment1;
default:
PlaceListFragment fragment2 = new PlaceListFragment();
fragment2.setArguments(data);
return fragment2;
}
}
#Override
public int getCount() {
return PAGE_COUNT;
}
}
Find fragment in Activity onCreate and set data to a method you write in your fragment:
ExampleFragment rf = (ExampleFragment) getSupportFragmentManager().findFragmentById(R.id.exampleFragment);
if(rf!=null){
rf.setExample(currentExample);
}
"CurrentExample" is whatever you want to send in to your "setExample" method in your fragment.
public void setExample(ExampleObject currentExample){
currentExampleInFragment = currentExample;
}
You can use the data in onActivityCreated method of Fragment.
Not sure is this is a good solution or not, but I found it the easiest one for passing objects.
Usually the activities will have a reference to their fragments. In your SearchableActivity.java are you also loading PlaceListFragment.java either in setContentView(activity_searchable.xml); or you need to create a instance of the fragment and add/replace a fragment using FragmentTransaction.
you can find a good example here on how to communicated between fragments or between activity & fragment.
Training link
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
and in Fragment onCreateView method:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
return inflater.inflate(R.layout.fragment, container, false);
}
see detail answer here..
"send data from Activity to Fragment"
Activity:
Bundle bundle = new Bundle();
bundle.putString("message", "Alo Stackoverflow!");
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();
Fragment:
Reading the value in the fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = this.getArguments();
String myValue = bundle.getString("message");
...
...
...
}
or
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
String myValue = this.getArguments().getString("message");
...
...
...
}
Create one Session model class and in Activity set the values you want to data needs to be send then in Fragment you can get that values from Session model class
eg. from your activity u can set like this.
AllEventDetails.getInstance().setEvent_description(event_Description);
AllEventDetails.getInstance().setDj_name(dj_name);
AllEventDetails.getInstance().setMusic_theme(music_theme);
AllEventDetails.getInstance().setClub_name(club_name);
AllEventDetails.getInstance().setDate(event_date);
AllEventDetails.getInstance().setBanner_image_path(banner_image_path);
AllEventDetails.getInstance().setEvent_title(event_title);
and from your Fragment u can retrive like this.
AllEventDetails.getInstance().getClub_name()
.........
Creating Session model class is like this.
public class AllEventDetails {
private static AllEventDetails mySession ;
private String event_description;
private String dj_name;
private String music_theme;
private String club_name;
private String date;
private String banner_image_path;
private String event_title;
private AllEventDetails() {
event_description = null;
dj_name = null;
music_theme = null;
club_name = null;
date = null;
banner_image_path = null;
event_title = null;
}
public static AllEventDetails getInstance() {
if( mySession == null ) {
mySession = new AllEventDetails() ;
}
return mySession ;
}
public void resetSession() {
mySession=null;
}
public String getEvent_description() {
return event_description;
}
public void setEvent_description(String event_description) {
this.event_description = event_description;
}
public String getDj_name() {
return dj_name;
}
public void setDj_name(String dj_name) {
this.dj_name = dj_name;
}
public String getMusic_theme() {
return music_theme;
}
public void setMusic_theme(String music_theme) {
this.music_theme = music_theme;
}
public String getClub_name() {
return club_name;
}
public void setClub_name(String club_name) {
this.club_name = club_name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getBanner_image_path() {
return banner_image_path;
}
public void setBanner_image_path(String banner_image_path) {
this.banner_image_path = banner_image_path;
}
public String getEvent_title() {
return event_title;
}
public void setEvent_title(String event_title) {
this.event_title = event_title;
}
}

Categories

Resources