Android Studio: Moving between fragments and actions inside fragments - android

My project operates around a navigation activity that uses fragments for the individual menu pages. I'd like to be able to open other fragments through clicking a button (as opposed to a navigation menu icon), however I can't figure out how to accomplish this. I've looked at both the following resources (and more), but I don't fully understand them.
How can I make my button to do something in Fragments,ViewPager
https://developer.android.com/training/basics/fragments/communicating.html
Furthermore, clicking a button would also have to call on code in the main activity that uses the app bar.
If someone can explain to me how to accomplish the desired effect, that would be great.

If you want to open a fragment by pressing a button from a fragment the call should go through the current activity.
Create a callback to the activity and call that callback when pressing the button. Then the Activity launches the second fragment when the callback is called.
This way the first fragment does not need to know anything about the second fragment. The Activity deals with the navigation between fragments in the same activity.
I think this is the cleanest and easiest solution.
edit: I'm basically saying the same as the link to the android documentation posted in the question. I think this is the best solution.

For simplicity: Activity = [A], Fragment 1 = [B], and Fragment 2 = [C]
Step 1: Create an interface inside [B] called IOnInitiate[C]Listener, and within that interface create a method called void Initiate[C]();.
Step 2: Create a private property within [B] of type IOnInitiate[C]Listener called (your-prefix-convention)OnInitiate[C]Listener.
Step 3: Create a public method within [B] called public void SetInitiate[C]Listener(Activity activity), and cast the activity parameter into the private property created in step 2.
Step 4: [A] must implement the interface [B].IOnInitiate[C]Listener and the method public void Initiate[C]().
Step 5: From [A], whenever you create a new instance of [B], be sure to call the method from step 3 and pass in this for the Activity parameter. Otherwise a null exception will occur.
Step 6: Now whenever you need to initiate [C] from [B] simply call the interface method from [B]'s private property. Example:(prefix)OnInitiate[C]Listener.Initiate[C]();
This is what mine looks like. I use C# for my development, so your syntax may be different.
public class A : Activity, B.IOnInitiateCListener
{
private void InitiateB()
{
B b = new B();
b.SetInitiateCListener(this);
b.Show(FragmentManager, "B");
}
public void InitiateC()
{
C c = new C();
c.Show(FragmentManager, "C");
}
}
public class B : Fragment
{
public interface IOnInitiateCListener
{
void InitiateC();
}
private IOnInitiateCListener _IOnInitiateCListener;
public void SetInitiateCListener(Activity activity)
{
_IOnInitiateCListener = (IOnInitiateCListener)activity;
}
private void InitiateC()
{
_IOnInitiateCListener.InitiateC();
}
}

Related

How can i intent this code to another activity?

How can I pass this code to my another activity, I created two activities one is home activity and another is video_activity I call this code in video_activity in bottom nav but I also want to call it on my home activity I tried too much by I am not getting the correct one and please help me ... I want to pass this code from video activity to home activity ...
case R.id.navigation_dashboard:
favourite = toolbar;
favourite.setTitle(item.getTitle().toString());
videos.clear();
fetch_db("favorit");
favouritList();
return true;
You can wrap it in a function and call it from other activities
Example:
public class A {
public void foo(){ //your code ... }
}
In other activities:
A namefunction = new A();
namefunction.foo();
Or you can use the static method
Here are several instructions you may want to look: link 1 , link 2

Is it possible to have a fragment without an activity?

This is unlikely but it would potentially save me a lot of time to re-write the same code.
I want to implement a UI using alert-type service (like Chathead) yet I'd still like to use my fragments. Is it possible? I know I can add views to the window but fragments?
Fragments are part of the activity, so they cannot replace activity. Though they behave like activity, they cannot stand themselves. Its like view cannot itself act like activity.
From Android Developers:
A Fragment represents a behavior or a portion of user interface in an
Activity. You can combine multiple fragments in a single activity to
build a multi-pane UI and reuse a fragment in multiple activities. You
can think of a fragment as a modular section of an activity, which has
its own lifecycle, receives its own input events, and which you can
add or remove while the activity is running (sort of like a "sub
activity" that you can reuse in different activities).
I hope it is helpful to you.
Well as people have pointed out you can't, but, you can always create
some sort of fragment wrapper.
For example purposes:
public class ActivityFragmentWrapper extends FragmentActivity {
public static final String KEY_FRAGMENT_CLASS = "keyFragmentClass";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getIntent().getExtras() != null) {
String fragmentClass = (String) getIntent().getExtras().get(KEY_FRAGMENT_CLASS);
try {
Class<?> cls = Class.forName(fragmentClass);
Constructor<?> constructor = cls.getConstructor();
Fragment fragment = (Fragment) constructor.newInstance();
// do some managing or add fragment to activity
getFragmentManager().beginTransaction().add(fragment, "bla").commit();
} catch (Exception LetsHopeWeCanIgnoreThis) {
}
}
}
public static void startActivityWithFragment(Context context, String classPathName) {
Intent intent = new Intent(context, ActivityFragmentWrapper.class);
intent.putExtra(KEY_FRAGMENT_CLASS, classPathName);
context.startActivity(intent);
}
}
You can start it like:
ActivityFragmentWrapper.startActivityWithFragment(context, SomeSpecificFragment.class.getCanonicalName().toString());
Of course if your fragment has another constructor you have to retrieve different
one, but that part gets easier.
No, Fragments can't exist without an Activity. They need an activity for their entry point otherwise they can't initiate their UI components and their lifecycle can't go beyond onAttach and onCreateView

Get data back from a fragment dialog - best practices?

I'm converting some of my project to use fragments. How do we communicate with a fragment dialog? I want to create a fragment dialog just to get some text input from the user. When the dialog is dismissed, I'd like to pass the entered text back to the "parent" fragment (the one that started it). Example:
public class MyFragment extends Fragment {
public void onBtnClick() {
// What's a good way to get data back from this dialog
// once it's dismissed?
DialogFragment dlgFrag = MyFragmentDialog.newInstance();
dlgFrag.show(getFragmentManager(), "dialog");
}
}
Thanks
As eternalmatt said the given solution does not really answer the question. The way to communicate the dialog with the fragment is calling:
dialog.setTargetFragment(myCallingFragment, requestCode);
The way I do this is by creating the FragmentDialog with an static method where the listener is instanciated an then do the setFragmentTarget() stuff:
public mySuperFragmentDialog extends DialogFragment {
public interface SuperListener{
void onSomethingHappened();
}
public static mySuperFragmentDialog newInstance(SuperListener listener){
MySuperFagmentDialog f = new MySuperFragmentDialog();
f.setTargetFragment((Fragment) listener, /*requestCode*/ 1234);
return f;
}
}
To create the dialog from the fragment just do as usual:
Dialog dialog = MySuperFragmentDialog.newInstance(parentFragment);
dialog.show();
Then when you want to comunicate with the fragment which calls the dialog just:
Fragment parentFragment = getTargetFragment();
((SuperListener) parentFragment).onSomethingHappened();
This solution works only when dialog is gonna be created from Fragments and not from Activities, but you can combine both methods ('setFragmentTarget()' and the 'onAttach()' one) plus some Class checks to provide a full solution.
A great way to pass this kind of Events is a Callback Interface like descripted in the Android Developers Guide
Your Fragment define a Callback Interface like
public class MyFragment extends Fragment {
...
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void onArticleSelected(Uri articleUri);
}
...
}
Then you check inside your onAttach Method if the Parent implemented the Callback Interface and save the Instance.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
when your Event inside the Fragment happens you simply call the Callback Handler
mListener.onArticleSelected(...);
Hope that helps, further infos here
I had this problem once and after I solved it, I created a project that would remind me how I did it. I put the project on github so anyone can see the solution. Here is the link: https://github.com/mumasaba/FragmentFragmentBoss
In this project, we have a simple app with a TextView displaying the words 'Hello World'. This text view is on a fragment which is hosted by the main app activity. This fragment needs to display a new word that the user can enter after they click on the add options menu icon. When clicked, the options menu item calls up a dialog allowing the user to type in their new word. After the user is done, they can click ok to dismiss the dialog and display their new input on the fragment's text view. Therefore, Fragment to DialogFragment communication is illustrated.
There is a new pattern possible which is to share a ViewModel instance between fragments. When instantiating a ViewModelFactory where to get your ViewModels, you have to specify a context as parameter. If the context is the same for both fragments (i.e: the parent activity or parent fragment) and you instantiate the same ViewModel from both fragments, you will get the same instance.
This opens a new range of possibilities but also challenges.

How to go back from second screen to first screen

How to switch layouts? First, I have a class Main where is onCreate (setContentView(R.layout.main);) and then I call, another class with command:
setContentView(secondClass);
In this class, I draw with Canvas and this work just fine. I also create button to go back in first "class" (R.layout.main), but I don't know how to do it.
Now my program is basic a graph shower. In first class you type your function and them second class draw it. But how to go back in first class to type another function. This "back" button or arrow witch every Android phone have, send me out of program not back on insert part.
In secondClass I can't create onCreate method, but I also tried the following and they didn't work:
Intent abc = new Intent("bla.bla.bla.FIRSTCLASS");
startActivity(abc);
and
Intent abc = new Intent(SecondClass.this,FirstClass.class);
startActivity(greNaPrvoOkno);
If you want to use a custom view (as I understood, you are extending the View class), you can do it in the following way;
Consider you are showing the second class from your Main activity like this;
setContentView(new SecondClass(getApplicationContext(), MainActivity.this));
And you Second class is this (suppose);
// I am using onClickListener to go back to main view. You do whatever you like.
public class SecondClass extends View implements OnClickListener {
// This is needed to switch back to the parent activity
private Activity mParentActivity = null;
public SecondClass(Context context, Activity parentActivity) {
super(context);
mParentActivity = parentActivity;
setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Set the Main view back here.
mParentActivity.setContentView(R.layout.main);
}
}
Disclaimer: This code will do what you have asked for, but may cause other problems.
As advised by #Mudassir, you should use two different activities for two screens. It will give you better control, and your code will be easy to understand and maintain.
On the Onclick event of the button you have to write finish(); that's it..
Both of your classes are Activities yes? IF so then in your second activity you will simply call finish() and your activity will close revealing your first activity again.
When I have used multiple intents in my android application, I have created a new activity through:
Intent abc = new Intent(this, SecondClass.class);
startActivity(abc);
When the button is pressed in your second class, I would then either call finish(); on the class, or create a new intent like so:
Intent abc = new Intent(this, FirstClass.class);
startActivity(abc);
However, this method has the disadvantage that if a user wanted to use the back button, they may have to scroll through many layers of activities.
You should create another activity for your second class but not just set the main activity to a new view setContentView(secondClass).
For an easier modification, You could try to set the view back to setContentView(R.layout.main) first.
You still need to configure the widgets(e.g. TextView) on it when you set it back.
You don't have to startActivity again to go back.
Just call finish() in your second activity when you want to finish the current activity and go back:
e.g. When user press the back button in your second activity
mButtonBack.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
finish();
}
}

Finishing current activity from a fragment

I have a fragment in an activity that I am using as a navigation drawer. It contains buttons that when clicked start new activities (startActivity from a fragment simply calls startActivity on the current activity).
For the life of me I can't seem to figure out how I would finish the current activity after starting a new one.
I am looking to achieve something like this in the fragment:
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
if (view == mButtonShows) {
Intent intent = new Intent(view.getContext(), MyNewActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
}
But it seems Fragment.class does not implement finish() (like it implements startActivity(...)).
I would like the activity backstack cleared when they launch the 2nd activity. (so pressing back from the new activity would technically drop them back to the launcher)
When working with fragments, instead of using this or refering to the context, always use getActivity(). You should call
Java
getActivity().finish();
Kotlin
activity.finish()
to finish your activity from fragment.
Well actually...
I wouldn't have the Fragment try to finish the Activity. That places too much authority on the Fragment in my opinion. Instead, I would use the guide here: http://developer.android.com/training/basics/fragments/communicating.html
Have the Fragment define an interface which the Activity must implement. Make a call up to the Activity, then let the Activity decide what to do with the information. If the activity wishes to finish itself, then it can.
As mentioned by Jon F Hancock, this is how a fragment can 'close' the activity by suggesting the activity to close. This makes the fragment portable as is the reason for them. If you use it in a different activity, you might not want to close the activity.
Code below is a snippet from an activity and fragment which has a save and cancel button.
PlayerActivity
public class PlayerActivity extends Activity
implements PlayerInfo.PlayerAddListener {
public void onPlayerCancel() {
// Decide if its suitable to close the activity,
//e.g. is an edit being done in one of the other fragments?
finish();
}
}
PlayerInfoFragment, which contains an interface which the calling activity needs to implement.
public class PlayerInfoFragment extends Fragment {
private PlayerAddListener callback; // implemented in the Activity
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback= (PlayerAddListener) activity;
}
public interface PlayerAddListener {
public void onPlayerSave(Player p); // not shown in impl above
public void onPlayerCancel();
}
public void btnCancel(View v) {
callback.onPlayerCancel(); // the activity's implementation
}
}
You should use getActivity() method in order to finish the activity from the fragment.
getActivity().finish();
This does not need assertion, Latest update in fragment in android JetPack
requireActivity().finish();
In Fragment use getActivity.finishAffinity()
getActivity().finishAffinity();
It will remove all the fragment which pushed by the current activity from the Stack with the Activity too...
Every time I use finish to close the fragment, the entire activity closes. According to the docs, fragments should remain as long as the parent activity remains.
Instead, I found that I can change views back the the parent activity by using this statement:
setContentView(R.layout.activity_main);
This returns me back to the parent activity.
I hope that this helps someone else who may be looking for this.
Very simple...
1- just grab activity by getActivity() in the fragment
2- then call finish();
So just getActivity().finish(); will finish the parent activity.
Try this. There shouldn't be any warning...
Activity thisActivity = getActivity();
if (thisActivity != null) {
startActivity(new Intent(thisActivity, yourActivity.class)); // if needed
thisActivity.finish();
}
You have two options for Java and Kotlin. However, logic of both ways are same. You should call activity after call finish() method.
Answer for Kotlin,
If your activity cannot be null, use Answer_1. However, if your activity can be null, use Answer_2.
Answer_1: activity!!.finish()
Answer_2: activity?.finish()
Answer for Java,
getActivity().finish();
To finish activity in a Fragment use:
getActivity().finish();
Simple solution:
activity?.finish()
yes Fragment.class does not implement finish()
When working with fragments, instead of using this or refering to the context, always use getActivity(). You should call

Categories

Resources