0

I have an app that has two tabs with fragments. One tab is called map and the other restaurantList. When I click on map marker or a card in the list it opens a restaurantDetailsActivity that has info about restaurant - lat, lang, name, rating, etc. There I have a floating action button that the user should click and it should close the current activity and go to maps tab fragment, to the location that I passed from the activity. I have tried a lot of stuff without any success: 1 2 3 4 5 6 7 8 9 ...

This is what I would want - when the user clicks the FAB, it should pass lat and lon from the restaurantDetailsActivity, to my map fragment and zoom in into that location (based on the lat and lon), regardless whether it was opened from the list fragment or the map fragment.

My restaurantDetailsActivity:

final String lat = restaurant.getLat();
final String lon = restaurant.getLon();

 FloatingActionButton fabGoToMap = findViewById(R.id.fabGoToMap);
    fabGoToMap.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
//                MapsFragment fragment = new MapsFragment();
//                Bundle bundle = new Bundle();
//                bundle.putString("lat", lat);
//                bundle.putString("lon", lon);
//                MapsFragment mapsFragment = new MapsFragment();
//                mapsFragment.setArguments(bundle);
//                Intent restaurantDescriptionIntent = new Intent(this, MapsFragment.class);
                  Bundle bundle = new Bundle();
                  bundle.putString("lat", lat);
                  bundle.putString("lon", lon);
                  MapsFragment fragInfo = new MapsFragment();
                  fragInfo.setArguments(bundle);
                  android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

//                transaction.add(R.id.map, mapsFragment, "tag").commit();
            finish();
        }
    });

UPDATED CODE: Calling the activity from list fragment:

public void fetchRestaurant(String restaurantId) {
    ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);

    Call<RestaurantResponse> call = apiService.getRestaurantById(restaurantId);
    call.enqueue(new Callback<RestaurantResponse>() {
        @Override
        public void onResponse(Call<RestaurantResponse> call, retrofit2.Response<RestaurantResponse> response) {
            final Restaurant restaurant= response.body().getResults();

            Intent intent = new Intent(getActivity().getApplicationContext(), AvailableRestaurantActivity.class);
            intent.putExtra("estaurant", estaurant);

            startActivity(intent);
        }

        @Override
        public void onFailure(Call<RestaurantResponse> call, Throwable t) {
            // Log error here since request failed
            Log.e(TAG, t.toString());
            Toast.makeText(getActivity().getApplicationContext(), R.string.failed_connectivity, Toast.LENGTH_LONG).show();
        }
    });
}

My main activity:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    tutorialUsed = false;
    tutorialPage = 1;


    db = new SQLiteHandler(getApplicationContext());
    // session manager
    session = new SessionManager(getApplicationContext());

    if (!session.isLoggedIn()) {
        Intent intent = new Intent(this, LoginActivity.class);
        startActivity(intent);
    } else {

        List<restaurant> restaurants = new ArrayList<>();

        TabLayout tabLayout = findViewById(R.id.sliding_tabs);
        tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.tab_one)));
        tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.tab_two)));
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);

        final ViewPager viewPager = findViewById(R.id.viewpager);
        PagerAdapter adapter = new PagerAdapter
                (getSupportFragmentManager(), tabLayout.getTabCount());
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        viewPager.setOffscreenPageLimit(3);
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }
        });
 ....
        myUserName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent accountIntent = new Intent(MainActivity.this, MyProfileActivity.class);
                startActivity(accountIntent);
            }
        });
    }
}
Banana
  • 2,435
  • 7
  • 34
  • 60
  • You can use [startActivityForResult](https://developer.android.com/training/basics/intents/result.html) and when the button is pressed, send a result to the other activity that tells it to show the `MapsFragment` fragment and sends any other data that is required. – Titus Dec 19 '17 at 15:22
  • what is current state, what happens on above FAB click ? – Akhil Dec 19 '17 at 15:23
  • @Akhil Right now when I click the FAB it only closes and goes to the fragment it was opened from, if it was opened from map it goes to map, if it was opened from list it goes back to list fragment – Banana Dec 19 '17 at 15:25
  • @Titus Not sure how would I send data like lat and lon and zoom in in this case. – Banana Dec 19 '17 at 15:26
  • You create an `Intent`, set the required data to the intent `theIntent.setData(...)` and call `setResult(theIntent)` – Titus Dec 19 '17 at 15:28
  • You can find more details in the answers to this question https://stackoverflow.com/questions/2497205/how-to-return-a-result-startactivityforresult-from-a-tabhost-activity – Titus Dec 19 '17 at 15:29
  • @Titus Trying it right now – Banana Dec 19 '17 at 15:36
  • You need to communicate to the root activity that a fragment needs to be swapped, removed or added. Your code is incomplete so I don't know if you are doing this – Pomagranite Dec 19 '17 at 15:40
  • @Pomagranite Sorry for not putting more of the code, it has a lot of unrelated code so I avoided putting it here. But to answer your question I do not communicate with the parent activity. – Banana Dec 19 '17 at 15:44

2 Answers2

2

Start restaurantDetailactivity from your MainActivity using startActivityForResult like this

startActivityForResult(intent, SHOW_DETAILS_REQUEST);

Click on FAB should be like this

final String lat = restaurant.getLat();
final String lon = restaurant.getLon();

 FloatingActionButton fabGoToMap = findViewById(R.id.fabGoToMap);
    fabGoToMap.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent();
            Bundle bundle = new Bundle();
            bundle.putString("lat", lat);
            bundle.putString("lon", lon);
            intent.putExtras(bundle);
            setResult(Activity.RESULT_OK,intent);
        }
    });

in your MainActivity handle activity result like below

@Override
protected void onActivityResult(final int requestCode,
                                final int resultCode,
                                final Intent data) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case SHOW_DETAILS_REQUEST: {
                //select mapfragment as current, assuming it is at index 0
                viewpager.setCurrentItem(0);
                //add your zoom logic here in zoomToCenter method
                mapfragment.zoomToCenter(data.getStringExtra("lat"),data.getStringExtra("lon"));
            }
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}
Akhil
  • 6,667
  • 4
  • 31
  • 61
  • I an starting my activity from two different fragments, maps and list fragment that are in the main activity. – Banana Dec 19 '17 at 15:47
  • you can use getActivity().startActivityForResult(intent, SHOW_DETAILS_REQUEST); from both fragments – Akhil Dec 19 '17 at 15:52
  • @Akil These are the errors I get: Error:(195, 22) error: cannot find symbol variable SHOW_DETAILS_REQUEST; Error:(197, 30) error: non-static method setCurrentItem(int) cannot be referenced from a static context and Error:(199, 33) error: cannot find symbol method zoomToCenter(String,String) – Banana Dec 19 '17 at 16:09
  • - You can define SHOW_DETAILS_REQUEST as any int constant - setCurrentItem(int) call this from non static method - zoomToCenter(String,String) you have to implement, i mentioned same in comments above – Akhil Dec 19 '17 at 16:13
  • One more question and I will stop bugging you :) what do you mean call this from non static method. I have posted updated code with viewpager above. – Banana Dec 19 '17 at 16:20
  • You might be calling ViewPager.setCurrentItem(int) instead of viewPager.setCurrentItem(int), just guessing. – Akhil Dec 19 '17 at 16:26
1

Kemo, You have an event that takes place in a fragment and as a result of the event you want the activity to swap one fragment for a second fragment. So your problem is how to communicate from fragment to activity. The fragment's on attach will give you the context for the activity. The activity should have a method to swap fragments in and out and using the context you got in the on attach you can use in the fragments oncreateview and run the activity's method.here Good luck professor

Pomagranite
  • 696
  • 5
  • 11