What I am trying to do: Starting from a Master/Detail flow project, I am trying to enable the user to press an item in the ActionMenu which should show a fragment where new data can be put in.
Problem: I get an error when I try to start the fragment. What am I doing wrong?
After pasting the code I think I have made a mess of it. Still need help.
Error:
java.lang.IllegalArgumentException: No view found for id 0x7f090040 (com.example.androidtest:id/AddItem_fragment) for fragment AddItem{5b161e7 #1 id=0x7f090040}
ItemListActivity.java:
public class ItemListActivity extends ActionBarActivity implements
ItemListFragment.Callbacks {
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
if (findViewById(R.id.item_detail_container) != null) {
mTwoPane = true;
((ItemListFragment) getSupportFragmentManager().findFragmentById(
R.id.item_list)).setActivateOnItemClick(true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_actions, menu);
setTitle("Shoppinglistan");
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add:
openAddItem();
return true;
case R.id.action_send:
//openSettings();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onItemSelected(String id) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(ItemDetailFragment.ARG_ITEM_ID, id);
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment).commit();
} else {
Intent detailIntent = new Intent(this, ItemDetailActivity.class);
detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
public void openAddItem() {
AddItem additem = new AddItem();
getSupportFragmentManager().beginTransaction()
.add(R.id.AddItem_fragment, additem).commit();
}
public static class AddItem extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.additem_layout,
container, false);
return rootView;
}
}
}
activity_item_detail.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/item_detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.androidtest.ItemDetailActivity"
tools:ignore="MergeRootFrame" >
<fragment
android:name="com.example.androidtest.AddItem"
android:id="#+id/AddItem_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
/>
</FrameLayout>
additem_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
your problem is this line
public void openAddItem() {
AddItem additem = new AddItem();
getSupportFragmentManager().beginTransaction()
.add(R.id.AddItem_fragment, additem).commit();
}
you already have it here
<fragment
android:name="com.example.androidtest.AddItem"
android:id="#+id/AddItem_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
/>
you can not recreate it programmatically, all you need to do is remove the programmatically added fragment,and this will be there, since (in a different language its stack)..
EDIT
to address your comment,first of all add a tag to your fragments when calling ItemDetailFragment for instance "ItemDetailFragment" & instead of the previous code in openAddItem() replace them with this
public void openAddItem() {
getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().
findFragmentByTag("ItemDetailFragment"));
getSupportFragmentManager().popBackStackImmediate(); //
// if your fragment is still not showing then uncomment the below line
//getSupportFragmentManager().beginTransaction().show(getSupportFragmentManager().
findFragmentById(the_id_of_ur_fragment));
}
hope its good enough
From the documentation, the add method:
abstract FragmentTransaction add(int containerViewId, Fragment fragment)
Calls add(int, Fragment, String) with a null tag.
In your code:
public void openAddItem() {
AddItem additem = new AddItem();
getSupportFragmentManager().beginTransaction().add(R.id.AddItem_fragment, additem).commit();
}
This code will find in your views a view with the id R.id.AddItem_frament and it will try to attach to it the view associated to the fragment passed. Since in your layout there is not a ViewGroup that serves as a container it is launching you a legitimate IllegalArgumentException since the id is not present. What you have to do is provide a container in which you can add all the fragments and passing to the add method of the transaction this id.
Related
I am new to Android development and have added an additional item to a Navigation menu which successfully opens an external browser window but clears the app screen (except for the navigation menu) when startActivity in onActivityCreated is performed.
I am not making any more progress despite working on this for several days so I am asking for help now. Perhaps this is a simple question for someone with more experience. I have spent a week looking at all the other answers in SO, YouTube and Google Developer Courses trying to solve this so I am asking for help now.
WebsiteFragment.java
public class WebsiteFragment extends Fragment {
View myFragment;
RecyclerView websiteList;
LinearLayoutManager layoutManager;
private static final String COMMON_TAG="CombinedLifeCycle";
private static final String ACTIVITY_NAME =WebsiteFragment.class.getSimpleName();
private static final String TAG=ACTIVITY_NAME;
public static WebsiteFragment newInstance() {
WebsiteFragment websiteFragment = new WebsiteFragment();
return websiteFragment;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
//Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_website, container, false);
Log.i(TAG,ACTIVITY_NAME+" onCreateView");
websiteList = (RecyclerView)view.findViewById(R.id.websiteList);
layoutManager = new LinearLayoutManager(getActivity());
websiteList.setHasFixedSize(true);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://english-alps.com"));
// App Window is cleared??
getActivity().startActivity(i);
Log.i(TAG,ACTIVITY_NAME+" onActivityCreated");
}
}
fragment_webiste.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WebsiteFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/websiteList"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</FrameLayout>
Edit 21-08-2018
Added the following code to try and save Fragment state but it generates the error:
java.lang.NullPointerException: Attempt to read from field 'int androidx.fragment.app.Fragment.mIndex' on a null object referen.
I am having trouble with the parameters to getFragmentManager. How should the variables to getFragmentManager be initialized?
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState!=null){
Log.i(TAG,ACTIVITY_NAME+" calling onSaveInstanceState");
onSaveInstanceState(savedInstanceState);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getFragmentManager().putFragment(outState,TAG,myFragment);
Log.i(TAG,ACTIVITY_NAME+" onSaveInstanceState");
}
Edit#2 21-08-2018
Home.Java which adds WebsiteFragment to the Activity
public class Home extends AppCompatActivity {
BottomNavigationView bottomNavigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Fragment selectedFragment = null;
switch (menuItem.getItemId()) {
case R.id.action_category:
selectedFragment = CategoryFragment.newInstance();
break;
case R.id.action_ranking:
selectedFragment = RankingFragment.newInstance();
break;
case R.id.action_website:
selectedFragment = WebsiteFragment.newInstance();
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, selectedFragment);
transaction.addToBackStack(String.valueOf(R.id.frame_layout)); /* 21.08.2018 */
transaction.commit();
return true;
}
});
setDefaultKeyMode();
}
}
Edit #3 21-08-2018 activity_home.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Home">
<FrameLayout
android:id="#+id/frame_layout"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/navigation"></FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorPrimary"
app:itemIconTint="#drawable/nav_item_color_state"
app:itemTextColor="#drawable/nav_item_color_state"
app:menu="#menu/bottom_menu"
/>
</RelativeLayout>
I am new at android app development.I have a problem with my app.I am doing a simple 'Todo List App'. When I deploy my app to android phone.First time it works well.When I change orientation of device, onCreateView() and onActivityCreated() in MyAddFragment works multiple.And 'Add Button' doesn't work after changing orientation.****Please help me how to get rid of the problem.
The following my activity and fragment classes and xml files.
public class MainActivity extends Activity implements Communicator{
FragmentManager man;
private ArrayAdapter<String> todoArrayAdapter;
private ArrayList<String> todoItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
man = getFragmentManager();
MyAddFragment f1 = new MyAddFragment();
MyListFragment f2 = new MyListFragment();
FragmentTransaction transaction = man.beginTransaction();
transaction.add(R.id.frameLayout1, f1, "Add");
transaction.add(R.id.frameLayout2, f2,"List");
Log.i("a", "onCreate - ADDED FRAGMENT");
if (savedInstanceState == null) {
todoItems = new ArrayList<String>();
}else {
todoItems = savedInstanceState.getStringArrayList("veri");
}
todoArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,todoItems);
f2.setListAdapter(todoArrayAdapter);
transaction.commit();
}
public void respond(String data) {
MyListFragment fb = (MyListFragment) man.findFragmentById(R.id.frameLayout2);
todoItems.add(data);
todoArrayAdapter.notifyDataSetChanged();
}
#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);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putStringArrayList("veri", todoItems);
}
}
public class MyAddFragment extends Fragment{
Button btnAdd;
EditText txtEdit;
Communicator comm;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_add, container,false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
btnAdd = (Button) getActivity().findViewById(R.id.btnAdd);
txtEdit = (EditText) getActivity().findViewById(R.id.txtEdit);
comm = (Communicator) getActivity();
btnAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String newRecord = txtEdit.getText().toString();
comm.respond(newRecord);
txtEdit.setText("");
}
});
}
}
public class MyListFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, container,false);
return view;
}
}
public interface Communicator {
public void respond(String data);
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.ceng389hw1.MainActivity" >
<FrameLayout
android:id="#+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:background="#ab3e0f" >
</FrameLayout>
<FrameLayout
android:id="#+id/frameLayout2"
android:layout_width="fill_parent"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_below="#+id/frameLayout1"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:background="#ab3eab"
>
</FrameLayout>
</RelativeLayout>
fragment_add.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ab3e0f">
<Button
android:id="#+id/btnAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="#string/btnStringAdd" />
<EditText
android:id="#+id/txtEdit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/btnAdd"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/btnAdd"
android:ems="10"
android:inputType="text" />
</RelativeLayout>
fragment_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ab5810" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
You should change two files in your Application.
First step, you should add following code in androidmanifest file.
android:configChanges="orientation|screenSize"
After you add the code to Androidmanifest, Your androidmanifes file must be like below.
<activity
android:name="com.example.ceng389hw1.MainActivity"
android:configChanges="orientation|screenSize"
android:label="#string/app_name" >
Secon Step, You must be override onConfigurationChanged function like below.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText( this, "landscape", Toast.LENGTH_SHORT ).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
For more detail -> http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
In your main activity check is fragment already added in activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
...
if(getFragmentManager().getFragment("Add")==null) {
//initialize fragment, create transaction and commit
}
...
}
You can add configChanges parametre inside manifest.xml it will provide you to ignore reinilizating after config changes you can do it simply like that
<activity
android:name="com.youractivity"
android:configChanges="orientation" />
I hope it will help you :)
So here's the problem. I'm coding an app with two EditText views inside a fragment and a button. When the button is clicked, it changes the text of the EditText. In the onViewCreated() method I use this code to get the EditText instance and store it to a variable.
EditText box1 = (EditText)(getView.findViewById(R.id.box1));
This works fine. However, when I try to access variable box1 when the button is clicked, the EditText has become null and throws a NullPointerException. Does anyone know why this would happen?
Here is the fragment code:
public class MyFragment extends Fragment {
EditText box1, box2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_text_coder_free,
container, false);
//Works here.
box1 = (EditText)(rootView.findViewById(R.id.box1));
box2 = (EditText)(rootView.findViewById(R.id.box2));
//Same thing. Sets the text correctly
box1.setText("hey look at me!");
return rootView;
}
//Called when the button is clicked.
public void setBox1Text(String text) {
//It's null here so it skips to the else
if(box1 != null) {
box1.setText(text);
}
else {
//This doesn't work. Throws the exception here.
box1 = (EditText)(getView().findViewById(R.id.box1));
}
}
public void setBox2Text(String text) {
if(box2 != null) {
box2.setText(text);
}
else {
//This doesn't work. Throws the exception here.
box2 = (EditText)(getView().findViewById(R.id.box2));
}
}
public String getBox1Text() {
if(box1 == null) {
return "Nice try.";
}
return box1.getText().toString();
}
public String getBox2Text() {
if(box2 == null) {
return "Nice try.";
}
return box2.getText().toString();
}
}
Here is the activity which houses the fragment:
public class MyActivity extends Activity {
MyFragment myFragment
EditText box1, box2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_coder);
if (savedInstanceState == null) {
myFragment = new MyFragment();
getFragmentManager().beginTransaction()
.add(R.id.container, myFragment.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.my_app, 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);
}
public void box1Click(View v) {
myFragment.setBox2Text("Some text");
}
public void box2Click(View v) {
myFragment.setBox2Text("Some text");
}
}
And here is the XML from the fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.mycode.MyFragment" >
<EditText
android:id="#+id/box1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:inputType="textMultiLine" />
<EditText
android:id="#+id/box2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/box1"
android:inputType="textMultiLine|none"
android:focusable="false" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/box2"
android:layout_alignParentRight="true"
android:onClick="box2Click" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/encrypt_button_text"
android:layout_below="#id/box2"
android:layout_toLeftOf="#id/button2"
android:onClick="box1Click" />
</RelativeLayout>
Exemple of use:
public class main extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.core_info_tab, container, false);
ImageButton ib = (ImageButton) view.findViewById(R.id.imageButton1);
return view;
}
}
Make sure the fragment is attached to the activity before calling setBox1Text(String text) else the view is not initialized and getView returns null.
There is no need to initialize the edittext again.
You can just have
public void setBox1Text(String text) {
box1.setText(text); // box1 is already initialized in onCreate no need to initialize again
}
If you want use getView use it in onActivtiyCreated
box1 = (EditText)getView().findViewById(R.id.box1));
That's because you're trying to execute setBoxXText(...) before having created the fragment, onCreateView is not yet executed. Be sure that your fragment is loaded before access it's views.
If you check your code, the only way to box1 & box2 to be null is that onCreateView is not yet called, so when you do
if(box1 != null) {
box1.setText(text);
}
else {
and it goes through the else statement, it's because you didn't initialize the fragment.
You have several ways to fix this, for example you can set this values in the fragment initialization (1) or use a listener to notify when the fragment is loaded (2).
1-
Use a factory to initialize your fragment, fragments in android need empty constructors, so in this way you will use an empty constructor and also ensure yourself that in onCreateView you will have setted the box1 and box2 strings
public class YourFragment extends Fragment{
//Empty and private constructor
private YourFragment(){
}
private String box1Text;
private String box2Text;
public void setBox1Text(String box1Text){
this.box1Text = box1Text;
}
public void setBox2Text(String box2Text){
this.box2Text = box2Text;
}
public static YourFragment YourFragmentFactory(String box1Text, String box2Text){
YourFragment result = new YourFragment();
result.setBox1Text(box1Text);
result.setBox2Text(box2Text);
return result;
}
}
and 2:
use a listener to notify your activity when you can start to set the texts:
public interface YourFragmentListener{
public void onViewCreated();
}
private YourFragmentListener listener;
public void setListener(YourFragmentListener listener){
this.listener = listener;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
if(this.listener != null){
this.listener.onViewCreated();
}
}
To use findViewById you have to execute it on Context (eg. an Activity).
Use: View.getContext().getViewById...
You can also try cleaning the project
I want to include Action Bar Tabs in my application and am working through a tutorial example to get my head round it all.
The tutorial has two tabs each with their own fragment so then when the tab is selected the correct fragment is shown...this seems to be the approach shown in all the examples I can find.
What I want to do however is to have each tab have their own instantiation of the Same fragment and to pass an argument to the Fragment so that the code can behave differently dependent on which tab is selected.
This is the code from the tutorial:
ACTIVITY (Start Activity)
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
appContext = getApplicationContext();
//ActionBar
ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab PlayerTab = actionbar.newTab().setText("Fragment A");
ActionBar.Tab StationsTab = actionbar.newTab().setText("Fragment B");
Fragment PlayerFragment = new AFragment();
Fragment StationsFragment = new BFragment();
PlayerTab.setTabListener(new MyTabsListener(PlayerFragment));
StationsTab.setTabListener(new MyTabsListener(StationsFragment));
actionbar.addTab(PlayerTab);
actionbar.addTab(StationsTab);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.menuitem_search:
Toast.makeText(appContext, "search", Toast.LENGTH_SHORT).show();
return true;
case R.id.menuitem_add:
Toast.makeText(appContext, "add", Toast.LENGTH_SHORT).show();
return true;
case R.id.menuitem_share:
Toast.makeText(appContext, "share", Toast.LENGTH_SHORT).show();
return true;
case R.id.menuitem_feedback:
Toast.makeText(appContext, "feedback", Toast.LENGTH_SHORT).show();
return true;
case R.id.menuitem_about:
Toast.makeText(appContext, "about", Toast.LENGTH_SHORT).show();
return true;
case R.id.menuitem_quit:
Toast.makeText(appContext, "quit", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}
}
The following class is included at the end in the same java file :
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
Toast.makeText(StartActivity.appContext, "Reselected!", Toast.LENGTH_LONG).show();
}
public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction ft) {
ft.remove(fragment);
}
This is A FRAGMENT:
public class AFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.afragment, container, false);
}
}
This is B FRAGMENT
public class BFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.bfragment, container, false);
}
}
HERE ARE THE XML FILES:
Main.xml
<LinearLayout
android:orientation="vertical"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
A Fragment:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:id="#+id/textView1"
android:text="Fragment A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
B Fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:id="#+id/textView2"
android:text="Fragment B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
So what I would like to do would be to get rid of Fragment B completely and have both Station and Player tabs use Fragment A. Then within Fragment A put code that did one thing if it is for Station and something else if it is for Player. I've tried all sorts with trying to put an Args Bundle but I'm new to this and nothing I have tried has worked,
I now have a solution that works here.
The way that I have done it is to set a Tag on each of the Tabs as I set them up and then get the current Tab in my fragment and use it's tag.
Code changes are as follows:
In Activity, so that I am just using Fragment A:-
ActionBar.Tab PlayerTab = actionbar.newTab().setText("Tab A")
.setTag("A");
ActionBar.Tab StationsTab = actionbar.newTab().setText("Tab B")
.setTag("B");
Fragment PlayerFragment = new AFragment();
Fragment StationsFragment = new AFragment();
Now within Fragment A I have overriden onResume() and put in the following code :-
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
TextView v = (TextView)getView().findViewById(R.id.textView1);
Tab b = getActivity().getActionBar().getSelectedTab();
String c = b.getTag().toString();
if (c.equals("A"))
v.setText("Tab A has been selected");
if (c.equals("B"))
v.setText("It's Tab B now");
}
Here is the xml for my main layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<FrameLayout
android:id="#+id/fragment_placeholder"
android:layout_width="250dp"
android:layout_height="0dip"
android:layout_weight="1" >
<ImageView
android:contentDescription="image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" />
</FrameLayout>
</LinearLayout>
Code for fragment class
public class ExerciseFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_layout, container, false);
return view;
}
}
and code in main activity for showing fragment on click of a button:
ExerciseFragment fragment = new ExerciseFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_placeholder, fragment);
ft.commit();
if (fragment.isVisible()) {
Toast.makeText(this, "works", Toast.LENGTH_LONG).show();
} else
Toast.makeText(this, "nooooo", Toast.LENGTH_LONG).show();
The toast says "noooo" meaning the fragment is not visible, and it still shows an image which i set up in the framelayout holder which i want to replace. Any ideas why the fragment is not showing up?
EDIT: COMPLETE CODE FOR MAIN ACTIVITY
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().setDisplayHomeAsUpEnabled(false);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.workout_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_exercise:
ExerciseFragment fragment = new ExerciseFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_placeholder, fragment);
ft.commit();
if (fragment.isVisible()) {
Toast.makeText(this, "works", Toast.LENGTH_LONG).show();
} else
Toast.makeText(this, "nooooo", Toast.LENGTH_LONG).show();
break;
}
return super.onOptionsItemSelected(item);
}
}
Instead of using ft.replace(R.id.fragment_placeholder, fragment);, try using ft.add(R.id.fragment_placeholder, fragment);. Since the R.id.fragment_placeholder doesn't contain a fragment yet, you aren't replacing anything, you are merely adding on to the layout. The .add(int containerViewId, Fragment fragment) function should work for your case. In the future, if you are going to change the fragment contained in R.id.fragment_placeholder, use .replace(int containerViewId, Fragment fragment).
Hope this works!