I am making a login page with fragments but whenever i run the application i am only getting a white scree,no edittext no buttons nuthing.
LoginFragment
public class LoginFragment extends Fragment {
private View view;
private Button btcancel;
private EditText etpassword;
private Button btlogin;
private EditText etusername;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view=inflater.inflate(R.layout.login_frag,container,false);
return view;
}
private void initialize() {
btcancel = (Button) getActivity().findViewById(R.id.bt_cancel);
etpassword = (EditText) getActivity().findViewById(R.id.et_password);
btlogin = (Button) getActivity().findViewById(R.id.bt_login);
etusername = (EditText) getActivity().findViewById(R.id.et_user_name);
}
}
LoginActivity
public class LoginActivity extends Activity {
private FragmentTransaction fragmentTransaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragmentSetUp();
}
private void fragmentSetUp() {
fragmentTransaction=getFragmentManager().beginTransaction();
LoginFragment loginFragment=new LoginFragment();
fragmentTransaction.add(loginFragment,"login").commit();
}
}
You need to have a parent layout to put a fragment, but in your case you can use the default layout of android as a parent container for the fragment.
solution:
fragmentTransaction=getFragmentManager().beginTransaction();
LoginFragment loginFragment=new LoginFragment();
fragmentTransaction.add(android.R.id.content,loginFragment,"login").commit();
it probably because you missed setContentView for the activity . Inside the layout you should declare a container where you can add/replace Fragments. Also in LoginFragment you are using getActivity to retrieve the Fragment's component. You should use the inflated view. The best way, imo, is to override onCreatedView
You can also use -
fragmentTransaction=getFragmentManager().beginTransaction();
LoginFragment loginFragment=new LoginFragment();
fragmentTransaction.add(0,loginFragment,"login").commit();
Fragment Transaction -
public abstract FragmentTransaction add (int containerViewId, Fragment
fragment, String tag)
Added in API level 11 Add a fragment to the activity state. This
fragment may optionally also have its view (if Fragment.onCreateView
returns non-null) into a container view of the activity.
Parameters
containerViewId - Optional identifier of the container this fragment is
to be placed in. If 0, it will not be placed in a container.
fragment - The fragment to be added. This fragment must not already
be added to the activity.
tag - Optional tag name for the fragment, to later retrieve the
fragment with FragmentManager.findFragmentByTag(String).
Returns - Returns the same FragmentTransaction instance.
Related
I created an application in which i had 1 ACTIVITY and 8 Fragment in which i am inflating every fragment into the activity. but my problem is that every fragment is overlapping each other. I change the background color of every fragment but when i am clicking the vacant spaces button of my previous fragment get clicked.
please suggest me some thing to get out of this situation.
Main_Activity.class
public class ActRegistration extends AppCompatActivity {
FragmentManager fm;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_registration);
fm = getSupportFragmentManager();
loadFragment(new FragmentRegLogSkip(), FragmentRegLogSkip.FRAGMENT_KEY);
}
public void loadFragment(Fragment fragmentName, String fragmentKey) {
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.add(R.id.id_registration_layout_frame, fragmentName);
fragmentTransaction.addToBackStack(fragmentKey);
fragmentTransaction.commit();
}
}
Frag_1.class
public class FragmentRegLogSkip extends Fragment implements View.OnClickListener {
private Activity activity;
private Context context;
public static final String FRAGMENT_KEY = "fragment_reg_log_skip";
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
context = getContext();
LanguageChanger.changeLanguage(context);
View view = inflater.inflate(R.layout.act_registration_screen_login, container, false);
return view;
}
}
Don't forget to add android:clickable="true" and android:focusable="true" to the parent view of your second fragment so it catches the clicks and they don't get propagated to the fragment below. Something like this:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true">
You're using fragmentTransaction.add(), which won't remove the previous Fragment - use fragmentTransaction.replace() if you want the other Fragment's view to be removed.
Note FragmentManager automatically restores any previously added Fragments when your Activity is recreated (i.e., when savedInstanceState != null). Therefore you'll want to ensure that you only add your initial Fragment once - when the savedInstanceState is null.
if (savedInstanceState == null) {
loadFragment(new FragmentRegLogSkip(), FragmentRegLogSkip.FRAGMENT_KEY);
}
Inside your second fragment layout file's Parent Tag , add this :-
android:clickable="true"
android:focusable="true"
then when you click on any view , it will not click previous fragment.
I'm new Android programming. Earlier I was working with activities, where i could implement onClick on an ImageButton and go to a different activity.
Now I need to do the same but using Fragments. I have a prototype with a menu that always appear on screen and can show different activities to the user. The different lactivities would be inside this container.
Now I want to place an ImageButton inside a fragment and make that the screen shows the next fragment. But I'm confused how to do it.
I have the following components:
Activity_main(java)+activity_main.xml (with menu)
Fragment1(java)+fragment1.xml(working normal)
Inside this layout I have an ImageButton and want to show Fragment2
Fragment2(java)+fragment2.xml
How should look Fragment1 to can call Fragment2?
I will be glad if the answer could be the clearest possible because I'm new on it, and maybe I could forgot an obvious step. Thanks
Simply make a method in your activity which will always change/replace fragment when you invoke it. something like
public void updateFragment(Fragment fragment){
//add fragment replacing code here
}
in your fragment, invoke it some thing like this
((YourActivity)getActivity()).updateFragment(new YourFragment());
since, it is just an idea which works fine but still you can improve the logic.
Actually, going from one fragment to another is almost similar to going from one activity to another. There are just a few extra lines of code.
First, add a new Java class named SingleFragmentActivity which would contain the following code-
public abstract class SingleFragmentActivity extends AppCompatActivity
{
protected abstract Fragment createFragment();
#LayoutRes
protected int getLayoutResId()
{
return R.layout.activity_fragment;
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(getLayoutResId());
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null)
{
fragment = createFragment();
fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
}
}
}
Make your activities in the following format-
public class SomeActivity extends SingleFragmentActivity
{
#Override
protected Fragment createFragment()
{
return SomeFragment.newInstance();
}
}
And your fragments like this-
public class SomeFragment extends Fragment
{
public static SomeFragment newInstance()
{
return new SomeFragment();
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.fragment_some, container, false);
return v;
}
}
After this everything has the same code as you have for activities except for one small detail which is your onCreateView(LayoutInflater, ViewGroup, Bundle) class. This is how you would write it-
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.fragment_some, container, false);
mTextView = (TextView)v.findViewById(R.id.some_text);
mButton = (Button)v.findViewById(R.id.some_button);
mTextView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
check();
}
});
return v;
}
And that is it!
Hi i hope you are already aware about the fragments and their uses but still here is a brief. They are child to an activity and an activity can have more than one fragment so you can update your layout without changing activity just by changing fragments.
You can found more on fragment here : https://developer.android.com/training/basics/fragments/index.html
Back to the original problem, supposed you are in MainActivity.java and you want to load fragment in it, so you do this to load fragment first time.
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame, new Fragment1);
transaction.addToBackStack(null);
transaction.commit();
You will need this method to change fragment from another fragment, so add this in your MainActivity
public void changeFragment(Fragment fragment){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame, new Fragment1);
transaction.addToBackStack(null);
transaction.commit();
}
Now from a button click in this fragment
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)getActivity()).changeFragment(new Fragment2);
}
});
Hope it will help!
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;
}
}
Let say the target application is built from 3 fragments which are all in the same activity public class MainActivity extends android.support.v4.app.FragmentActivity implements ActionBar.TabListener. Starting fragment is public class ButtonSectionFragment extends Fragment where there is a Button:
public class ButtonSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.btn, container, false);
Button mybutton = (Button) rootView.findViewById(R.id.mybutton);
mybutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
????????????????????
}
});
}
There are ?? in the onClick method, I will get to that. And there is another fragment like this:
public static class TextSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tv, container, false);
TextView textv = (TextView) rootView.findViewById(R.id.texty);
}
Both of the fragments are using different layouts so this is why rootView is being used right in front of findViewById.
The outcome I would like to achieve is: by Button from 1st fragment click set the TextView from 2nd fragment to Hello. What should I put in the ??? part to make it all work?
You need to use interface as callback to the activity then set the textview in fragment.
Two framgents should never communicate directly.
http://developer.android.com/training/basics/fragments/communicating.html.
Framgent1 -->Activity -->Fragment2.
You can comunicate value from fragment2 to activity first then from activity to fragment2. Then set text in fragment2
You just have to use getActivity().findViewById() instead of getView().findViewById()
final TextView tv = (TextView) getActivity().findViewById(R.id.texty);
if (tv != null)
tv.setText("Hello");
Fragments are just branches inside the common layout tree of activity. All fragment views of a common activity can be accessed through Activity.findViewByXXX(). The only complication is that fragments can be dynamically added, removed, replaced, etc. So you to be sure that the needed fragment is already inflated into the layout hierarchy. You can make initialization of the UI in onViewCreated() of the other fragment. That guarantees you the layout has been loaded already.
Fragment frag1 = new ButtonSectionFragment ();
Fragment frag2 = new TextSectionFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(layout, frag1);
ft.add(layout, frag2);
ft.commit();
View frag1RootView = frag1.getView();
View frag2RootView = frag2.getView();
Button btn = (Button)frag1RootView.findViewById(id);
TextView tv = (TextView)frag2RootView.findViewById(id);
untested but... I think that would do it...
EDIT: You should get the root views onActivityCreated(); or it'll throw you a null...
In continuation to Raghunandan's answer, you could check similar implementation in the link.
update TextView in fragment A when clicking button in fragment B
Do not forget to get a reference of the textview of the TextSectionFragment into the MainActivity.
First time posting here and also a new developer for Android Apps.
Desire Function of Example App:
1) Activity starts in fullscreen A
2) Fragment B then populates/inflates container of A fullscreen
3) Fragment B has a button, button is press
4) Fragment B is now replaced with Fragment C
5) Fragment C is now full screen and has data that is inputted by users, user then hits button to send to next Fragment
6) Fragment C is replaced with Fragment D and presents data to view which was inputted from Fragment C
Summary Functionality:
I am trying to keep everything on one screen going from
A (Activity) -> B (Fragment replace) -> C (Fragment replace to type data) -> D (Fragment replace and see last fragment data)
Problem/Issue
My code crashes when I try to populate the last screen with data obviously. It seems to throw an error in MainActivity at this specific line when I debug it
CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
I am definitely passing the values correctly through the interface I created, but during the debug process, I found out that my current program is trying to populate information into the same container since it seems like it didn't commit yet to replace the fragment to assign the variables to the right UI.
I was checking if I was able to replace the Fragment C with D, and I was able to only if I remove that above line of code.
Code Below
Main
public class MainActivity extends FragmentActivity implements OrderFragmentCode.FragUIListeners{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment AllMenu = new AllMenuFragmentCode();
FragmentManager fragManager = getSupportFragmentManager(); //getSupportFragmentManager setup
FragmentTransaction ft = fragManager.beginTransaction(); //setup fragmentTranscation = ft
ft.add(R.id.maincontainer, AllMenu);
ft.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onCartButtonClicked(String editFood, String editType, String editName){
CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
addCartInfoTextFragment.UpdateCartTexts(editFood, editType, editName);
}}
Fragment A
public class AllMenuFragmentCode extends Fragment implements OnClickListener {
private Button Order;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.all_menu_fragment, container, false);
Order = (Button) view.findViewById(R.id.orderButton);
Order.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
Fragment OrderFragmentCode = new OrderFragmentCode();
FragmentManager fragManager = getFragmentManager(); //getSupportFragmentManager setup
FragmentTransaction ft = fragManager.beginTransaction(); //setup fragmentTranscation = ft
ft.replace(R.id.maincontainer, OrderFragmentCode);
ft.addToBackStack(null);
ft.commit();
}}
Fragment C
public class OrderFragmentCode extends Fragment implements OnClickListener {
FragUIListeners activityCallback;
public interface FragUIListeners {
public void onCartButtonClicked(String foodText, String typeText, String nameText);
}
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
activityCallback = (FragUIListeners) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement FragUIListeners");
}
}
private EditText editTextFood;
private EditText editTextType;
private EditText editTextName;
private Button AddToCartButton;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.order_fragment, container, false);
editTextFood = (EditText) view.findViewById(R.id.editText);
editTextType = (EditText) view.findViewById(R.id.editText2);
editTextName = (EditText) view.findViewById(R.id.editText3);
AddToCartButton = (Button) view.findViewById(R.id.addToCart);
AddToCartButton.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
Fragment Cart = new CartFragmentCode();
FragmentManager fragManager = getFragmentManager();
FragmentTransaction ft = fragManager.beginTransaction();
ft.replace(R.id.maincontainer, Cart);
ft.addToBackStack(null);
ft.commit();
activityCallback.onCartButtonClicked(editTextFood.getText().toString(), editTextType.getText().toString(), editTextName.getText().toString());
}}
Fragment D
public class CartFragmentCode extends Fragment{
private TextView foodView;
private TextView typeView;
private TextView nameView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.cart_fragment, container, false);
foodView = (TextView) view.findViewById(R.id.foodView);
typeView = (TextView) view.findViewById(R.id.typeView);
nameView = (TextView) view.findViewById(R.id.nameView);
return view;
}
public void UpdateCartTexts(String editfood, String edittype, String editname)
{
foodView.setText(editfood);
typeView.setText(edittype);
nameView.setText(editname);
}}
--Final Say--
Sorry for the long post, this has been bugging me for HOURS and I even tried to use bundles and setting the arguements but I wasnt able to get that working either (I thought if i were able to obtain values correctly I could work around and use this to assign values to my textviews through getArguments on my last Fragment).
Please help!!!! Thanks!!!
In the line CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
findFragmentById sholule be passed that you use as 2nd argument in add while adding fragment to container for e.g. ft.add(R.id.maincontainer, AllMenu); if you want to get this fragment then you use findFragmentById(AllMenu) which is the tag that is associated with the fragment. R.id.maincontainer is the container in which that fragment is being displayed.
I guess the problem is you call onCartButtonClicked inside fragment C (where fragment C still exist) so the fragment D isn't created and take C place yet.
Try to call onCartButtonClicked by a Handler in your MainActivity
This is was one of my resource at the time to mimic a solution (he was using two fragments in one activity, while my app is trying to use one activity and replacing the main framelayout): http://www.techotopia.com/index.php/Using_Fragments_in_Android_-_A_Worked_Example
After playing around with example codes and using the available documentations. I cannot use these two lines to transfer the information as suggested in my MainActivity:
CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
addCartInfoTextFragment.UpdateCartTexts(editFood, editType, editName);
I think I finally found a workaround or a solution? I am not sure if this is the correct way of passing information to fragments or other classes, but here it is...
I basically Took away those two lines and rework my MainActivity's Click method and changed it to this...
public void onCartButtonClicked(String editFood, String editType, String editName){
CartFragmentCode.passFood = editFood;
CartFragmentCode.passType = editType;
CartFragmentCode.passName = editName;
}
I then went to my last fragment Code which was OrderFragmentCode.java and declared my Strings to retrieve them at the top of the Class and they were...
public static String passFood;
public static String passType;
public static String passName;
I then took the those values and setText them to my textViews. Wallah! It works as intented, however I am not sure if this is the right way to do things... If you guys are able to find a more professional way to handle data across multiple fragments, please let me know!