In my application I use ViewPager for show two fragments in an activity.
In one of the fragments I use NavigationDrawer. I want when click on onBackPress close this NavigationDrawer.
I wrote below code for open this Drawer :
reviewSerialFrag_DrawerLayout.openDrawer(Gravity.END);
I want that when I click on onBackPress it will close this drawer with below code:
reviewSerialFrag_DrawerLayout.closeDrawer(Gravity.END);
questioner, put in what the current problem is, please
onBackpress() only called in fragment if you need back press event in fragment you have to implement interface to get onBackPress() callback.
In Activity:
public MyActivity extends AppCompatActivity{
private BackPressListener backPressListener;
#Override
public void onBackPressed() {
if (backPressListener != null) {
backPressListener.onActivityBackPress();
} else {
super.onBackPressed();
}
}
public void setBackPressListener(BackPressListener backPressListener) {
this.backPressListener = backPressListener;
}
public interface BackPressListener{
void onActivityBackPress();
}
}
In Fragment:
public class MyFragment extends Fragment implements BackPressListener{
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyActivity)getActivity()).setBackPressListener(this);
}
#Override
public void onActivityBackPress() {
// handle your back press here.
reviewSerialFrag_DrawerLayout.closeDrawer(Gravity.END);
getActivity().onBackPressed();
}
#Override
public void onDestroy() {
super.onDestroy();
((MyActivity)getActivity()).setBackPressListener(null);
}
}
My solution:
Create BaseFragment.java:
public class BaseFragment extends Fragment
{
public boolean onBackPressed()
{
return false;
}
}
then extend your fragment by this BaseFragment, and in activity:
#Override
public void onBackPressed()
{
if (!yourFragment.onBackPressed())
super.onBackPressed();
}
In yourFragment:
public class YourFragment extends BaseFragmnet
{
...
.
.
#Override
public boolean onBackPressed()
{
// do something...
return true; // you should return true;
}
}
According to the AndroidX release notes, androidx.activity 1.0.0-alpha01 is released and introduces ComponentActivity, a new base class of the existing FragmentActivity and AppCompatActivity. And this release brings us a new feature:
You can now register an OnBackPressedCallback via addOnBackPressedCallback to receive onBackPressed() callbacks without needing to override the method in your activity.
The best solution is create your interface, and implement in Fragment.
Solution here : implement onBackpress in Fragment
public interface IOnBackPressed {
/**
* Si vous retouné true le back press ne sera pas pris en compte, sinon l'activité agira naturellement
* #return true si votre traitement est prioritaire sinon false
*/
boolean onBackPressed();
}
see link for more details ... easy sample
You can keep the flag that drawer was opened. And when you override the onBackPressed(), check this flag and if it's true, call
reviewSerialFrag_DrawerLayout.closeDrawer(Gravity.END);
otherwise, call super.onBackPressed() or any other logic you need.
Related
I think this question may simple but I didn't find any solution for this,
I there any way in Android that if any one of an activity calls onPause() I need to show Toast message or any notification kind of thing need to show. Generally I want to get notified when activity calls onPause() but I need it in one place since I may have some 15 activity I don't want to add it in all the activity.
ex:If I have activity when any one of the activity calls onPause I need to get notified but that notification code should be in one place and we should not add any line of code onPause() Is it possible to do this.
Thanks.
Create a baseActivity, which has for example :
open class BaseActivity : AppCompatActivity() {
override fun onPause() {
super.onPause()
Toast.makeText(this, "notified", Toast.LENGTH_SHORT).show()
}
}
Then you can extends this in your activities and handle the on pause call in BaseActivity
If your minSdkVersion >= 14, you can use Application.ActivityLifecycleCallbacks: ActivityLifecycleCallbacks
You have to define a custom Application class and you can register for this callbacks afterwards:
public class MyApplication extends Application {
private class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
#Override
public void onActivityCreated(final Activity activity, final Bundle savedInstanceState) {
//nothing to do
}
#Override
public void onActivityDestroyed(final Activity activity) {
//nothing to do
}
#Override
public void onActivityPaused(final Activity activity) {
// TODO Do your stuff, e.g. show toast.
}
#Override
public void onActivityResumed(final Activity activity) {
//nothing to do
}
#Override
public void onActivitySaveInstanceState(final Activity activity, final Bundle outState) {
//nothing to do
}
#Override
public void onActivityStarted(final Activity activity) {
}
#Override
public void onActivityStopped(final Activity activity) {
}
}
private final LifecycleCallbacks callbacks;
public void onCreate() {
super.onCreate();
callbacks = new LifecycleCallbacks();
application.registerActivityLifecycleCallbacks(callbacks);
}
}
Create a BaseActivity which contain all the methods you want to use in all other activities.
Then extend every activity with BaseActivity to call onPause() method.
In my application I use ViewPager for show two fragments into activity.
In one of this fragments I use NavigationDrawer, I want when click on onBackPress close this NavigationDrawer.
I write below code for open this Drawer :
reviewSerialFrag_DrawerLayout.openDrawer(Gravity.END);
I want when click on onBackPress close this drawer with below code :
reviewSerialFrag_DrawerLayout.closeDrawer(Gravity.END);
How can I it? Please help me
/Try to use below code snipet/
#Override
public void onBackPressed()
{
int count = getFragmentManager().getBackStackEntryCount();
// count --> Is your current fragment
if (count == 0)
{
if(reviewSerialFrag_DrawerLayout.isDrawerVisible(GravityCompat.END))
{
reviewSerialFrag_DrawerLayout.closeDrawer(GravityCompat.END);
}
}
}
In your Activity onBackPressed() write below code
#Overrdie
public void onBackPressed(){
Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
if(currentFragment instanceof YourDrawerFragment && reviewSerialFrag_DrawerLayout.isDrawerVisible(GravityCompat.END))
{
reviewSerialFrag_DrawerLayout.closeDrawer(GravityCompat.END);
return;
}
super.onBackPresses():
}
You can do this to close your drawer on back press
#Overrdie
public void onBackPressed(){
super.onBackPresses():
if(reviewSerialFrag_DrawerLayout.isDrawerVisible(GravityCompat.END)){
reviewSerialFrag_DrawerLayout.closeDrawer(GravityCompat.END);
}
}
In general, I find it easiest to use the Observer pattern and delegate the back pressed event down to the fragment. This will allow you to keep the activity and fragment concerns separated.
interface OnBackPressedListener {
public void onBackPressed();
}
Then, in your fragment, implement this OnBackPressedListener
class MyFragment extends Fragment implements OnBackPressedListener{
public void onBackPressed(){...}
}
And finally, in your activity, you can do the following:
class MyActivity extends Activity {
#Override
public void onBackPressed(){
// Grab all the fragments that are 'observing' the back press event
Fragment currentFragment =
getFragmentManager().findFragmentById(R.id.fragment_container);
if(currentFragment != null && currentFragment instanceof OnBackPressedListener) {
// delegate this back press event down to the fragment
OnBackPressedListener backFragment = (OnBackPressedListener) currentFragment;
backFragment.onBackPressed();
}
super.onBackPressed():
}
In Jon's solution, the super.onBackPressed will always be called. This may not necessarily be the case.
To do this, it is enough that the implementation returns a boolean and act according to the result.
My solution almost identical here
public interface IOnBackPressed {
/**
* Si vous retouné true le back press ne sera pas pris en compte, sinon l'activité agira naturellement
* #return true si votre traitement est prioritaire sinon false
*/
boolean onBackPressed();
}
see link for more details
In my main Activity, I have a DialogFragment that contains a FragmentTabHost. I have two tabs, one that is a DialogFragment and one that is a ListFragment. When either the 'OK' button is pressed in the inner DialogFragment or when an element in the ListFragment is pressed, I want to pass two Strings (that are entered in two TextView's in the inner DialogFragment and are displayed in each element in the ListFragment) back to the Activity, but I am unsure of how to do this with multiple levels of Fragments.
Any help is appreciated!
There's no magic.
You can achieve with two approaches.
Use callback.
Create interface and class to pass the data through child Fragment to Activity. You don't need to modify bridged TabHostFragment as Fragment always rely on its mother Context (Activity) no matter how many fragments wrap the fragment.
public class TwoStrings {
public TwoStrings(String one, String two){
this.one = one;
this.two = two;
}
public String one;
public String two;
}
First, declare interface.
public interface DataPassListener {
void dataPassed(TwoStrings data);
}
And, implement interface in Activity.
public class MainActivity extends Activity implements DataPassListener {
#Override
public void dataPassed(TwoStrings data) {
// do something with data.
Log.d("string one", data.one);
Log.d("string two", data.two);
}
}
Finally, let child Fragment acknowlege that mother Activity has the callback listener.
public class DialogFragment1 extends DialogFragment {
DataPassListener listener;
#Override
public void onAttach(Activity activity) {
if (activity instanceOf DataPassListener)
listener = (DataPassListener) activity;
}
public void setDataPassListener(DataPassListener listener){
listener = ((DataPassListener) listener);
}
public void doSomeThing(){
if(listener != null) // important to prevent NullPointerException
listener.dataPassed("a", "b");
}
}
Use EventBus.
I prefer to use Otto in order to publish and subscribe data.
To subscribe event for listening in Activity,
public class MainActivity extends Activity {
#Override
public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
#Override
public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void onUpdateTwoStrings(TwoStrings event) {
// do something with data.
Log.d("string one", data.one);
Log.d("string two", data.two);
}
}
And, publish event in anywhere in Fragment.
bus.post(new TwoStrings("a", "b"));
Take a look at setTargetFragment() and getTargetFragment() methods. You could connect fragments with each other through it without any additional callbacks and libs.
Please please don't minus my question i confused when googling.
I used Android Tab Layout with Swipeable Views in my code for when user pressed setting button on an activity.
now I need send message from TopRatedFragment.java that extends from fragment to the activity that call the mainActivity of "Android Tab Layout with Swipeable Views".
You can do this by implementing a call back
create an interface first
public interface CommunicationInterface {
public void onSuccess();
public void onFailed();
}
then in your activity implement the interface
public class YourActivity extends ActionBarActivity implements CommunicationInterface {
//default functions
#Override
public void onSuccess() {
//stuff you want to do in the acivity
}
#Override
public void onFailed() {
//stuff you want to do in the acivity
}
}
Now in the fragment
public class yourfragment extends Fragment {
CommunicationInterface callback;
//stuffs that usually come in yor fragment and like OncreateView etc
#Override
public void onActivityCreated(#Nullable Bundle outState) {
super.onActivityCreated(outState);
//after all the stuff you want to do in your fragment then implement //call back function to communicate with the activity
callback= (CommunicationInterface) getActivity();
callback.onSuccess();//according to your purpose use where ever you like
callback.onFailed();//according to your purpose use where ever you like
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback= (CommunicationInterface) activity;
}
}
Take a close look on this reference:
Creating event callbacks to the activity
The android docs recommend using this pattern of having the parent activity implement an interface of the fragment (Basically calling methods on it)
class MyFragment extends Fragment {
interface Listener {
public void onSomeEvent();
}
private void somethingHappeninInTheFragment() {
// let the activity know
((Listener) getActivity()).onSomeEVent();
}
}
class MyActivity extends Activity implements MyFragment.Listener {
// etc
#Override
public void onSomeEvent() {
// handle the message from the fragment
}
}
Explained with a more concrete example here: http://developer.android.com/guide/components/fragments.html#EventCallbacks
Here's the solution:
Step 1 : From your fragment.
Intent i = new Intent(getActivity(), YourActivity.class);
i.putExtra("key", "Your value1");
i.putExtra("key2", "Your value2");
i.putExtra("key3", "Your value3");
getActivity().startActivity(i);
Step 2 : In your Activity where you want the result
Intent getResults = getIntent();
String firstValue = getResults.getStringExtra("key1");
String secondValue = getResults.getStringExtra("key2");
String thirdValue = getResults.getStringExtra("key3");
Use those values your needs are.
Hope this helps.. :)
For Fragment-Activity communication, this is the suggested way of doing it, by using a listener.
In my case I have two fragments and a button at each and I would like them to do the exact same thing when pressed.
Should I create a separate listener class that the Activity implements and then instantiate a listener in each fragment or there is a better design that I am not aware of?
EDIT
I am sorry, I probably didn't communicate that properly. I am not looking for communication between fragments. I have a Fragment A with a buttonA and a Fragment B with a buttonB. When I click on buttonA, there is a listener in my Activity and method doSomething() is called. Now I want buttonB calling doSomething() too. Should I A) create a second listener and have the activity implement that too, B) create one separate listener class and use this one for both or C) a better choice ??
For communication between fragment to frament or activity to fragment communication via events. There are few alternatives are there e.g. this otto eventbus I know. and the tutorial about this can be found Here or just google it.
As from the documentation :
Two Fragments should never communicate directly.
So you best follow the pattern explained in the article and communicate thru the activity on which the fragments are attached.
When a listener is called from fragment A then get the fragment B from the fragmentManger
YourFragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_b);
fragment.doSomething();
I'm using this pattern and it works well for me:
public class Fragment1 extends Fragment {
FragmentListener mCallback;
public interface FragmentListener {
public void onAction1();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof FragmentListener) {
mCallback = (FragmentListener) activity;
}
}
public void onAction2() {
// do your stuff...
}
}
public class Fragment2 extends Fragment {
FragmentListener mCallback;
public interface FragmentListener {
public void onAction2();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof FragmentListener) {
mCallback = (FragmentListener) activity;
}
}
public void onAction1() {
// do your stuff...
}
}
public class MainActivity implements Fragment1.FragmentListener, Fragment2.FragmentListener {
private Fragment1 fragment1;
private Fragment2 fragment2;
/**
* Listening to events from first fragment and forwarding to second fragment
*/
#Override
public void onAction1() {
fragment2.onAction1();
}
/**
* Listening to events from second fragment and forwarding to first fragment
*/
#Override
public void onAction2() {
fragment1.onAction2();
}
}
The Activity listens to "events" from the fragments and if needed forward it to the other fragment(s).