I have to implement "standart" fragments navigation in my app (please see link).
The issue is when device is in portrait mode, there should be shown only 1 fragment, and when it is rotated to landscape mode, 2 fragments should be shown.
I tried to do this 2 different ways:
1) I use only 1 activity with different portrait and landscape layouts.
Portrait layout xml:
<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" >
<FrameLayout
android:id="#+id/main_frame_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
And here`s landscape layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/main_frame_fragment_container_left"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/main_frame_fragment_container_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
Activity`s onCreate method:
private static ItemsFragment mItemsFragment;
private static ItemDetailsFragment mItemDetailsFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (mItemsFragment == null) {
mItemsFragment = ItemsFragment.newInstance();
}
if (mItemDetailsFragment == null) {
mItemDetailsFragment = ItemDetailsFragment.newInstance();
}
if (isLandscape()) {
getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container_left, mItemsFragment)
.commit();
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
} else {
getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container, mItemsFragment)
.commit();
}
}
And that`s the way I refresh 2nd fragment:
Bundle bundle = new Bundle();
bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, response.getItem());
mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle);
if (isLandscape()) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
} else {
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container, mItemDetailsFragment).addToBackStack(null).commit();
}
Also I save and restore fragments` states, so my data does not disappear after rotations. Generally, this code works properly in my case.
2) I use 2 activities and the same layout for 1st Activity portrait and landscape modes.
xml layout is the same as in previous one for landscape:
<FrameLayout
android:id="#+id/main_frame_fragment_container_left"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/main_frame_fragment_container_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
onCreate method (note, that fragments entities are not static, as it was in 1st case):
private ItemsFragment mItemsFragment;
private ItemDetailsFragment mItemDetailsFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
mItemsFragment = ItemsFragment.newInstance();
mItemDetailsFragment = ItemDetailsFragment.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.main_frame_fragment_container_left, mItemsFragment)
.commit();
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
}
}
And now if the device is in portrait mode, I start new Activity:
if (isLandscape()) {
Bundle bundle = new Bundle();
bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, response.getItem());
mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container_right, mItemDetailsFragment).commit();
} else {
Intent intent = new Intent(getApplicationContext(), DetailsActivity.class);
intent.putExtra(KEY_ITEM, response.getItem());
startActivity(intent);
}
And, at last, 2nd Activity`s onCreate method:
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_details);
if (isLandscape()) {
finish();
}
Item item = (Item) getIntent().getExtras().getSerializable(KEY_ITEM);
Bundle bundle = new Bundle();
bundle.putSerializable(BaseFragment.KEY_BUNDLE_ITEM, item);
ItemDetailsFragment mItemDetailsFragment = ItemDetailsFragment.newInstance(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame_fragment_container, mItemDetailsFragment).commit();
}
When device is rotated to landscape mode, 2nd activity finishes, and I see my 1st activity with 2 fragments (as expected).
Question:
In 1st case I save fragments as static variables, and because of this I don't care if I change 2nd fragment state in portrait or landscape modes (the same fragment is used). But I don't think it's a good idea to save it as static fields.
In 2nd case I don't know how to sync Activity A Fragment B (landscape) and Activity B Fragment B (portrait). If I change something in fragment (I mean, toggle button etc) and rotate device, changes should be applied in another fragment.
Generally, what case is better, and if 2nd, how can I resolve synchronization issue? Or maybe there is another easier way. Thanks for reading, I hope you can help me :)
Just follow this mate http://developer.android.com/guide/components/fragments.html. Dont make fragments static (thats just wierd)
Related
I have some sort of architecture issue:
I have Activity in which I need to show one of 3 views (one view at one moment in time):
1. One view with stable AppBarLayout + another part of the screen is
NestedScrollView that needs to be in separate fragment.
2. One view with stable AppBarLayout + another part of screen need to be a fragment with two tabs to switch between them.
3. Connection lost view - is a fullscreen view without AppBar - just to show that there is no connection.
The upper part of AppBarLayout - I made. Looks like good, but I need runtime to switch Fragments depending on the response from Server.
I am sending a request to the server in onCreate method in MainActivity, and then in onDataLoadedFromServer callback, depending on response - I am deciding which fragment to create. But my application crashes, because fragments fields are not initialized properly - the view is not attached to fragment. When I am adding fragment in onCreate method - everything is working good, but at that time I don't have a response from server.
Where to place TabLayout? And where ViewPager? Do I need to put
TabLayout in main_activity.xml, and ViewPager in separate
fragment_2_layout. And then add it to FrameLayout (container for
fragment which is located in main_activity)?
Is it good practice to load some data from the server in the fragment? Or it's better to load data in Activity and then set it through the method
call to Fragment?
Please, provide some sort of pseudo code to understand logic. Thanks!.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:id="#+id/shop_final_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lampa.letyshops.view.activity.ShopFinalActivity">
<android.support.design.widget.AppBarLayout>
<android.support.design.widget.CollapsingToolbarLayout>
<include
layout="#layout/collapsing_part" />
<android.support.v7.widget.Toolbar>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
<LinearLayout
android:id="#+id/content_layout_dual_tabs">
<android.support.design.widget.TabLayout />
<android.support.v4.view.ViewPager/>
</LinearLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<include layout="#layout/shop_final_no_connection_layout" />
</android.support.design.widget.CoordinatorLayout>
public MainActivity {
protected void onCreate(Bundle savedInstanceState) {
loadDataFromServer();
}
private void onDataLoaded(Object dto) {
if (showOneViewLayout) {
showOneViewLayout();
} else {
showTabViewLayout();
}
}
}
private void showOneViewLayout() {
f1 = Fragment1.newInstance(params);
showFragmentWithoutBackStack(R.id.fragment_holder, f1);
}
private void showTabViewLayout() {
f2 = Fragment2.newInstance();
showFragmentWithoutBackStack(R.id.fragment_holder, f2);
}
protected void showFragmentWithoutBackStack(int containerViewId, Fragment fragment) {
Fragment previousFragment = currentFragment;
Fragment currentFragment = fragment;
String fragmentTag = fragment.getClass().getSimpleName();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if (previousFragment != null) {
fragmentTransaction.hide(previousFragment);
}
fragmentTransaction.add(containerViewId, fragment, fragmentTag)
.commitAllowingStateLoss();
}
I am new to developing android applications, so please pardon any stupid mistakes that I may have made. On to the question:
I am making an application which has its main activity layout screen containing some stuff and have a navigation drawer wired in. Now I am trying to use the entries in the navigation drawer to call up various fragments and display them over my main activity. However when I run my piece of code, I am getting an Activity Destroyed error I have attached my code below for reference. I think the problem is with what I have done with the container. To make the fragment cover the whole screen of my main activity, I gave the fragment container as the root layout as I was unsure how to go about this.
Code which handles item clicks from navigation drawer
class DrawerItemClickListener extends FragmentActivity implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
private void selectItem(int position) {
Fragment mFragment = null;
switch(position) {
case 0:
mFragment = new AnnouncementFragment();
Bundle args = new Bundle();
args.putInt(null, position);
break;
case 1:
break;
case 2:
break;
case 3:
break;
default:
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.drawer_layout, mFragment);
transaction.commit();
transaction.addToBackStack(null);
}
Code for fragment
public class AnnouncementFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_announcement, container, false);
}
XML layout of main activity
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id = "#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/screen_login"
android:gravity="center"
android:textColor="#android:color/holo_blue_light"
android:id="#+id/login_tv"
android:layout_alignParentTop="true"
android:layout_marginTop="105dp"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:textSize="40sp" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/username_et"
android:layout_below="#id/login_tv"
android:layout_alignParentStart="true"
android:layout_marginTop="45dp"
android:layout_alignParentEnd="true"
android:hint="#string/username"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:ems="10"
android:id="#+id/editText2"
android:layout_below="#id/username_et"
android:layout_alignParentStart="true"
android:layout_marginTop="30dp"
android:layout_alignParentEnd="true"
android:hint="#string/password" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/login"
android:id="#+id/login_btn"
android:layout_below="#+id/editText2"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp" />
</RelativeLayout>
<ListView
android:id="#+id/drawer_list"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ffeeeeee"/>
Error
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1399)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:637)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:616)
at com.it.learnera.DrawerItemClickListener.selectItem(DrawerItemClickListener.java:40)
at com.it.learnera.DrawerItemClickListener.onItemClick(DrawerItemClickListener.java:19)
I am wondering how I can make the fragment draw over the main activity layout without causing a mess
Cheers and Thanks in advance
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction()
.replace(R.id.drawer_layout, mFragment); // < - first problem ( see ad. 1)
.commit() // <- third problem (see ad. 3)
// second problem ( see ad. 2)
mFragment = new AnnouncementFragment();
Bundle args = new Bundle();
args.putInt(null, position);
ad 1. You replacing DrawerLayout instead of its container
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
drawer_layou - this is a view which holds:
FrameLayout / with id - >content_frame
( container capable to hold "only" one element: fragment / view)
ListView / with id - > left_drawer
( list view for example with menu entries )
so you need replace content_frame
ps to better see purpose of transaction you should call it in one statement - in "chain / sequence "
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, mFragment)
.addToBackStack(null) // add to manager " will remember this fragment - for navigation purpose"
.commit() // commit mean do everything from top to bottom on next pass
ad 2. you need also put args in fragment:
mFragment = new AnnouncementFragment();
Bundle args = new Bundle();
args.putInt(null, position);
mFragment.setArguments(args)
ad 3. You calling commit when activity is after onSaveInstanceState
Note:
A fragment transaction can only be created/committed prior to an activity saving its state.
If you try to commit a transaction after:
Activity.onSaveInstanceState()
and prior to a following
Activity.onStart()
Activity.onResume()
you will get an error. This is because the framework takes care of saving your current fragments in the state, and if changes are made after the state is saved then they will be lost.
After FragmentTransaction is committed with FragmentTransaction.commit() is scheduled to be executed asynchronously on the process's main thread.
If you want to immediately executing any such pending operations, you can call this function (only from the main thread) to do so. Note that all callbacks and other related behavior will be done from within this call, so be careful about where this is called from.
boolean executePendingTransactions();
which return true if there were any pending transactions to be executed.
btw look at this docs which refers to extending an FragmentActivity:
https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html
i don't know which api you target but you may also check this bug:
http://johnfeng.github.io/blog/2015/05/31/fragment-activity-has-been-destoryed-problem/
( problem with child fragment which state is not being reset )
Hi, appreciate the detailed explanation but it doesnt work – Prejith P
and this article about state loss which is i think related to your problem
http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
so you can try call instead of commit() (but this is not solution):
commitAllowingStateLoss()
Hi, I fixed it myself just now. I changed the implementation of my navigation drawer a bit and it just started working. I have no idea how it got fixed, which is why I haven't posted an answer here – Prejith P
YES - the problem was your implementation you have tried to call commit() after an activity instance was destroyed what is indicating by stack trace
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1399)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:637)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:616)
at com.it.learnera.DrawerItemClickListener.selectItem(DrawerItemClickListener.java:40)
at com.it.learnera.DrawerItemClickListener.onItemClick(DrawerItemClickListener.java:19)
`
when You call commit() you should ensure that:
activity is attached
activity is visible ( before onSaveInstanceState )
The problem is that you're calling transaction.addToBackStack(null); after you commit the replacement. I suggest you to do as follow:
getSupportFragmentManager().beginTransaction()
.replace(R.id.drawer_layout, mFragment).addToBackStack(null).apply();
u need a fragment to fragment communication
class DetailActivity extends
AppCompatActivity implements BioDetailClickView {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.navigation);
setSupportActionBar(toolbar);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = new Fragment1();
fm.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
}
public void fragment_transaction(Fragment fragment){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
#Override
public void onClickFragmentQuick() {
Fragment frag= new Fragment1();
fragment_transaction(frag);
}
#Override
public void onClickFragment2() {
Fragment fragment =new Fragment2();
fragment_transaction(fragment);
}
#Override
public void onClickFragment3() {
Fragment fragment =new Fragment3();
fragment_transaction(fragment);
}
public interface BioDetailClickView {
void onClickFragment1();
void onClickFragment2();
void onClickFragment3();
}
I've tried adding splash screens to my app, and while they do show before the main activity, this screen also always shows no matter what:
Here is the code for MainActivity:
public class MainActivity extends Activity implements WelcomeFragment.StartQuestions, QuestionFragment.QuestionsAnswered {
#Override
protected void onCreate(Bundle savedInstanceState) {
Parse.enableLocalDatastore(this);
Parse.initialize(this, "***************************", "*****************************");
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
loadingIcon = (ProgressBar) findViewById(R.id.loadingIcon);
loadingIcon.setVisibility(View.GONE);
checkInternetConnection();
showWelcomeScreen();
}
}
showWelcomeScreen():
public void showWelcomeScreen(){
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragmentContainer);
if (fragment == null){
fragment = new WelcomeFragment();
getFragmentManager().beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
} else {
fragment = new WelcomeFragment();
getFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, fragment)
.commit();
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/loadingPanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" android:id="#+id/loadingIcon"/>
</RelativeLayout>
In MainActivity, I have already specified the removal of the top bar:
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
The app itself doesn't have the bar. Any activity that I place as being default in the manifest (acting as a splash screen) is nevertheless proceeded by the screen shown above when the app is launched.
You can't. Android will always attempt to show something using only the attributes of your theme before your Activity actually loads.
In fact, the correct way to build a splash screen involves taking advantage of that fact and customizing your theme such that what displays during this time is your splash screen.
If I dynamically add a Fragment (using the FragmentManager) into a container defined in a landscape XML then switch to portrait, that dynamically injected Fragment still exists. It is contributing to the Action Bar even though it is not visible. What is a good way / design to prevent this from happening?
I have tried using isVisible in onCreateOptionsMenu of the Fragment but that causes issues on some Android versions because onCreateOptionsMenu is called before onCreateView which results in false even if the fragment is going to be visible with the current configuration.
Note: I am not handling the configuration myself. I haven't specified configChanges in the manifest and I am not overriding onConfigurationChanged.
Activity:
// inject detail fragment
Fragment detailFragment = getSupportFragmentManager().findFragmentById(R.id.detail_container);
if(detailFragment == null)
getSupportFragmentManager().beginTransaction().replace(R.id.detail_container, DetailFragment.newInstance(id)).commit();
// inject master fragment
if(findViewById(R.id.master_container) != null) {
masterDetail = true;
Fragment listFragment = getSupportFragmentManager().findFragmentById(R.id.master_container);
if(listFragment == null)
getSupportFragmentManager().beginTransaction().replace(R.id.master_container, ListFragment.newInstance(position)).commit();
}
Activity portrait XML
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Activity landscape XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false">
<FrameLayout
android:id="#+id/master_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="#+id/detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"/>
</LinearLayout>
The model I'd follow based on your explanation.
public class MyActivity extends Activity {
boolean mMultiPane = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout masterContainer = (FrameLayout) findViewById(R.id.master_container);
if (masterContainer != null)
mMultiPane = true;
...
}
}
From then on in your Activity you can use the mMultiPane variable to change the behaviour including changing how the options menu is set up (just have two different menu.xml files or add / remove menu items depending on which mode you're in).
findViewById(R.id.team_detail_container) is failing to find the view. Is my problem with the xml or in the way I am constructing the FragmentActivity? How do I solve this?
To support a customised list for a fragment in the constructor of my fragment activity I have replaced
setContentView(R.layout.activity_team_list);
with
frag=(TeamListFragment)getSupportFragmentManager().findFragmentById(android.R.id.content);
if (frag==null) {
frag=new TeamListFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
So that my class now looks like this
public class TeamListActivity extends SherlockFragmentActivity implements
TeamListFragment.Callbacks {
private boolean mTwoPane;
private TeamListFragment frag=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
frag=(TeamListFragment)getSupportFragmentManager().findFragmentById(android.R.id.content);
if (frag==null) {
frag=new TeamListFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (findViewById(R.id.team_detail_container) != null) {
Log.i("####", "Team Detail Container has been found! Yaay!");
mTwoPane = true;
((TeamListFragment) getSupportFragmentManager().findFragmentById(
R.id.team_list)).setActivateOnItemClick(true);
}
}
The if (findViewById(R.id.team_detail_container) != null) { condition is never met despite the fact that team_detail_container exists in the xml file that is used
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/team_list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:orientation="horizontal"
android:showDividers="middle"
tools:context=".TeamListActivity" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/team_list"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false" />
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No data"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
/>
<FrameLayout
android:id="#+id/team_detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
I know that this particular layout xml is being used as changes I make to the xml file are reflected in the app.
I also know that the condition is never met as I never get the log message Log.i("####", "Team Detail Container has been found! Yaay!"); and the behaviour get is that when an item is selected the list view is replaced with the detail fragments instead of the detail fragments being displayed next to the list view because the item selected conditions are not being met
#Override
public void onItemSelected(int id) {
if (mTwoPane) {
// mTwoPane is never set! Why?
Bundle arguments = new Bundle();
arguments.putInt(TeamDetailFragment.ARG_ITEM_ID, id);
TeamDetailFragment fragment = new TeamDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.team_detail_container, fragment).commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, TeamDetailSwipeActivity.class);
detailIntent.putExtra(TeamDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
The fragment doesn't get added to your layout tree immediately after committing the transaction. You'll have to wait till onViewCreated on the fragment was called. You could probably access the view within the onStart-Method of your Activity, but it would probably be a better idea to keep that logic within the fragment itself. The Activity shouldn't be concerned with what views are contained in a fragment.
I think the issue is you're looking for the Fragment from the Activity, but since you're not using setContentView, the Activity doesn't actually have a View to look through. Try getting the view from the Fragment instead using the getView() method.