The following is running on an Android 1.6 so I'm using the compatibility package for fragments. In the following TestFragment is a static nested class:
public class FragmentTestActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public static class TestFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView result = new TextView(getActivity());
result.setText("Hello TestFragment");
return result;
}
}
}
The main.xml file:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<fragment class="com.test.FragmentTestActivity$TestFragment"
android:id="#+id/test"
android:layout_width="fill_parent" android:layout_height="fill_parent" />
</FrameLayout>
The strange thing is that the container parameter in onCreateView is null.
Now, if I add the fragment programatically like so(just change the onCreate method of the Activity) the container is no longer null. Why?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fragment frag = new TestFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
}
The documentation mentions that it can be null:
public View
onCreateView(LayoutInflater
inflater, ViewGroup container, Bundle savedInstanceState)
[...]
container: If non-null, this is the parent view that the
fragment's UI should be attached to. The fragment should not add the
view itself, but this can be used to generate the LayoutParams of the
view.
To be clear: you shouldn't do anything like container.addView(...).
Related
I know that to show a list of views I can use recycler view with but what if I wanna reuse also my fragment logic too?
for example, if I have a fragment like this
XML
<androidx.constraintlayout.widget.ConstraintLayout 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=".views.fragments.testview">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="hi"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment class
public class TestView extends Fragment {
private TextView txt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.test, container, false);
initComponent(v);
return v;
}
private void hardTask1(){};
private void hardTask2(){};
//Some other hardtask
}
What I could do if I need to display a list of fragments in some activity but I don't want to rewrite all my TestView in the adapter?
Trying to add Fragment to my Activity, but it isn't showing up.
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WeatherFragment mainFragment = new WeatherFragment();
getFragmentManager()
.beginTransaction()
.add(R.id.main_weather_container, mainFragment)
.commit();
}
}
And there is my fragment:
public class WeatherFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
boolean isAttachedToParent = false;
View inflatedView = inflater.inflate(R.layout.main_weather_fragment, container, isAttachedToParent);
return inflatedView;
}
}
R.id.main_weather_container - FrameLayout in my MainActivity.
R.layout.main_weather_fragment - Fragment's layout
What am i doing wrong?
I've tried to use FragmentActivity + v4 support fragment and fragmentSupportManager, but it didn't make any difference.
MainActivity xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical">
<FrameLayout
android:id="#+id/main_weather_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="#dimen/padding_16_dp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/words_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" />
</LinearLayout>
UPDATED: The problem wasn't in fragment transaction or whatever, i've used tools: namespace that's why fragment wasn't displayed. Sorry about that :(
try this way .in your activity call fragment
Fragment fragment = Video_fragment.newInstance();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.framecontainer, fragment).commit();
in fragment class.
public class Video_fragment extends Fragment{
View view;
public static Fragment newInstance() {
Video_fragment fragment = new Video_fragment();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view= inflater.inflate(R.layout.video_frag, container, false);
return view;
}
}
Create a instance of Fragment in WeatherFragment:
public static WeatherFragment newInstance() {
Bundle args = new Bundle();
WeatherFragment weatherFragment = new WeatherFragment();
weatherFragment.setArguments(args);
return weatherFragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_layout, container, false);
}
Inside your Activity in MainActivity :
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WeatherFragment weatherFragment = WeatherFragment.newInstance();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.flContainerId, weatherFragment)
.commit();
}
Your layout file will be:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/flContainerId"/>
public class WeatherFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View inflatedView = inflater.inflate(R.layout.main_weather_fragment, null, false);
return inflatedView;
}
}
As I can see, you are using AppCompatActivity but using getFragmentManager.
With AppCompatActivity you will need to use getSupportFragmentManager() rather than getFragmentManager()
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WeatherFragment mainFragment = new WeatherFragment();
getSupportFragmentManager()
.beginTransaction()
.add(R.id.main_weather_container, mainFragment)
.commit();
}
}
Your WeatherFragment should be extend android.support.v4.app.Fragment;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:weightSum="4"
android:orientation="vertical">
<FrameLayout
android:id="#+id/main_weather_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="#dimen/padding_16_dp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/words_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" />
</LinearLayout>
Added WeightSum in the parent Layout.
I am new to the android platform so I know I am just missing something by here is what I have
<!-- activity_main -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.example_app.MainActivity"
tools:ignore="MergeRootFrame" >
<fragment
android:id="#+id/mainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.example.example_app.MainFragment"
/>
</FrameLayout>
Then I created a fragment called MainFragment.java.
public class MainFragment extends Fragment {
public TextView displayTextView;
public MainFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
this.displayTextView = (TextView)rootView.findViewById(R.id.displayTextView);
return rootView;
}
}
I add the fragment in the OnCreate function in the activity and it seems to be adding everything okay but when I click on the button nothing happens, I logged the function to see its being called but setting the textview doesn't do anything. What am I doing wrong?
<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.example.example_app.MainActivity$PlaceholderFragment" >
<Button
android:id="#+id/button10"
android:textColor="#ffffff"
android:textSize="34dp"
android:text="10%"
android:layout_below="#id/amountEditText"
android:background="#drawable/pct_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="doSomething"
/>
<TextView
android:text="Blah Blah Blah"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/displayTextView"
></TextView>
</RelativeLayout>
And here is the click Event in the MainActivity.java
public void doSomething(View v) {
this.mainFragment.displayTextView.setText("Nothing to set for some reason!");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
//
this.mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.mainFragment);
mainFragment = new MainFragment();
getSupportFragmentManager().beginTransaction().add(mainFragment, "mainFragment").commit();
}
}
Declaring onClick-Listeners via XML is possible if you work with Activities. According to the Google API, however, you need to declare OnClickListeners programmatically if you use Fragments.
[...] You can also declare the click event handler programmatically rather than in an XML layout. This might be necessary if you instantiate the Button at runtime or you need to declare the click behavior in a Fragment subclass.
Source:
http://developer.android.com/guide/topics/ui/controls/button.html
So you may want to use this instead:
public class MainFragment extends Fragment {
public TextView displayTextView;
public Button yourButton;
public MainFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
this.displayTextView = (TextView)rootView.findViewById(R.id.displayTextView);
yourButton = (Button)rootView.findViewById(R.id.button10);
yourButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
displayTextView.setText("Nothing to set for some reason!");
}
});
return rootView;
}
}
The problem is the way you try to execute the button click. From your question i understand that Button and TextView is in Fragment view. So do why are Trying to access it in activity ?? It is wrong, then there is no point of using Fragments. Also this will lead to many serious issues later .
Fragments are Reusable components so all the functionalities of a fragment must stay inside the Fragment Class
Change Fragment code :
public class MainFragment extends Fragment {
public TextView displayTextView;
public Button yourButton;
public MainFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
this.displayTextView = (TextView)rootView.findViewById(R.id.displayTextView);
yourButton = (Button)rootView.findViewById(R.id.button10);
//Setting click listener for button in fragment
yourButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
displayTextView.setText("Nothing to set for some reason!");
}
});
return rootView;
}
}
and remove android:onClick="doSomething" from XML
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.
I have a problem with ViewPager. It won't display any of my pre-definied fragments, it just displays a black screen. The onCreateView method is called from inside the fragments.
public class TestViewPager extends FragmentActivity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.test_view_pager);
}
}
public class TestFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.entry_layout, container, false);
return fragmentView;
}
}
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
class="com.test.TestFragment"
android:id="#+id/embedded1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<fragment
class="com.test.AnotherTestfragment"
android:id="#+id/embedded2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.view.ViewPager>
With ViewPager you must implement a PagerAdapter and supply the fragments from there. You can not define views/fragments to be shown in the ViewPager from XML, as it will simply not draw them.
Edit: Since you want to show Fragments, you must use FragmentPagerAdapter.