Though it seems an easy problem, I've been stuck for quite a few hours. If anyone can help my out providing some code it'd be great. So there it goes my question.
There's a MainActivity which has an ActionBar with two buttons. Each button starts a ListFragment when it's clicked. Then each item of each ListFragment starts another fragment (that's what I'm not able to achieve). Here is the code for the MainActivity:
public class MainActivity extends Activity implements
DataListFragment.DataListSelectionListener {
private final String TAG = "MainActivity";
// Reference the buttons in the ActionBar
private Button actionBarData;
private Button actionBarElu;
private Button actionBarOptions;
// Reference the ListFragments
DataListFragment dataListFragment;
EluListFragment eluListFragment;
// Reference the fragments related to the listItems
SectionTypeFragment sectionTypeFragment;
SectionDimensionsFragment sectionDimensionsFragment;
MaterialsFragment materialsFragment;
ReinforcementFragment reinforcementFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Inflate the custom layout for the ActionBar
final ViewGroup actionBarLayout = (ViewGroup) getLayoutInflater().inflate(
R.layout.action_bar,
null);
// Set the custom ActionBar
final ActionBar actionBar = getActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(actionBarLayout);
// ActionBar Customization with buttons
final int actionBarColor = getResources().getColor(R.color.blue_2);
actionBar.setBackgroundDrawable(new ColorDrawable(actionBarColor));
actionBarData = (Button) findViewById(R.id.action_bar_data);
actionBarData.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
Log.i(TAG, "DATA button clicked.");
clickActionBarButton(v);
}
});
actionBarElu = (Button) findViewById(R.id.action_bar_elu);
actionBarElu.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "ELU button clicked.");
clickActionBarButton(v);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_bar_data) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void clickActionBarButton(View v){
// Get a reference to the FragmentManager
FragmentManager fragmentManager = getFragmentManager();
// Begin a new FragmentTransaction
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Create the fragment depending on the button pressed
if(v == actionBarData){
// If there is no FeedFragment instance, then create one
if(sectionTypeFragment == null)
dataListFragment = new DataListFragment();
// Replace the main_frame_layout with the sectionTypeFragment
fragmentTransaction.replace(R.id.main_frame_layoout, dataListFragment);
}else if(v == actionBarElu){
// If there is no FeedFragment instance, then create one
if(sectionTypeFragment == null)
eluListFragment = new EluListFragment();
// Replace the main_frame_layout with the sectionTypeFragment
fragmentTransaction.replace(R.id.main_frame_layout, eluListFragment);
}
// Commit the FragmentTransaction
fragmentTransaction.commit();
}
// Called when the user selects an item in the DataListFragment
public void onDataListSelection(int index){
// Get a reference to the FragmentManager
FragmentManager fragmentManager = getFragmentManager();
// Begin a new FragmentTransaction
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Add the fragment related to the selected item in the List
switch (index){
case 0:
// If there is no SectionTypeFragment instance, then create one
if(sectionTypeFragment == null)
sectionTypeFragment = new SectionTypeFragment();
// Replace the main_frame_layout with the sectionTypeFragment
fragmentTransaction.replace(R.id.main_frame_layout, sectionTypeFragment);
// Add this FragmentTransaction to the backstack
fragmentTransaction.addToBackStack(null);
break;
case 1:
...
}
// Commit the FragmentTransaction
fragmentTransaction.commit();
}
}
Here is the code for one of the ListFragments (DataListFragment):
public class DataListFragment extends ListFragment {
private static final String TAG = "DataFragment";
// List items
private String[] listItems;
private DataListSelectionListener mListener = null;
// Callback interface that allows this Fragment to notify the MainActivity when
// user clicks on a DataList Item
public interface DataListSelectionListener {
public void onDataListSelection(int index);
}
// Called when the user selects an item from the DataList
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Indicates the selected item has been checked
getListView().setItemChecked(position, true);
// Inform the MainActivity that an item has been selected
mListener.onDataListSelection(position);
}
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// Get the the items to show in the List from the strings.xml
listItems = getResources().getStringArray(R.array.data_list_array);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, listItems);
setListAdapter(adapter);
}
}
Here is the exception:
03-12 14:39:38.681 29515-29515/com.tari.rcsec E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3459)
at android.view.ViewGroup.addView(ViewGroup.java:3330)
at android.view.ViewGroup.addView(ViewGroup.java:3275)
at android.view.ViewGroup.addView(ViewGroup.java:3251)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:840)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
at android.app.BackStackRecord.run(BackStackRecord.java:635)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5022)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1032)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:790)
at dalvik.system.NativeStart.main(Native Method)
Related
I 've added a button to the menu which is suppose to take me from the fragment to the main activity but I don't now how to implement it?
I put a switch statement inside onOptionsItemSelected.
Fragment wehre I will call main activity:
public class DetailFragment extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor> {
//Fragment detailFragment= new Fragment(this);
// callback methods implemented by MainActivity
public interface DetailFragmentListener {
void onContactDeleted(); // called when a contact is deleted
// pass Uri of contact to edit to the DetailFragmentListener
void onEditContact(Uri contactUri);
}
private static final int CONTACT_LOADER = 0; // identifies the Loader
private DetailFragmentListener listener; // MainActivity
private Uri contactUri; // Uri of selected contact
private TextView nameTextView; // displays contact's name
private TextView phoneTextView; // displays contact's phone
private TextView emailTextView; // displays contact's email
private TextView specialtyTextView; // displays contact's
private TextView cityTextView; // displays contact's city
private TextView chargeTextView; // displays contact's state
private TextView noteTextView; // displays contact's zip
private Button callButton; //Nuha
private Button emailButton;
private Button smsButton;
// set DetailFragmentListener when fragment attached
#Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (DetailFragmentListener) context;
}
// remove DetailFragmentListener when fragment detached
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
// called when DetailFragmentListener's view needs to be created
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
setHasOptionsMenu(true); // this fragment has menu items to display
// get Bundle of arguments then extract the contact's Uri
Bundle arguments = getArguments();
if (arguments != null)
contactUri = arguments.getParcelable(MainActivity.CONTACT_URI);
// inflate DetailFragment's layout
View view =
inflater.inflate(R.layout.fragment_detail, container, false);
// get the EditTexts
nameTextView = (TextView) view.findViewById(R.id.nameTextView);
phoneTextView = (TextView) view.findViewById(R.id.phoneTextView);
emailTextView = (TextView) view.findViewById(R.id.emailTextView);
specialtyTextView = (TextView) view.findViewById(R.id.specialtyTextView);
cityTextView = (TextView) view.findViewById(R.id.cityTextView);
chargeTextView = (TextView) view.findViewById(R.id.chargeTextView);
noteTextView = (TextView) view.findViewById(R.id.noteTextView);
callButton = (Button) view.findViewById(R.id.callbutton);//nuha
emailButton=(Button) view.findViewById(R.id.sendEmailbutton);
smsButton=(Button)view.findViewById(R.id.smsbutton);
// load the contact
getLoaderManager().initLoader(CONTACT_LOADER, null, this);
addListenerOnButton(view);//Nuha buttons
Animation animation = AnimationUtils.loadAnimation(getContext(),R.anim.pop_enter);//Animate details Nuha
nameTextView.startAnimation(animation);
phoneTextView.startAnimation(animation);
emailTextView.startAnimation(animation);
emailButton.startAnimation(animation);
specialtyTextView.startAnimation(animation);
cityTextView.startAnimation(animation);
chargeTextView.startAnimation(animation);
noteTextView.startAnimation(animation);
callButton.startAnimation(animation);
emailButton.startAnimation(animation);//till here
return view;
}
// display this fragment's menu items
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_details_menu, menu);
}
// handle menu item selections
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_edit:
listener.onEditContact(contactUri); // pass Uri to listener
return true;
case R.id.action_home:////home button
//What should I put here ??
return true;
case R.id.action_delete:
deleteContact();
return true;
}
return super.onOptionsItemSelected(item);
}
My mainactivity :
public class MainActivity extends AppCompatActivity
implements ContactsFragment.ContactsFragmentListener,
DetailFragment.DetailFragmentListener,
AddEditFragment.AddEditFragmentListener {
// key for storing a contact's Uri in a Bundle passed to a fragment
public static final String CONTACT_URI = "contact_uri";
private ContactsFragment contactsFragment; // displays contact list
// display ContactsFragment when MainActivity first loads
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// if layout contains fragmentContainer, the phone layout is in use;
// create and display a ContactsFragment
if (savedInstanceState == null &&
findViewById(R.id.fragmentContainer) != null) {
// create ContactsFragment
//Nuha animation
// add the fragment to the FrameLayout
///Nuha try animation
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);
contactsFragment = new ContactsFragment();
transaction.replace(R.id.fragmentContainer, contactsFragment);
transaction.addToBackStack(null);
transaction.commit();
}
else {
contactsFragment =
(ContactsFragment) getSupportFragmentManager().
findFragmentById(R.id.contactsFragment);
}
}
// display DetailFragment for selected contact
#Override
public void onContactSelected(Uri contactUri) {
if (findViewById(R.id.fragmentContainer) != null) // phone
displayContact(contactUri, R.id.fragmentContainer);
else { // tablet
// removes top of back stack
getSupportFragmentManager().popBackStack();
displayContact(contactUri, R.id.rightPaneContainer);
}
}
// display AddEditFragment to add a new contact
#Override
public void onAddContact() {
if (findViewById(R.id.fragmentContainer) != null) // phone
displayAddEditFragment(R.id.fragmentContainer, null);
else // tablet
displayAddEditFragment(R.id.rightPaneContainer, null);
}
// display a contact
private void displayContact(Uri contactUri, int viewID) {
DetailFragment detailFragment = new DetailFragment();
// specify contact's Uri as an argument to the DetailFragment
Bundle arguments = new Bundle();
arguments.putParcelable(CONTACT_URI, contactUri);
detailFragment.setArguments(arguments);
// use a FragmentTransaction to display the DetailFragment
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.replace(viewID, detailFragment);
transaction.addToBackStack(null);
transaction.commit(); // causes DetailFragment to display
}
// display fragment for adding a new or editing an existing contact
private void displayAddEditFragment(int viewID, Uri contactUri) {
AddEditFragment addEditFragment = new AddEditFragment();
// if editing existing contact, provide contactUri as an argument
if (contactUri != null) {
Bundle arguments = new Bundle();
arguments.putParcelable(CONTACT_URI, contactUri);
addEditFragment.setArguments(arguments);
}
// use a FragmentTransaction to display the AddEditFragment
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.replace(viewID, addEditFragment);
transaction.addToBackStack(null);
transaction.commit(); // causes AddEditFragment to display
}
// return to contact list when displayed contact deleted
#Override
public void onContactDeleted() {
// removes top of back stack
getSupportFragmentManager().popBackStack();
contactsFragment.updateContactList(); // refresh contacts
}
// display the AddEditFragment to edit an existing contact
#Override
public void onEditContact(Uri contactUri) {
if (findViewById(R.id.fragmentContainer) != null) // phone
displayAddEditFragment(R.id.fragmentContainer, contactUri);
else // tablet
displayAddEditFragment(R.id.rightPaneContainer, contactUri);
}
// update GUI after new contact or updated contact saved
#Override
public void onAddEditCompleted(Uri contactUri) {
// removes top of back stack
getSupportFragmentManager().popBackStack();
contactsFragment.updateContactList(); // refresh contacts
if (findViewById(R.id.fragmentContainer) == null) { // tablet
// removes top of back stack
getSupportFragmentManager().popBackStack();
// on tablet, display contact that was just added or edited
displayContact(contactUri, R.id.rightPaneContainer);
}
}
//
}
Can you please help ?
Edit: This fragment is associated with the main activity.. I want to return to the main activity with the original fragment.
If I get your question correctly, this is what you need to put in your switch statement,
Intent mainActivityIntent = new Intent(getActivity(),MainActivity.class);
startActivity(mainActivityIntent);
brief explanation of the constructor of Intent
getActivity() returns the activity associated with the fragment.
The activity is a context (since Activity extends Context).
MainActivity.class is the activity you want to return to.
Hope this helps! :)
-After you updated the question-
I think this is what you are looking for How to get a Fragment to remove itself?
Try this.(inside fragment)
Intent intent = new Intent (getApplicationContext(),MainActivity.class);
startActivity(intent);
you have to use this in your itenselected option
Intent intent = new Intent(context, ActivityName.class);
startActivity(intent);
where context is the fragment that you are using , and the next is the activity that you want to go .
How can I ensure that a button inside a list item is clickable, because I am trying to make the button clickable so that it can transition to a different fragment?
Like the listview and the list items inside it are part of a fragment and I want to ensure that clicking a specific button inside a list item will transition to the new fragment.
MainActivity Code:
It contains tabs(not all of which are implemented yet, but thats not an issue right now)
public class MainActivity extends FragmentActivity implements HomeFragment.OnFragmentInteractionListener {
private FragmentTabHost mTabHost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set up the tabs which hold different fragments, it will currently crash because of the null
mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
mTabHost.setup(this,getSupportFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("home").setIndicator("Home"), HomeFragment.class , null);
// mTabHost.addTab(mTabHost.newTabSpec("search").setIndicator("Search"),null/*fragment here*/,null);
// mTabHost.addTab(mTabHost.newTabSpec("post").setIndicator("Post"),null/*fragment here*/,null);
// mTabHost.addTab(mTabHost.newTabSpec("books").setIndicator("Books"),null/*fragment here*/,null);
// mTabHost.addTab(mTabHost.newTabSpec("me").setIndicator("Me"),null/*fragment here*/,null);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
//For home fragment...parameter might change
#Override
public void onFragmentInteraction(String id) {
Button viewPostings = (Button) findViewById(R.id.view_postings);
viewPostings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PostDetailFragment fragment = PostDetailFragment.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.realtabcontent, fragment).addToBackStack(null).commit();
}
});
}
}
Im trying to launch the new activity from the implementation of onFragmentInteractionListener. The app loads the list view and its contents, but the individual buttons in it aren't clickable.
First off you need to add this line to make the items in the custom list item clickable:
android:descendantFocusability="blocksDescendants"
Add this property to the enclosing layout.
Secondly, you need to set the onClickListener in the getView method of the custom adapter that you have made for your custom ListView. For example, that would be something like this:
ImageButton deleteBtn = (ImageButton) view.findViewById(R.id.delete_btn);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// code here
}
});
Use some sort of ListAdapter such as an ArrayAdapter to populate your ListView. That way, you can use the adapter to handle the button clicks.
In your list fragment, use the onItemClick:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onFragmentInteraction(foodList.get(position));
}
}
Then in your parent activity, you will have something like this.
#Override
public void onFragmentInteraction(Food food) {
//going from ListFragment to DetailFragment
//call detail fragment here
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment fragment = DetailFragment.newInstance(food);
ft.replace(R.id.container, fragment);
ft.addToBackStack( "tag" );
ft.commit();
}
I would like to know if anyone knows a way to achieve both forward and backward navigation with Fragments?
I would like to start with a single Fragment, when I press the next button a new Fragment must be created, when I push the back button, the previous Fragment must be shown. My code does this and it saves any changes I have made to any previous Fragments as they are saved in the back stack, however, I want the same to be true of forward navigation, is there any way in which I can achieve this?
So to be more exact, I want to for example create 10 Fragments all with a single text box in which I can enter some data, each time I enter data and press the next button it must navigate to the next Fragment, have an empty text box and save the previous Fragment plus data entered to the back stack (this it currently does). So when I get to Fragment 10, I want to be able to go back to Fragment 1 and then back to Fragment 10 but as I navigate forward again, the data I originally entered must still be there. Then when I navigate to Fragment 11 it must be an empty text box. So it must be a forward and backward navigation system of sorts.
The code below generates Fragments dynamically from code and adds Views to it dynamically as well (at run time). This is the code I currently have working for going backwards.
public class MainActivity extends Activity
{
int mStackLevel = 0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button IntegratedBiometricsButton = (Button) findViewById(R.id.integrated_biometrics_button);
IntegratedBiometricsButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent IBIntent = new Intent(MainActivity.this, SimpleScanActivity.class);
startActivity(IBIntent);
}
});
// Watch for button clicks.
Button button = (Button) findViewById(R.id.new_fragment);
button.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
addFragmentToStack();
}
});
button = (Button) findViewById(R.id.delete_fragment);
button.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
getFragmentManager().popBackStack();
if(mStackLevel > 0){mStackLevel--;}
}
});
if (savedInstanceState == null)
{
// Do first time initialization -- add initial fragment.
Fragment newFragment = CountingFragment.newInstance(mStackLevel);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();
} else
{
mStackLevel = savedInstanceState.getInt("level");
}
}
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putInt("level", mStackLevel);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings)
{
return true;
}
return super.onOptionsItemSelected(item);
}
void addFragmentToStack()
{
mStackLevel++;
// Instantiate a new fragment.
Fragment newFragment = CountingFragment.newInstance(mStackLevel);
// Add the fragment to the activity, pushing this transaction
// on to the back stack.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, newFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
public static class CountingFragment extends Fragment
{
int mNum;
/**
* Create a new instance of CountingFragment, providing "num"
* as an argument.
*/
static CountingFragment newInstance(int num)
{
CountingFragment f = new CountingFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
/**
* The Fragment's UI is just a simple text view showing its
* instance number.
*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
int ID = 0;
View v = inflater.inflate(R.layout.fragment_layout, container, false);
LinearLayout fragmentLayout = (LinearLayout) v.findViewById(R.id.infoLayout);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
TextView tv = new TextView(container.getContext());
tv.setId(ID);
ID++;
tv.setTextSize(16);
tv.setText("Fragment #" + mNum);
tv.setGravity(Gravity.CENTER);
tv.setLayoutParams(lp);
fragmentLayout.addView(tv);
EditText et = new EditText(container.getContext());
et.setId(ID);
ID++;
et.setHint("Text");
et.setGravity(Gravity.CENTER);
et.setInputType(InputType.TYPE_CLASS_NUMBER);
et.setLayoutParams(lp);
fragmentLayout.addView(et);
CheckBox cb = new CheckBox(container.getContext());
cb.setId(ID);
cb.setChecked(false);
cb.setGravity(Gravity.LEFT);
cb.setLayoutParams(lp);
fragmentLayout.addView(cb);
cb.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(((CheckBox) v).isChecked())
{
Toast.makeText(v.getContext(), "Yo", Toast.LENGTH_LONG).show();
}
}
});
ID++;
ImageView iv = new ImageView(container.getContext());
iv.setId(ID);
iv.setImageResource(R.drawable.output);
iv.setLayoutParams(lp);
fragmentLayout.addView(iv);
iv.setOnLongClickListener(new View.OnLongClickListener()
{
public boolean onLongClick(View v)
{
Toast.makeText(v.getContext(), "It works", Toast.LENGTH_LONG).show();
return true;
}
});
ID++;
//View tv = v.findViewById(R.id.text);
//((TextView) tv).setText("Fragment #" + mNum);
//tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
return v;
}
}
}
I have a problem with adding the fragment transactions to the back stack. I have a Main activity in which I populate my layout with a Menu Fragment:
public class MainActivity extends ActionBarActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getFragmentManager().beginTransaction().add(R.id.frag_container, new MainMenuFragment()).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;
}
#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.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Then, inside the MainMenuFragment, the user chooses some option which results in replacing the menu fragment with some other fragment:
public class MainMenuFragment extends Fragment implements OnItemClickListener{
GridView grid;
FragmentManager manager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.main_menu_fragment, container, false);
manager = getActivity().getFragmentManager();
grid = (GridView) root.findViewById(R.id.gridView1);
grid.setAdapter(new MenuTileAdapter(getActivity()));
grid.setOnItemClickListener(this);
return root;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentTransaction trans = manager.beginTransaction();
if (position == 0){
trans.replace(R.id.frag_container, new BasicSettingsFragment());
trans.addToBackStack(null);
trans.commit();
}
}
}
For what i understand, this should make it so that when the user presses back button on their device, they will be brought back to the menu fragment, but instead this quits the app. What am i doing wrong?
In your Activity overwrite:
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
And probably you need to use in every commited fragment transaction:
FragmentTransaction.addToBackStack(null);
Your code is a mixup, you use ActionBarActivity from appcompat and not using getSupportFragmentManager() and the fragments import should be the appcompat one if you decide to use it. If not, use Activity instead of ActionBarActivity and the simple Fragment import with FragmentManager
Add this to your activity android:configChanges="keyboardHidden|orientation|screenSize"
This will stop your activity from restarting when you rotate.
use setRetainInstance(true) on fragments.
You are not adding the MainMenuFragment to the back stack. You can try this one on your activity:
getFragmentManager().beginTransaction().add(
R.id.frag_container, new MainMenuFragment()).
addToBackStack(null).commit();
When you add or replace a fragment with the FragmentManager, you need to manually add the old fragment to the backstack with addToBackStack() before calling commit().
I'm having lot of problems when implementing ActionBar Sherlock, the last one is this one. I have an Slide Menu whith 3 options in my ActionBar. My problem is that when I choose one item (it load a fragment) that has been previously selected the app crash. The log error is
The specified child already has a parent. You must call removeView()
on the child's parent first.
It mark a line where I add view to a HorizontalScroller.
lls.addView(mviews.get(i));
In my OnCreateView I have
final View v = inflater.inflate(R.layout.activity_landing, container,false);
container.removeAllViews();
I haved tried many different ways posted here, but I don't get thw solution to my problem. Any ideas?
EDIT:
Here is some code of my MainActivity and Fragment.
This is the MainActivity. Ther's a ScreenSplash after and a class that extends from Application that control all WebService communications.
public class MainActivity extends SherlockFragmentActivity {
//Declare Variables
//...
Fragment fragment1 = new Fragment1();
Fragment fragment2 = new Fragment2();
Fragment fragment3 = new Fragment3();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getSupportActionBar().setIcon(R.drawable.ic_launcher);
getSupportActionBar().setTitle("");
setContentView(R.layout.drawer_main);
// Generate title
title = new String[] { "Item 1", "Item 2", "Item 3", "Item 4" };
// Generate icon
icon = new int[] { R.drawable.item1, R.drawable.item2,
R.drawable.item3, R.drawable.item4};
// Locate DrawerLayout in drawer_main.xml
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// Locate ListView in drawer_main.xml
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set a custom shadow that overlays the main content when the drawer
// opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
// Pass results to MenuListAdapter Class
mMenuAdapter = new MenuListAdapter(this, title, subtitle, icon);
// Set the MenuListAdapter to the ListView
mDrawerList.setAdapter(mMenuAdapter);
// Capture button clicks on side menu
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// Enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open,
R.string.drawer_close) {
public void onDrawerClosed(View view) {
// TODO Auto-generated method stub
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
// TODO Auto-generated method stub
super.onDrawerOpened(drawerView);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
selectItem(0);
}
}
//FOR ABS y ND
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.activity_main, menu);
//Define ActionBar buttons and actions
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//Sliding lateral Menu
if (item.getItemId() == android.R.id.home) {
if (mDrawerLayout.isDrawerOpen(mDrawerList)) {
mDrawerLayout.closeDrawer(mDrawerList);
} else {
mDrawerLayout.openDrawer(mDrawerList);
}
}
return super.onOptionsItemSelected(item);
}
// The click listener for ListView in the navigation drawer
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
selectItem(position);
}
}
private void selectItem(int position) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Locate Position
switch (position) {
case 0:
ft.replace(R.id.content_frame, fragment1);
break;
case 1:
ft.replace(R.id.content_frame, fragment2);
break;
case 2:
ft.replace(R.id.content_frame, fragment3);
break;
}
ft.commit();
mDrawerList.setItemChecked(position, true);
// Close drawer
mDrawerLayout.closeDrawer(mDrawerList);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
mDrawerToggle.onConfigurationChanged(newConfig);
}
}
This is the fragment with error. Now the other two are empty.
public class Fragment1 extends SherlockFragment implements
AdapterView.OnItemClickListener {
//DeclareVariables
public Fragment1() {
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//some declaration ad settings (witdhs, typefaces, caches,...)
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.main_activity, null,
false);
container.removeAllViews();
lls = (LinearLayout) v.findViewById(R.id.lscroll_item);
lls.removeAllViews();
//Instantiate some elements of the view such as TextViews and ImageViews
//layoutParams
// Show Scroll
DataStore.sharedInstance().getInfo(
new DataStore.infoReturn() {
#Override
public void call(final ArrayList<User> users, int error) {
if(users != null){
for (i = 0; i < users.size(); i++) {
mviews.add((RelativeLayout) getActivity().getLayoutInflater().inflate(R.layout.item_user, null));
mviews.get(i).setLayoutParams(layoutParams2);
imv = (ImageView) mviews.get(i).findViewById(R.id.user);
imv.getLayoutParams().height=friend_height;
imv_click = (ImageView) mviews.get(i).findViewById(R.id.click);
TextView text2 = (TextView) mviews.get(i).findViewById(R.id.fav);
text2.setTypeface(myTypeFace);
//set widths and layoutParams and sources
mviews.get(i).setId(i);
//NEXT LINE IS THE CRASH POINT, WHERE I TRY TO ADD ITEMS TO THE VIEW
lls.addView(mviews.get(i));
mviews.get(i).setOnClickListener(
new OnClickListener() {
#Override
public void onClick(View v) {
//Set actins when click
}
});
}
}else{
switch (error) {
case -1: //ERROR OBTENER USERS
break;
default:
break;
}
}
}
});
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// actions when click
}
#Override
public void onResume() {
super.onResume();
refreshInfo();
refreshSelectedUsers();
}
#Override
public void onPause() {
super.onPause();
DataStore.sharedInstance().setSelectedUsers(mSelected);
}
#Override
public void onDestroy() {
super.onDestroy();
//delete cache
}
//Some other methods for other UI items.
}
I have hidden some code to make it easier to read.
Use this
final View v = inflater.inflate(R.layout.activity_landing, null, false);
instead of
final View v = inflater.inflate(R.layout.activity_landing, container,false);