I want to show a Button and a PieChart below in a tab.
Thats the code I worked with: https://github.com/JakeWharton/ActionBarSherlock/blob/master/samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabs.java
Instead of the CountingFragment etc. I implemented my own.
I'm not sure what to
My xml:
fragment_graph_categories.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_graph_categories"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button_filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_filter" />
</LinearLayout>
And that's my "Tab" attached to the TabManger
public class GraphCategories extends SherlockFragmentActivity {
GraphCategoriesFragment mCategoriesFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_graph_categories);
if (savedInstanceState == null) {
// Do first time initialization -- add initial fragment.
mCategoriesFragment = GraphCategoriesFragment.newInstance(1);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_graph_categories, mCategoriesFragment).commit();
} else {
//mStackLevel = savedInstanceState.getInt("level");
}
}
#Override
protected void onResume() {
if(mCategoriesFragment != null) {
//mCategoriesFragment.onResumeRedraw();
}
}
//notice Inner class
public static class GraphCategoriesFragment extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//View mChartView = inflater.inflate(R.layout.hello_world, container, false);
View rlayout = inflater.inflate(R.layout.fragment_graph_categories, container, false);
//? rlayout = new LinearLayout(getActivity());
return rlayout;
}
}
}
But im not sure what to inflate at the fragments onCreateView or if I need a FrameLayout in my xml?
I tried some options but don't figured it out.
Related
I am sending data from one fragment to another, using interface. This works absolutely fine. Now I am trying to use onSaveInstanceState() to save the value in
a Fragment and retrieving in onCreate(). however i'm getting null in Bundle of onCreate(). P.S. everything works fine when i set the Fragment directly into the activity layout in xml. but when i set the fragment through java code into the activity, the onSaveInstanceState is failing. It is not saving the last known value. Please help. Pasting the code below. You can try it out to know the exact issue.
Fragment_A :
public class Fragment_A extends Fragment implements View.OnClickListener {
Button btnAdd;
int counter = 0;
Communicator comm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null){
counter = savedInstanceState.getInt("counter", 0);
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
comm = (Communicator) getActivity();
btnAdd = (Button) getActivity().findViewById(R.id.btnAdd);
btnAdd.setOnClickListener(this);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("counter", counter);
}
#Override
public void onClick(View v) {
counter++;
comm.sendData(counter);
}
}
interface Communicator{
void sendData(int i);
}
=====
Activity :
public class Activity_InterComm extends Activity implements Communicator{
FragmentManager manager;
FragmentTransaction transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intercomm);
Fragment_A fragment_1 = new Fragment_A();
Fragment_B fragment_2 = new Fragment_B();
manager = getFragmentManager();
transaction = manager.beginTransaction();
transaction.add(R.id.frag_a, fragment_1, "Frag1");
transaction.add(R.id.frag_b, fragment_2, "Frag2");
transaction.commit();
}
#Override
public void sendData(int i) {
manager = getFragmentManager();
Fragment_B fragment_b = (Fragment_B) manager.findFragmentById(R.id.frag_b);
fragment_b.setData("Button has been clicked " + i + " times");
}
}
=====
Fragment_B :
public class Fragment_B extends Fragment {
TextView txtMessage;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_b, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
txtMessage = (TextView) getActivity().findViewById(R.id.txtMessage);
}
public void setData(String message){
txtMessage.setText(message);
}
}
activity_intercomm.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">
<!--<fragment
android:id="#+id/frag_a"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:name="android.learning.com.fragintercomm.Fragment_A"/>
<fragment
android:id="#+id/frag_b"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="android.learning.com.fragintercomm.Fragment_B"/>-->
<LinearLayout
android:id="#+id/frag_a"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:background="#color/colorAccent"
android:orientation="vertical"/>
<LinearLayout
android:id="#+id/frag_b"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:background="#color/colorPrimaryDark"
android:orientation="vertical"/>
</LinearLayout>
the soluion I found was using getView() instead of getActivity() while initializing the button in Fragment_A. use btnAdd = (Button) getView().findViewById(R.id.btnAdd); instead of btnAdd = (Button) getActivity().findViewById(R.id.btnAdd);.
However, you can't use getView() in Fragment_B. The Textview freezes and, onSaveInstanceStat() doesn't work. Please suggest a solution.
I'm having a problem in my app where, even with some of the most basic code (see below), I'm losing a fragment view on rotation.
Everything starts off great:
Until you rotate:
The story is the same the the other way as well:
I'm not sure what is going on. I've tried to follow various tutorials and code examples, checked via logging to make sure that the fragments are being saved and restored, but to no avail. What am I doing wrong?
MainActivity.java
public class MainActivity extends FragmentActivity
{
private FragmentManager fragment_manager;
private CharacterMenuFragment characterMenuFragment;
private CharacterEditFragment characterEditFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_frame);
fragment_manager = getSupportFragmentManager();
if (savedInstanceState != null) {
characterMenuFragment = (CharacterMenuFragment) fragment_manager.getFragment(savedInstanceState, "characterMenuFragment");
characterEditFragment = (CharacterEditFragment) fragment_manager.getFragment(savedInstanceState, "characterEditFragment");
}
if (characterMenuFragment == null) {
Log.i("characterMenuFragment", "making new fragment");
characterMenuFragment = new CharacterMenuFragment();
} else {
Log.i("characterMenuFragment", "re-using old fragment");
}
if (characterEditFragment == null) {
Log.i("characterEditFragment", "making new fragment");
characterEditFragment = new CharacterEditFragment();
} else {
Log.i("characterEditFragment", "re-using old fragment");
}
fragment_manager.beginTransaction().replace(R.id.menu_frame, characterMenuFragment).commit();
fragment_manager.beginTransaction().replace(R.id.content_frame, characterEditFragment).commit();
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
fragment_manager.putFragment(savedInstanceState, "characterMenuFragment", characterMenuFragment);
fragment_manager.putFragment(savedInstanceState, "characterEditFragment", characterEditFragment);
}
}
CharacterEditFragment.java
public class CharacterEditFragment extends Fragment {
private View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.hello_world, container, false);
return view;
}
}
CharacterMenuFragment.java
public class CharacterMenuFragment extends Fragment {
private View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.hello_world, container, false);
return view;
}
}
content_frame.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="horizontal" >
<FrameLayout
android:id="#+id/menu_frame"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
hello_world.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" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
Try this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_frame);
fragment_manager = getSupportFragmentManager();
if (savedInstanceState != null) {
characterMenuFragment = (CharacterMenuFragment) fragment_manager.getFragment(savedInstanceState, "characterMenuFragment");
characterEditFragment = (CharacterEditFragment) fragment_manager.getFragment(savedInstanceState, "characterEditFragment");
}
if (characterMenuFragment == null) {
Log.i("characterMenuFragment", "making new fragment");
characterMenuFragment = new CharacterMenuFragment();
fragment_manager.beginTransaction().replace(R.id.menu_frame, characterMenuFragment).commit();
} else {
Log.i("characterMenuFragment", "re-using old fragment");
}
if (characterEditFragment == null) {
Log.i("characterEditFragment", "making new fragment");
characterEditFragment = new CharacterEditFragment();
fragment_manager.beginTransaction().replace(R.id.content_frame, characterEditFragment).commit();
} else {
Log.i("characterEditFragment", "re-using old fragment");
}
}
Move the fragment managers into the applicable if statements above. You're just making sure to reuse the existing fragment and only creating one if the fragment doesn't exist.
The issue of many fragments in one activity has been covered here before, but I cannot seem to find a solution for my positioning problem.
I want a horizontal scroll bar on top of the screen and under it a custom ListFragment. The code I am posting below puts up the scroll bar and then the ListFragment overwrites it. When I try to modify the hosting FrameLayout to have two FrameLayouts I get runtime errors.
Simply, How can I position the listFragment under the scrollbar?
public class GoogleNewsMainActivity extends FragmentActivity{
public static Context c;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
c=this;
setContentView(R.layout.activity_fragment);
/* FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
Scroll_Menu_Fragment scrollFragment = new Scroll_Menu_Fragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, scrollFragment)
.commit();
GoogleNewsMainFragment f = new GoogleNewsMainFragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, f)
.commit();
} */
}
}
Here is the scroll bar fragment:
public class Scroll_Menu_Fragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.scrollbar_fragment, container, false);
}
#Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
}
This is the ListFragment
public class GoogleNewsMainFragment extends ListFragment implements LoaderCallbacks<Cursor> {
private static final String COLUMN_ID = "id";
public final static String NEWSFROMSERVICE = "NEWSFROMSERVICE";
static ImageView thumbnail;
static String mSectionSelected;
private NewsCursor mCursor;
private ListView lv;
private NewsCursorAdapter adapter;
public static final String ID = "id";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
mSectionSelected = ""; // until they select one
getLoaderManager().initLoader(0, null, this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_google_news_main, container, false);
getActivity().setTitle(R.string.news_list_title);
return v;
}
And finally the hosting layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentContainer"
android:baselineAligned="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/scrollFragment"
android:layout_width="fill_parent"
android:layout_weight="10"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
class="com.gilchrist.android.googlenews.Scroll_Menu_Fragment" ></fragment>
<fragment
android:id="#+id/listFragment"
android:layout_width="fill_parent"
android:layout_weight="90"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
class="com.gilchrist.android.googlenews.GoogleNewsMainFragment" ></fragment>
</LinearLayout>
I just updated the activity layout. The problem was caused by the weight values I was using. By going to 90 and 10 I got exactly what I wanted. All of the code above now works.
If I try to inflate a view within a fragment I am getting NULL.. For example:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Here I will inflate my view using the layout ID & return.
return view;
}
Whenever a button is clicked I need to create a dynamic view e.g.: button & add to the LinearLayout. I would like to perform this operation inside my fragment class like this:
public void addPlaces() {
Button button = new Button(null);
button.setText("button name");
// e.g. like adding button to enter code here linear layout
linearLayout.addView(button);
}
So, if I get inflate LinearLayout inside onCreateView and use it in add class, I'm getting NULL. How to achieve?
Declare the variable as a instance variable and then initialize Linear Layout
LinearLayout linearLayout;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment1, container, false);
linearLayout = (LinearLayout) rootView.findViewById(R.id.linearlayout);
return rootView;
}
Then
public void addPlaces() {
Button button = new Button(getActivity());
// needs activity context
// fragment hosted by a activity. use getActivity() to get the context of the hosting activity.
button.setText("button name");
linearlayout.addView(button);
}
Example: Modify the below according to your requirement.
fragment1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Button" />
<LinearLayout
android:layout_width="fill_parent"
android:id="#+id/linearlayout"
android:layout_height="fill_parent"
android:layout_above="#+id/button1"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
Myfragment.java
public class Myfragment extends Fragment {
LinearLayout linearLayout;
View rootView;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button b = (Button) rootView.findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
addPlaces();
}
});
linearLayout = (LinearLayout) rootView.findViewById(R.id.linearlayout);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment1, container, false);
return rootView;
}
public void addPlaces() {
Button button = new Button(getActivity()); // needs activity context
button.setText("button name");
linearLayout.addView(button);
}
}
Snap shot of my emulator
Edit :
activity-main.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"
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=".MainActivity" >
<fragment android:name="com.example.fragments.Myfragment"
android:id="#+id/frag"
android:layout_above="#+id/button1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Button" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends FragmentActivity {
Button b;
Myfragment fragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragment = new Myfragment();
fragmentTransaction.add(R.id.frag, fragment);
fragmentTransaction.commit();
b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
fragment.addPlaces();
}
});
}
}
Myfragment.java
public class Myfragment extends Fragment {
LinearLayout linearLayout;
View rootView;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
linearLayout = (LinearLayout) rootView.findViewById(R.id.linearlayout);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment1, container, false);
return rootView;
}
public void addPlaces() {
Button button = new Button(getActivity()); // needs activity context
button.setText("button name");
linearLayout.addView(button);
}
}
My app has a list and detail view, where I allow the user to swipe between the different detail views, using a ViewPager in portrait. In landscape, I show both fragments on the screen.
I'm having an issue where, when the device is rotated, the icons are duplicating themselves over and over in the Actionbar. I've learned that I'm probably creating new fragments whenever the device is rotated and I should be checking if the fragment is in the FragmentManager and then create a new instance if it isn't.
I am able to do that easily using the landscape layout, however, I'm not sure how to check if the fragment exists in portrait mode, using the ViewPager. Do I do that in getItem() of the FragmentStatePagerAdapter?
This is the code I'm using:
public class Main extends SherlockFragmentActivity
{
private static List<Integer> mIds;
#Override
public void onCreate(final Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
mViewPager = (ViewPager)findViewById(R.id.viewpager); //view pager exists, so we are using the portait layout
if (mViewPager != null)
{
mIds = new ArrayList<Integer>();
mIds.add(0);
mIds.add(1);
mIds.add(2);
}
else //in landscape
{
ListFragment lf = (ListFragment)getSupportFragmentManager().findFragmentById(R.id.fragmentList);
if (lf == null)
lf = new ListFragment();
DetailFragment df = (DetailFragment)getSupportFragmentManager().findFragmentById(R.id.fragmentDetail);
if (df == null)
{
df = new DetailFragment();
df.setArguments(getIntent().getExtras());
}
getSupportFragmentManager().beginTransaction().add(R.id.fragmentList, lf).commit();
getSupportFragmentManager().beginTransaction().add(R.id.fragmentDetail, df).commit();
}
}
private static class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
//can't use getSupportFragmentManager().findFragmentById() here because I get a "Cannot make a static reference to the non-static method" error
if (index == 0)
return ListFragment.newInstance();
else
return DetailFragment.newInstance(mIds.get(index-1));
}
#Override
public int getCount() {
return 4;
}
}
}
Main Layout (portrait)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_height="match_parent"
android:layout_width="match_parent"
/>
</RelativeLayout>
Main Layout (landscape)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:weightSum="3"
>
<FrameLayout
android:id="#+id/fragmentList"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="fill_parent"
/>
<FrameLayout
android:id="#+id/fragmentDetail"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="fill_parent"
/>
</LinearLayout>
List Fragment
public class ListFragment extends SherlockListFragment implements DialogKeywordAddListener
{
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public static ListFragment newInstance() {
return new ListFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.listing, container, false);
}
}
Detail Fragment
public class DetailFragment extends SherlockListFragment
{
private int mId;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public static DetailFragment newInstance() {
DetailFragment df = new DetailFragment();
Bundle bundle = new Bundle();
bundle.putInt("id", id);
df.setArguments(bundle);
return df;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
if (getArguments() != null)
mId = getArguments().getInt("id");
return inflater.inflate(R.layout.detail, container, false);
}
}
Well, this question's solution seemed to work for me. Just setting:
super.onCreate(null);
in onCreate of the Activity solved my fragment issue.