I have created a MainActivity which consists of 3 tabs which are scrollable (by using ViewPager). Now each of these 3 tabs is a Fragment. Also, I am using ActionBarSherlock (ABS).
For the 1st Fragment, I have created the following class:
public class Fragment_1 extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment1, container, false);
return v;
/* R.layout.fragment1 only contains a TextView. */
}
}
For the 2nd Fragment, I want to extend a FragmentActivity as shown below.
public class Fragment_2 extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment2);
}
}
The 3rd Fragment is same as the first one.
But when I launch the app, it crashes. So, am I wrong in extending FragmentActivity for the class Fragment_2? Is it illegal to extend a FragmentActivity or even an Activity to fragment classes? If not, what is the problem here?
Thanks.
EDIT: After #CommonsWare's answer I updated my class as follows:
public class Fragment_2 extends SherlockFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button send = (Button) findViewById(R.id.bSend); //Error at this line
//some error free code
FragmentTransaction t = getSupportFragmentManager().beginTransaction(); //Error at this line
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment2, container, false);
return v;
}
My final two questions are:
How should I access my R.id.bSend Button in the Fragment_2 class.
Eclipse is giving the suggestion to change getSupportFragmentManager() to getFragmentManager(). Is that change all right?
Thanks!
Is it illegal to extend a FragmentActivity or even an Activity to fragment classes?
Fragment is a Java class. Your fragment implementations (for use as pages in your ViewPager) must inherit from Fragment, directly or indirectly.
Activity does not inherit from Fragment. FragmentActivity does not inherit from Fragment. Hence, you cannot inherit from Activity or FragmentActivity and somehow also inherit from Fragment.
Related
I am developing an application where i need to call two fragments on an activity replacing another fragment,one of the fragment will contain a Form and another fragment will contain another Form ,i don't have any idea how to do this,so any suggestion will be cordially appreciated,thanks in advance....
I want to replace Form on Click button. by R&D i come to know at this point i need to use to fragment with two layout each layout will contain Forms.
Main Activity.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Fragment 1.
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment1, container, false);
}
Fragment 2.
public class Fragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment2, container, false);
}
}
You can try like this
FragmentTransaction ft=getSupportFragmentManager().beginTransaction();
ft.add(Home.newInstance(),"First");
ft.add(Second.newInstance(),"Second");
ft.commit();
So here you are added multiple fragment into the stack
If you are trying to replace Fragment1 with Fragment2, you replace the fragment.
https://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#replace(int,%20android.support.v4.app.Fragment)
Users have a crash. I know why but I do not know how to fix it. I am newbie in android dev.
Situation:
Android: Fragment inside Activity. Fragment has an EditText. Activity has a button. User tap the button. Inside Button.OnClick() I want to get text Fragment.EditText.getText();
Some users have a crash here EditText.getText(). i.e. EditText is null.
How I do:
In Activity:
public class MyAcrivity extends AppCompatActivity implements OnFragmentInteractionListener {
final MyFrag myFrag= MyFrag.newInstance();
public void run(final View view) {
//some users have crash here because getEt() return null
final String str = myFrag.getEt().getText().toString();
}
}
In Fragment:
public class MyFrag extends Fragment {
private EditText et;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_myfrag, container, false);
et = (EditText) view.findViewById(R.id.et);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
et = (EditText) view.findViewById(R.id.et);
}
public EditText getEt() {
// return (EditText) getView().findViewById(R.id.et); here getView() could be nul too
return et;
}
}
I know getView() could be null (already googled it).
Init "View" inside onCreateView useless. Crash still happend.
Init "View" inside onViewCreated useless. Crash still happend.
I can NOT reproduce this crash in emulator or my smartphone. I have stable work of my app. BUT some users have the crash and Fabric(crashlytics) is sending messages about it.
People! Help! How to obtain some View from Fragment correctly? I can not to find answers from lifecycle of Fragment. Please explain to me what is wrong.
From your code it seems you have only created instance of fragment and trying to access the view .But to get the view of the fragment you have to add fragment to your activity.
Do this in your activity
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
MyFrag myFrag= MyFrag();
ft.replace("YOUR_FRAGMENT_CONTAINER's id", myFrag);
ft.commit();
Just a hunge, try to do the newInstance() call in the activity lifecycle. Otherwise, there might not be a trustable context to attach fragments. Try to do so in the onCreate().
And something that might be unrelated, but did you properly attach that fragment to the activity? Chances are you are already doing, since some users are correctly accessing it. Anyway, here's the fragment documentation, and a code block to attach it.
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment myFrag = MyFrag.newInstance();
fragmentTransaction.add(R.id.fragment_container, myFrag);
fragmentTransaction.commit();
Use butterknife like this:
class ExampleActivity extends Activity {
#Bind(R.id.user) EditText username;
#Bind(R.id.pass) EditText password;
#BindString(R.string.login_error)
String loginErrorMessage;
#OnClick(R.id.submit) void submit() {
// TODO call server...
}
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...
}
}
Add the fragment to the Activity in Activity.onCreate() method.
Get the reference to the Activity during Fragment.onAttach (Context) in the Fragment.
Create a method in Activity like enableButton(), which will enable the button like button.setEnabled (true).
Call this method from Fragment onCreateView after initializing the EditText.
This way you can ensure that EditText is initialized before the button is clicked.
Also remember to make the Activity reference null in Fragment.onDetach() to prevent any leak.
If you use getActivity.findViewById in Fragment.
public class MyFrag extends Fragment {
private EditText et;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_myfrag, container, false);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
et = (EditText) getActivity.findViewById(R.id.et);
}
public EditText getEt() {
// return (EditText) getView().findViewById(R.id.et); here getView() could be nul too
return et;
}
}
I have 2 Fragments - ButtonFragment and ListViewFragment - in my Activity MainActivity.
ButtonFragment contains a Button, ListViewFragment contains a ListView.
Each time I click on the ButtonFragment Button I want the ListViewFragment to show/hide.
How do I code this properly?
Currently my code looks like this:
MainActivity.java
public class MainActivity extends Activity implements Communicator {
ButtonFragment buttonFrag;
ListViewFragment listviewFrag;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonFrag= new ButtonFragment();
listviewFrag = new ListViewFragment();
manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.button_fragment, buttonFrag, "Fragment1");
transaction.add(R.id.listview_fragment, listviewFrag, "Fragment2");
transaction.commit();
}
}
ButtonFragment.java
public class DynamicButtonsFragment extends Fragment implements View.OnClickListener {
Button btn;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.button_fragment_layout, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onClick(View v) {
//?? hide listview fragment from here ??
}
}
ListViewFragment.java
public class ListViewFragment1 extends Fragment {
protected ArrayAdapter<String> adapter1;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.list_view_fragment, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}
So my question is where do I implement the showing/hiding of ListViewFragment? I feel like I should send data to the MainActivity through the onClick method of ButtonFragment. But I do not know how to do so.
Or do I only add code in the MainActivity since the MainActivity has access to all the Fragments?
I am having trouble becase the Button is in a Fragment, not part of the MainActivity. I haven't really seen cases like this...
Can someone please help?
You cannot show/hide a Fragment directly. You may show/hide a UI object like Listview. If you like, you can show/hide Fragment indirectly by using the FragmentTransaction, and you can call its method add, remove or replace.
A link for sample code is Fragments
Do this ..
android.app.Fragment fragment = getActivity().getFragmentManager().findFragmentByTag("YOUR_FRAGMENT_TAG");
getActivity().getFragmentManager().beginTransaction().hide(fragment);
inside your click event!
One more thing when you add fragments like this..
transaction.add(R.id.button_fragment, buttonFrag, "Fragment1");
transaction.add(R.id.listview_fragment, listviewFrag, "Fragment2");
you're expected to provide the container id instead of the id of the fragment.
Example: For MainActivity container use R.id.containerMain
If you in fragment want to do some MainActivity function , you can try
#Override
public void onClick(View v) {
//?? hide listview fragment from here ??
((MainActivity)getActivity()).hidelistView();
//hidelistView you should imp in your MainActivity
}
If you have fragments within the same layout, you can use the following code:
http://www.java2s.com/Code/Android/Core-Class/Demonstrationofhidingandshowingfragments.htm
If not, than you can use several possibilities...
You can use an Intent to send data to MainActivity.
You can have a singleton instance where you store pointer to your MainActivity.
You can also use Handler to send messages, but the ways discribed above are easier to implement and should be enough for you.
I have used fragments in app. When i pass constructor of FragmentActivity class to the fragment it gives an error i.e. "Type mismatch: cannot convert from ReadFragment to Fragment". Thanks in advance for your help
ReadFragment.java
public class ReadFragment extends FragmentActivity {
public ReadFragment(){
}
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.read_layout);
}
}
MainActivity.java
......
Fragment fragment = null;
fragment = new ReadFragment();
......
}
I guess what you want to do is either:
public class ReadFragment extends Fragment {
or (and this should not work because you cannot cast from one to the other):
fragment_activity = new ReadFragment();
fragment = (fragment) fragment_activity;
Now you can chose
FragmentActivity is not a Fragment and thus cant be assigned to a variable of type Fragment. Your ReadFragment should extend Fragment instead. I would suggest doing this tutorial to learn the basics of fragments and probably search the web for Java tutorials, this is the very basics of Java.
public class ReadFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//For more info how to implement this i highly suggest you read the tutorial.
}
...
}
When extending Fragment you also need to override OnCreateView.
I have two fragments, MyFirst fragment and MySecond fragment. MySecond fragment extends from MyFirst fragment.
classed are like this:
public class MyFirstFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
// Check view and map, request to recreate if each of them is null
if(MyFirstFragment.this.getView() == null || googleMap == null) {
Toast.makeText(getActivity().getApplicationContext(), R.string.my_message, Toast.LENGTH_LONG).show();
return;
}
}
}
public class MySecondFragment extends MyFirstFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
}
}
My problem is super.onActivityCreated(savedInstanceState); in onActivityCreated() method of MySecondFragment calls its super. Since I want to hide functionality of this method in super class (Which is not useful for this fragment) I have added onActivityCreated() method in MySecondFragment.
The problem is if I remove this line then I have run-time error that throws "SuperNotCalledException".
What you think? seems I have to extend Fragment class instead of extending MyFirstFragment.
I have some variables in MyFirstFragment that I need them in MySecondFragment.
You can write a new Function testFunction(Bundle savedInstanceState) in your MyFirstFragment in which call super.onActivityCreated(savedInstanceState);
And in your MySecondFragment's onActivityCreated call this testFunction(Bundle savedInstanceState) rather than super.onActivityCreated(savedInstanceState);
i.e.
in MyFirstFragment
testFunction(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
in MySecondFragment
public void onActivityCreated(Bundle savedInstanceState) {
super.testFunction(savedInstanceState);
...
}
i don't clearly understand your basic requirment to bypass the MyFirstFragment's onActivityCreated but you can do this way.
You need to call the Fragment's implementation regardless. If you don't want to call MyFirstFragment's implementation there's a few solutions:
The cleanest one, give MyFirstFragment and MySecondFragment a common ancestor, which will be pretty much MyFirstFragment , except for onActivityCreated(). Both activities will inherit directly from it.
call super, but add a variable to the bundle to let MyFirstFragment know that its implementation is not to be called this time.
Just extend Fragment in MySecondFragment
You should always call the super method. Just set the variables you need in the MySecondFragment.onActivityCreated() method and use them afterwards. To hide functionality you can always check the calling object class but this goes against the OOP inheritance principles.