I have some problem with Fragment and addToBackStack. I am create some project using Activity, Fragment, ActionBar, navigation spinner. Activity (MainActivity) is parent with two fragment (BestFragment and CurrFragment). BestFragment using action bar with navigation spinner to call two data (Buy and Sell) and display in Listview (default load is Buy data). When listview (BestFragment) setonitemclicklistener then calling detail selected item and display to CurrFragment. I am using addToBackStack from BestFragment to CurrFragment. When i am choose Sell data from navigation spinner (BestFragment) and selected item in Listview, it will be send detail on CurrFragment. If i am press back button in action bar (CurrFragment), that's can be back to BestFragment but that's load default Buy data (not Sell data on previous BestFragment). Help me.
Main Activity
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.action_settings:
return true;
case android.R.id.home:
getFragmentManager().popBackStack();
getActionBar().setTitle(mTitle);
//setTitle(navMenuTitles[1]);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
BestFragment
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int p,
long arg3) {
// TODO Auto-generated method stub
//ambil mata uang
String des = bestList.get(p).getMataUang();
//ambil kata terakhir textview
String a[] = textinfobest.getText().toString().split(" ");
String last_text = a[a.length-1];
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
CurrFragment llf = new CurrFragment();
Bundle bundle = new Bundle();
bundle.putString("tambah title", des +" "+last_text);
bundle.putString("pilih",des+last_text);
llf.setArguments(bundle);
ft.replace(R.id.frame_container, llf);
ft.addToBackStack(null);
ft.commit();
}
});
Related
I want to refresh the content of the fragment when a user clicks the refresher icon which is in menu action bar.
My application has three fragments on one activity with view pager; I tried to refresh all of them by calling them in onOptionsItemSelected() and I performed transactions to them, the application crashes when a user clicks refresh menu.
I read this question, it is likely similar to mine, but I couldn't find an appropriate answer to settle my problem: android: menu item click event from fragment I read this article too: but nothing helped me: https://developer.android.com/guide/topics/ui/menus maybe I am not doing it in a right way.
My code of refreshing all three fragments in the activity are here below:
#Override
public boolean onOptionsItemSelected(MenuItem item){
Fragment sentMsg=getSupportFragmentManager().findFragmentByTag("fragmentSentMsg");
Fragment receivedMsg=getSupportFragmentManager().findFragmentByTag("fragmentReceivedMsg");
Fragment allMsg=getSupportFragmentManager().findFragmentByTag("fragmentAllMsg");
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
switch (item.getItemId()){
case R.id.refresher_id:
fragmentTransaction.detach(sentMsg).attach(sentMsg).commit();
fragmentTransaction.detach(receivedMsg).attach(receivedMsg).commit();
fragmentTransaction.detach(allMsg).attach(allMsg).commit();
break;
}
return super.onOptionsItemSelected(item);
}
These are the code of a one fragment:
public class Page2_sent_msg extends Fragment {
//default constructor
public Page2_sent_msg(){}
#SuppressLint("ResourceType")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){
final View Page2_sent_msg=inflater.inflate(R.layout.page2_sent_msg,container,false);
ListView sentMsgListView=(ListView)Page2_sent_msg.findViewById(R.id.sentMsgListview);
ArrayList<String> sentMsgArrayList=new ArrayList<String>();
SQLite_database_helper_class myDb=new SQLite_database_helper_class(getContext());
Cursor result=myDb.getting_sms_from_db();
if (result.moveToFirst()){
do {
if (!result.getString(3).equals("Sent message")){
continue;
}else{
sentMsgArrayList.add("SMS No : "+result.getString(0)+"\n"
+"Address : "+result.getString(1)+"\n"
+"Date : "+result.getString(2)+"\n"
+"Type : "+result.getString(3)+"\n"
+"Content : "+"\n________\n\n"+result.getString(4)+"\n");
}
}while (result.moveToNext());
}
ArrayAdapter<String>sentMsgAdapter=new ArrayAdapter<>(getContext(),android.R.layout.simple_list_item_1,sentMsgArrayList);
sentMsgListView.setAdapter(sentMsgAdapter);
sentMsgListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//this is what will happen when a user clicks one item from the lis view
}
});
Page2_sent_msg.setTag("sentMsg");
return Page2_sent_msg;
}
I do really need a help. Kind regards!
Just write the fragment transaction in onclick of refresh button
fragment = new HomeFragment();
onFrangmentChange(fragment, true, false);
onFrangmentChange function will be like this
private void onFrangmentChange(BaseFragment fragment, boolean replace,
boolean addBackstack) {
this.fragment = fragment;
fm = getFragmentManager();
ft = fm.beginTransaction();
if (replace) {
ft.replace(R.id.fragment, fragment);
} else {
ft.add(R.id.fragment, fragment);
}
if (addBackstack) {
ft.addToBackStack(fragment.getClass().getSimpleName());
}
ft.commit();
}
Note:BaseFragment is nothing but A fragment which extend Fragment.You can write the common functions like checking network connection,email validation etc.in this fragment.
Add a method refresh in your fragment like this
public void refreshFragment() {
sentMsgArrayList.clear();
sentMsgAdapter.notifyDataSetChanged();
SQLite_database_helper_class myDb=new SQLite_database_helper_class(getContext());
Cursor result=myDb.getting_sms_from_db();
if (result.moveToFirst()){
do {
if (!result.getString(3).equals("Sent message")){
continue;
}else{
sentMsgArrayList.add("SMS No : "+result.getString(0)+"\n"
+"Address : "+result.getString(1)+"\n"
+"Date : "+result.getString(2)+"\n"
+"Type : "+result.getString(3)+"\n"
+"Content : "+"\n________\n\n"+result.getString(4)+"\n");
}
}while (result.moveToNext());
sentMsgAdapter.notifyDataSetChanged
}
Then called it once the user taps on refresh
#Override
public boolean onOptionsItemSelected(MenuItem item){
Fragment sentMsg=getSupportFragmentManager().findFragmentByTag("fragmentSentMsg");
Fragment receivedMsg=getSupportFragmentManager().findFragmentByTag("fragmentReceivedMsg");
Fragment allMsg=getSupportFragmentManager().findFragmentByTag("fragmentAllMsg");
switch (item.getItemId()){
case R.id.refresher_id:
sentMsg.refreshFragment();
receivedMsg.refreshFragment();
allMsg.refreshFragment();
break;
}
return super.onOptionsItemSelected(item);
}
I have implemented a navigation slider in my app. In this slider I have four fragments: Home, Profile, Search, calculator. Don't worry about the naming conventions in selectItem method as I am only focusing on searchProgram as of now and don't have all my four fragments implemented
NavigationDrawer.class (Activity):
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}
public void selectItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomePage();
break;
case 1:
fragment = new HomeFragment();
break;
case 2:
fragment = new SearchProgram();
default:
break;
}
if (fragment != null) {
Bundle bundle = new Bundle();
bundle.putInt(HomeFragment.EXTRA_ITEM_INDEX, position);
bundle.putString("username", userName);
bundle.putString("access_token", access_token);
fragment.setArguments(bundle);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(mNavItems[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
When I select search i am brought to a view which has an action bar with the navigation slider just like I wanted. When the user selects what they want to search for from the two spinners and clicks my own button called search I then start a master detail flow containing an expandable list.
Below is where i start my new activity from my searchProgram class(Fragment):
protected void onPostExecute(ArrayList<SportProgram> programList) {
Bundle extras = new Bundle();
String userName = getArguments().getString("username");
String access_Token = getArguments().getString("accessToken");
System.out.println("Search Program Test Username: " + userName);
System.out.println("Search Program Test Access_Token: " + access_Token);
extras.putString("username", userName);
extras.putString("accessToken", access_Token);
extras.putParcelableArrayList("programs", programList);
Intent intent = new Intent(getActivity(), TrainingProgramListActivity.class);
intent.putExtras(extras);
startActivity(intent);
}
}
This view has an action bar with a back/up button and no navigation slider. When I click this button I am brought back to the previous view, i.e. the search view, however the action bar stays the same and still has the up button. Has anyone any idea on how to change the action bar to include the navigation slider like it did previously? also when I select the back/up button in my listActivity view I am replacing the current fragment as follows:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_list_program, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
Fragment fragment = null;
switch (item.getItemId()) {
//This is the back/up button
case android.R.id.home:
fragment = new SearchProgram();
break;
case R.id.action_home:
Intent homeIntent = new Intent(this, NavigationDrawer.class);
Bundle extras = this.getIntent().getExtras();
homeIntent.putExtras(extras);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
System.out.println("HIT HOMEINTENT");
return true;
case R.id.action_search:
fragment = new SearchProgram();
System.out.println("HIT SEARCH");
break;
default:
break;
}
if (fragment != null) {
Bundle bundle = this.getIntent().getExtras();//new Bundle();
// bundle.putString("username", userName);
// bundle.putString("access_token", access_token);
fragment.setArguments(bundle);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.containerE, fragment).commit();
// fragment.getActivity().supportInvalidateOptionsMenu();
}
return super.onOptionsItemSelected(item);
}
I have tried numerous possible solutions but keep falling short. All the examples i have found navigate from the navigationDrawer activity to a fragment and then another fragment but for me I am navigating from NavigationDrawer to a fragment->class->fragment. Any ideas please?
You are stacking a detail activity on top of the main one which holds your drawer. To get back to the original activity, just close the last one using finish(), in your onOptionsItemSelected().
The issue occurs when I attempt to switch from the Second Fragment to the First Fragment. I am using ActionBar Option Menu Icons to navigate back and forth between the different fragments.
Each fragment has its own menu that is associated with the individual option menu items. I cannot seem to figure out why I am able to transition from one the First Fragment to the Second Fragment, but am unable to do the reverse.
Does anything in my code stand out that would disable me from being able to navigate back to the previous fragment?
I was able to switch between the fragments without any issues in the past, but after I incorporated these option menu items to do the navigation, it stopped working.
Starting Fragment
public class SearchFragmentActivity extends Fragment implements OnClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.activity_search_fragment,
container, false);
btnBasketball = (ImageButton) view.findViewById(R.id.btnBasketball);
btnBasketball.setOnClickListener(this);
setHasOptionsMenu(true);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Add your menu entries here
menu.clear();
inflater.inflate(R.menu.navigation_search_event, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_more:
// do something with a dropdown
break;
}
return true;
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.btnBasketball:
changeFragment("Basketball");
break;
}
}
public void changeFragment(String sportName) {
Bundle bundle = new Bundle();
bundle.putString("SPORTNAME", sportName);
Fragment fragment = new SearchDetailsFragmentActivity();
fragment.setArguments(bundle);
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.cell_left_in,
R.anim.cell_right_out);
transaction.replace(R.id.searchFragment, fragment);
transaction.commit();
}
}
Second Fragment
public class SearchDetailsFragmentActivity extends Fragment {
TextView tvSportsName;
GridView gView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.activity_search_details_fragment,
container, false);
String sportsName = getArguments().getString("SPORTNAME");
tvSportsName = (TextView) view.findViewById(R.id.tvSportsName);
tvSportsName.setText(sportsName);
// SportAdapter sAdapter = new SportAdapter(getActivity(), lstSports);
gView = (GridView) view.findViewById(R.id.gridViewSearch);
setHasOptionsMenu(true);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Add your menu entries here
menu.clear();
inflater.inflate(R.menu.navigation_search_details_event, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_cancel:
changeFragment();
break;
}
return true;
}
public void changeFragment() {
Fragment fragment = new SearchFragmentActivity();
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.cell_left_in,
R.anim.cell_right_out);
transaction.replace(R.id.searchDetailsFragment, fragment);
transaction.commit();
}
}
Options Menu associated with Second Fragment
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" >
<item
android:id="#+id/action_cancel"
android:icon="#drawable/ic_content_remove"
android:orderInCategory="100"
android:title="#string/action_settings"
app:showAsAction="always"/>
</menu>
UPDATES
These changes allow me to navigate backwards from the SearchDetailsFragmentActivity >> SearchFragmentActivity using the SoftKey Back Button.
Changes to the changeFragment() method inside SearchDetailsFragmentActivity
public void changeFragment() {
Fragment fragment = new SearchFragmentActivity();
FragmentManager fm = getFragmentManager();
//FragmentTransaction transaction = fm.beginTransaction();
//transaction.setCustomAnimations(R.anim.cell_left_in,
//R.anim.cell_right_out);
//transaction.replace(R.id.searchDetailsFragment, fragment);
//transaction.commit();
fm.popBackStack();
}
inside the SearchFragmentActivity
public void changeFragment(String sportName) {
Bundle bundle = new Bundle();
bundle.putString("SPORTNAME", sportName);
Fragment fragment = new SearchDetailsFragmentActivity();
fragment.setArguments(bundle);
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.cell_left_in,
R.anim.cell_right_out);
transaction.replace(R.id.searchFragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
UPDATE 2
I placed a Log.e inside the OnOptionItemSelected() to see if the button was even firing properly and it appears as if it is not. There is nothing that is getting logged.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_cancel:
Log.e("IS THIS WORKING", "THIS IS WORKING"); <<< NOT FIRING
changeFragment();
break;
}
return true;
}
When replacing a fragment, you need to indicate whether or not that transaction is reversable (i.e. whether or not it goes onto the backstack). For the first fragment transaction, you usually won't want to do this (wouldn't want to pop to an empty view). For fragment replacements, you want to specify addToBackStack() with an optional tag (which can be later used with popBackStack(String)).
For example, in between these lines:
transaction.replace(R.id.searchDetailsFragment, fragment);
transaction.commit();
add:
transaction.replace(R.id.searchDetailsFragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
I'm using this tutorial to implement facebook login etc.
Facebook Login
I have added new fragment in this to show list of friends. Now when I press back button on my newly added fragment it takes me to the SPLASH fragment, I want same behaviour on back button on action bar. Means when I'm on my new fragment it shows me a back button on action bar. And pressing that back button takes me back to the SPLASH screen.
private void showFragment(int fragmentIndex, boolean addToBackStack) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
for (int i = 0; i < fragments.length; i++) {
if (i == fragmentIndex) {
transaction.show(fragments[i]);
} else {
transaction.hide(fragments[i]);
}
}
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.commit();
}
You can do that by two ways :
1. Inside your fragment
#Override
public void onDetach()
{
super.onDetach();
PUT YOUR CODE HERE
}
This will called when fragment will be finished.
2. Just add addToBackStack while you are transitioning between your fragments like below:
fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();
if you write addToBackStack(null) , it will handle it by itself but if you give a tag , you should handle it manually.
EDITED:
for doing transactions
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
Fragment scheduleFragment = new ScheduleFragment();
fragmentTransaction.replace(R.id.content_container, scheduleFragment, "scheduleFragment");
fragmentTransaction.addToBackStack("scheduleFragment");
fragmentTransaction.commit();
#Yawar actionbar is on activity only and this will added on activity it will be called evertime when u press actionbar home button-->
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; goto parent activity.
this.finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
i got this code on stackoverflow after searching hard hope this may help you
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);// in on Create()
search for code onOptionsItemSelected(MenuItem item)
and edit it in this way
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// change your behaviour here
Intent intent = new Intent(this, yourclass.class);// i started new activity here
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
I'd like to replace a fragment, when a menu button is clicked. The toast is displayed, but it seems like I have a problem with the FragmentTransaction, since it tells me it
Description Resource Path Location Type
Cannot instantiate the type FragmentTransaction ActivityAppLaunch.java /juraQuiz/src/com/pthuermer/juraquiz line 71 Java Problem
this is what I tried:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.actionbar_menu_info) {
Toast.makeText(getApplicationContext(), "Info", Toast.LENGTH_LONG).show();
FragmentTransaction ft = new FragmentTransaction();
Fragment fragment = new FragmentInfo();
ft.replace(R.id.container, fragment);
}
if (id == R.id.actionbar_menu_settings) {
Toast.makeText(getApplicationContext(), "Settigns", Toast.LENGTH_LONG).show();
}
return super.onOptionsItemSelected(item);
}
try FragmentManager
FragmentManager fragmentManager = getFragmentManager();
Fragment fragment = new FragmentInfo();
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();