Orientation change with multiple fragments and different layouts - android

In landscape, I have an activity with previewFragment loaded into the R.id.fragment_container_child (on the left third of the screen) and selectionFragment loaded into R.id.fragment_container_parent (right two thirds of the screen). Selecting the second tab changes selectionFragment to contactFragment but previewFragment remains the same. This all works fine.Upon an orientation change, the layout is changed slightly via xml, where R.id.fragment_child now occupies the bottom third, instead of the left third. The problem arises when I change the orientation. My action bar and fragments disappear, although the layout is confirmed changing.I have not defined android:configChanges="orientation" in the Manifest file. Below is the code to my activity:
public class MainActivity extends Activity implements ActionBar.TabListener {
static SelectionFragment selectionFragment;
static ContactFragment contactFragment;
public static PreviewFragment previewFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.fragment_container_child) != null) {
if (savedInstanceState != null) {
return;
}
previewFragment = new PreviewFragment();
selectionFragment = new SelectionFragment();
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
transaction.add(R.id.fragment_container_child, previewFragment,
"PREVIEW");
transaction.add(R.id.fragment_container_parent, selectionFragment,
"SELECTION");
transaction.commit();
}
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.addTab(actionBar.newTab().setText(R.string.menu)
.setTabListener(this));
actionBar.addTab(actionBar.newTab()
.setText(R.string.client_information).setTabListener(this));
sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
}
#Override
public void onSaveInstanceState(Bundle outState) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction transaction) {
switch (tab.getPosition()) {
case 0:
if (selectionFragment == null) {
selectionFragment = new SelectionFragment();
transaction.add(R.id.fragment_container_parent,
selectionFragment, "SELECTION");
} else {
transaction.attach(selectionFragment);
}
break;
case 1:
if (contactFragment == null) {
contactFragment = new ContactFragment();
transaction.add(R.id.fragment_container_parent,
contactFragment, "CONTACT");
} else {
transaction.attach(contactFragment);
}
break;
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction transaction) {
switch (tab.getPosition()) {
case 0:
if (selectionFragment != null)
transaction.detach(selectionFragment);
break;
case 1:
if (contactFragment != null)
transaction.detach(contactFragment);
break;
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction transaction) {
}

I can't understand what really happens to you, but here some tips:
When you rotate the screen Android destroy and rebuild all Fragment/Activity. So take a look in your onCreate, onDestroy...
If you're want a multiple screen app take a look here and create new layouts for each screen to make sure that your app will work fine.

Related

Android SlidingMenu lag at first use

I am experiencing some problems with the slidingmenu library from jfeinstein10: https://github.com/jfeinstein10/SlidingMenu
The problem I observe is that at first use, when the menu opens, it lags showing some black space. Then when I close it and reuse it again, everything is smooth, nothing to declare.
I basically have an Activity extending the SlidingFragmentActivity, and 2 fragments. One for the left menu and another one for the main content.
Here is how I implemented it, I'm investigating this but I really don't know what I've missed:
public class CavendishSlidingFragmentActivity extends SlidingFragmentActivity {
private final String TAG = CavendishSlidingFragmentActivity.class.getName();
protected FragmentManager fragmentManager;
protected Fragment mContent;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
fragmentManager = getSupportFragmentManager();
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
getSlidingMenu().setBehindOffset((int) (metrics.widthPixels * 0.2));
}
public void onClickMenu(View v)
{
if (getSlidingMenu().isMenuShowing())
getSlidingMenu().showContent();
else
getSlidingMenu().showMenu();
}
public void onClickMenuItem(View v)
{
Long position = (Long) v.getTag();
switch (position.intValue())
{
case Utils.CAT_RESTAURANT:
showFragment(new RestaurantFragment());
break;
case Utils.CAT_SLEEP:
showFragment(new SleepFragment());
break;
case Utils.CAT_DISCOVER:
showFragment(new DiscoverFragment());
break;
case Utils.CAT_TRANSPORT:
showFragment(new TransportFragment());
break;
}
}
private void showFragment(Fragment fragment)
{
if (mContent != fragment)
{
mContent = fragment;
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.main_fragment, fragment);
fragmentTransaction.commit();
}
getSlidingMenu().showContent();
}
}
MainActivity.java
public class MainActivity extends CavendishSlidingFragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setBehindContentView(R.layout.fragment_menu);
setContentView(R.layout.fragment_main);
// set the Above View Fragment
if (savedInstanceState != null)
mContent = fragmentManager.getFragment(savedInstanceState, "mContent");
if (mContent == null)
{
mContent = new RestaurantFragment();
}
fragmentManager
.beginTransaction()
.replace(R.id.main_fragment, mContent)
.commit();
}
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
fragmentManager.putFragment(outState, "mContent", mContent);
}
}
I can provide further code but I think the issue might be here, since the menu is drawing itself at first use, causing the lag. I believe I have to force the menu to be drawn before showing it.
Looks like there is something wrong with the library when rendering the menu while it's being opened. My design didn't fit the library I guess, well I just passed to the default Android navigation drawer. Bit different in behavior but the design remains unchanged, works fine for me.

How to include the activity in fragment tabs ?

I am developing an app in which there are two fragmenttabs.when pressing the tabs corresponding fragments will appear.that works fine.but what I want an activity inside the fragmenttabs. I am using ABS library for this.
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = bar.newTab();
ActionBar.Tab tab2 = bar.newTab();
tab1.setText("Fragment A");
tab2.setText("Fragment B");
tab1.setTabListener(new MyTabListener<FragmentA>(this, "tab1",
FragmentA.class, null));
tab2.setTabListener(new MyTabListener<FragmentB>(this, "tab1",
FragmentB.class, null));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; go Location selection
Intent intent = new Intent(FragmentDemoActivity.this,
TestActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getSupportActionBar()
.getSelectedNavigationIndex());
}
listnerclass is
public class MyTabListener<T extends Fragment> implements ActionBar.TabListener {
private final FragmentActivity mActivity;
private final String mTag;
private final Class<T> mClass;
private final Bundle mArgs;
private Fragment mFragment;
public MyTabListener(FragmentActivity activity, String tag, Class<T> clz,
Bundle args) {
mActivity = activity;
mTag = tag;
mClass = clz;
mArgs = args;
FragmentTransaction ft = mActivity.getSupportFragmentManager()
.beginTransaction();
mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(
mTag);
if (mFragment != null && !mFragment.isDetached()) {
ft.detach(mFragment);
}
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft = mActivity.getSupportFragmentManager().beginTransaction();
if (mFragment == null) {
mFragment = Fragment
.instantiate(mActivity, mClass.getName(), mArgs);
ft.add(android.R.id.content, mFragment, mTag);
ft.commit();
} else {
ft.attach(mFragment);
ft.commit();
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft = mActivity.getSupportFragmentManager().beginTransaction();
if (mFragment != null) {
ft.detach(mFragment);
ft.commitAllowingStateLoss();
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
Fragmentclass
public class FragmentB extends Fragment {
Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved)
{
return inflater.inflate(R.layout.frag_b, group, false);
}
#Override
public void onActivityCreated (Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
button = (Button) getActivity().findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Fragment B");
builder.setMessage("What would you like to do?");
builder.setPositiveButton("Nothing", null);
builder.setNegativeButton("Leave me alone!", null);
builder.show();
}
});
}
}
i wnt to include the following activity in the fragmentB
public class TestActivity extends Activity {
Button b1, b2;
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.testactivity);
b1 = (Button) findViewById(R.id.button1);
b2 = (Button) findViewById(R.id.button2);
tv = (TextView) findViewById(R.id.textView1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tv.setText("You Clicked on Button 1");
}
});
b2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tv.setText("You Clicked on Button 2");
}
});
}
}
I have lot of created activites to include in the fragment..its un imaginable to recreate in onActivityCreated of fragment class. according to this I have to modify my main application.
A Fragment can't host an activity. Instead of activity, you can use Nested Fragment.
A simple tutorial: http://xperiment-andro.blogspot.com/2013/02/nested-fragments.html
You cannot run an activity inside of a fragment. At best, you can have a fragment inside of a fragment.
so the best thing you can do in this situation is instead of creating an Activity you can create a Fragment and add it inside your FragmentB.
Like Faheem Said "
A Fragment can't host an activity. Instead of activity, you can use Nested Fragment"
Fragments are just like Activities if you read the Docs.Changing your activity to Fragment is easy
This is what developer.android says
To create a fragment, you must create a subclass of Fragment (or an existing subclass of it). The Fragment class has code that looks a lot like an Activity. It contains callback methods similar to an activity, such as onCreate(), onStart(), onPause(), and onStop(). In fact, if you're converting an existing Android application to use fragments, you might simply move code from your activity's callback methods into the respective callback methods of your fragment.
Usually, you should implement at least the following lifecycle methods:
onCreate()
The system calls this when creating the fragment. Within your implementation, you should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
onCreateView()
The system calls this when it's time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a View from this method that is the root of your fragment's layout. You can return null if the fragment does not provide a UI.
onPause()
The system calls this method as the first indication that the user is leaving the fragment (though it does not always mean the fragment is being destroyed). This is usually where you should commit any changes that should be persisted beyond the current user session (because the user might not come back).
This is the code activity inside Fragment.
YourActivityName.getSupportFragmentManager();

Tab navigation in new HoloEverywhere not displays fragment after screen rotation

Yesterday I downloaded new HoloEverywhere library.
Currently, I have problem with tab navigation after screen rotation.
My Home Activity:
public class MainActivity extends Activity implements TabListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setUpTabs();
}
private void setUpTabs() {
String[] titles = {
"First", "Second",
};
ActionBar supportActionBar = getSupportActionBar();
for (int i = 0; i < titles.length; i++) {
ActionBar.Tab tab = supportActionBar.newTab();
tab.setText(titles[i]);
tab.setTag(MyFragment.TAG);
tab.setTabListener(this);
supportActionBar.addTab(tab, false);
}
supportActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
supportActionBar.setSelectedNavigationItem(0);
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) {
final String fragmentTag = tab.getTag().toString();
Fragment fragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (fragment == null) {
fragment = new MyFragment();
fragmentTransaction.add(android.R.id.content, fragment, fragmentTag);
} else {
fragmentTransaction.attach(fragment);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction fragmentTransaction) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag((String) tab.getTag());
if (fragment != null) {
fragmentTransaction.detach(fragment);
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction fragmentTransaction) {
}
}
And my Fragment class.
public class MyFragment extends Fragment {
public static final String TAG = MyFragment.class.getCanonicalName();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = new View(getActivity());
view.setBackgroundColor(Color.BLACK);
return view;
}
}
When I rotate the screen fragment not displaying. It displays when i select tab (which is not currently selected) manually.
I just solve the problem.
I post my code here and see if those can help you :D
if (savedInstanceState == null){
TabHomeFragment homeFragment = new TabHomeFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, homeFragment, "home_fragment").commit();
}else{
TabHomeFragment homeFragment = (TabHomeFragment) getSupportFragmentManager().findFragmentByTag("home_fragment");
}
Those code are located in OnCreate method.
When the Device rotate and Ortiention change, the fragment will recreate again. So add a if clase to check if there is already one here.
But I am using normal Fragment in Android. Hope it can help you a little.

How to show ListView in Tab?

I want to display ListView in Tab (after selecting this tab I want ListView to appear),so I have created Fragment class and placed ListView code in it.The main problem now is to pass fragment object to tabListener. Please, post here example, or even better show how to do that in my code. Anyway, any help will be appreciated.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tabOne = actionBar.newTab().setText("One");
ActionBar.Tab tabTwo = actionBar.newTab().setText("Two");
tabOne.setTabListener(new tabListener());
tabTwo.setTabListener(new tabListener());
actionBar.addTab(tabOne);
actionBar.addTab(tabTwo);
}
protected class tabListener implements ActionBar.TabListener {
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
};
public class FirstFragment extends ListFragment {
private ArrayList<Cinemas> cinema;
private CinemasAdapter cinemaAdapter;
private ListView list;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
cinema = new Handler().handle();
cinemaAdapter = new CinemasAdapter(MainActivity.this, R.layout.movie_data_row, cinema);
setListAdapter(cinemaAdapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Cinemas movie = cinemaAdapter.getItem(position);
Intent intent = new Intent (MainActivity.this, More.class);
intent.putExtra("Cinemas", movie);
intent.putExtra("data", movie.getBitmap());
Bundle translateBundle =
ActivityOptions.makeCustomAnimation(MainActivity.this,
R.anim.slide_in_left, R.anim.slide_out_left).toBundle();
startActivity (intent, translateBundle);
}
}
}
If you want to open up the list inside the tabTwo, you will need to create an instance of the FirstFragment class and add it to your view when you select the tab. Inside onTabSelected, create a new instance of FirstFragment if it isn't null, and add it to your view inside a container in your activity_main file. A container is a linear layout inside the view with the given amount of space that should be occupied by the fragment. In the case of a fullscreen fragment, the container is the root layout. You need only to specify an id to this layout. Once you create a new fragment, attach it by calling transaction.attach(); The final code block should be similar to this:
/** this example assumes that the fragment
* FirstFragment will be attached to tab 1
* which is at position = 0, and SecondFragment
* will be attached to tab 2, which is at
* position = 1. Also, the root layout of
* activity_main.xml has the id attribute of
* fragment_container
*/
FirstFragment firstFragment;
SecondFragment secondFragment;
#Override
public void onTabSelected(Tab tab, FragmentTransaction transaction) {
switch (tab.getPosition()) {
case 0:
if (firstFragment == null) {
firstFragment = new FirstFragment();
transaction.add(R.id.fragment_container,
firstFragment, "FIRST");
} else {
transaction.attach(firstFragment);
}
break;
case 1:
if (secondFragment == null) {
secondFragment = new SecondFragment();
transaction.add(R.id.fragment_container, secondFragment, "SECOND");
} else {
transaction.attach(secondFragment);
}
break;
}
}

Run code in ActionBar Tab Fragment when tab is removed

I've got Fragment ActionBar Tabs with an TabListener attached to every tab. In my main activity I got a delete tab button as follows:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()
case R.id.closeTab:
closeTab();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void closeTab() {
if(getActionBar().getTabCount() > 1) {
Tab tab = getActionBar().getSelectedTab();
getActionBar().removeTab(tab);
}
}
What I'm trying to accomplish is to run some code in my tab-fragment before it gets removed. I could place this in the fragments onDestroyView() or onDestroy() but I only whant to run this code when I press my delete tab button.
I have checked the documentation for the TabListener but it seems like TabListener only listens to selectionchanges.
My TabListener:
public TabListener(Activity a, String t, Class<T> c) {
activity = a;
tag = t;
myClass = c;
}
/* The following are each of the ActionBar.TabListener callbacks */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (fragment == null) {
// If not, instantiate and add it to the activity
fragment = Fragment.instantiate(activity, myClass.getName());
ft.add(android.R.id.content, fragment, tag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(fragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (fragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(fragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
To clarify my question: How can I run code in my Fragment before the tab is removed?
Okey, I figured it out after reading this post: link.
In my fragment I put setHasOptionMenu(true)
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
And then I could just add onOptionsItemSelected in my fragment.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.closeTab:
closeTab();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void closeTab() {
ActionBar actionBar = getActivity().getActionBar();
if(actionBar.getTabCount() > 1) {
Tab tab = actionBar.getSelectedTab();
actionBar.removeTab(tab);
Log.d(TAG, "CLOSED TAB");
}
}

Categories

Resources