How to create a fragment of an activity in android studio? - android

I want to call a new activity when a list item is clicked from the drawer. I searched over the internet and what I got was to call the fragment of that activity. So, I wanted to know how to make a fragment of an activity.
P.S.- Sorry, if this question is silly. I'm still a noob.

A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. Here the full explanation from android official developer guide.
Also on android developer guide you can find the code to properly create and use a fragment.
Create a fragment class:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.ViewGroup;
public class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_view, container, false);
}
}
Then you have to add the fragment to the activity layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment android:name="com.example.android.fragments.HeadlinesFragment"
android:id="#+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="com.example.android.fragments.ExampleFragment"
android:id="#+id/example_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
Finally you can add the layout to your activity:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.item_from_exampleLayout);
}
}
I took those examples from the android developer guide that i put above.
Anyway if i have understood your question this code should work:
list.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Intent intent = new Intent(ThisClass.this, ClassToCall.class);
startActivity(intent);
}
});
This will start a new activity when a list item is clicked using an intent, but it doesn't need fragments.

Related

Can I limit findViewById() to within the scope of an individual fragment?

In my application, I have multiple instances of the same fragment, Activity_Fragment, displayed in a LinearLayout. In each fragment, there is an activity_text textview and an edit_button. When the button is pressed in a fragment, it should change the text of the textview in the same fragment. However, when multiple instances of the fragment are added, any edit_button pressed in any fragment will only change the activity_text textview in the first fragment added to the LinearLayout. This is because all fragments are identical, and their child views share the same id's. Each fragment should act independently of one other; any edit_button pressed in a fragment should only affect that fragment.
Is it possible to have the findViewById() method limited to the scope of an individual fragment so that one fragment won't be affected by an event in another fragment, or will I have to somehow change the id of each view in a fragment upon creation?
Here is the Activity Fragment xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="wrap_content"
android:id="#+id/activity_fragment">
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/activity_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="Edit Activity"
android:textSize="18sp"
app:layout_constraintBaseline_toBaselineOf="#+id/checkbox"
app:layout_constraintLeft_toRightOf="#+id/checkbox"
app:layout_constraintRight_toLeftOf="#+id/edit_button"/>
<Button
android:id="#+id/edit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"
android:onClick="editActivity"
android:text="Edit Activity"
app:layout_constraintBaseline_toBaselineOf="#+id/checkbox"
app:layout_constraintRight_toRightOf="parent"/>
Here is my MainActivity.java with the ActivityFragment class. The onClick method for the edit_button is at the very bottom:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static class ActivityFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.activity_fragment, container,
false);
}
}
public void addActivity(View view) {
ActivityFragment fragment1 = new ActivityFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, fragment1).commit();
}
//This is the editButton method
public void editActivity(View view) {
TextView activityText = (TextView) findViewById(R.id.activity_text);
activityText.setText("success");
}
}
Your problem can be solved by limiting the scope that findViewById() scans. If you want to look within a particular fragment, you'll probably want to call myFragment.getView().findViewById() (rather than just using findViewById() from your activity).
So how can you do this? Well, it's not easy with the way you have things set up. Since you're using the android:onClick attribute to set your click listener, you have to handle things from inside the activity.
So don't use android:onClick.
Instead, inside your Fragment's onCreateView() method, write something like this:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.your_fragment, container, false);
Button button = (Button) root.findViewById(R.id.edit_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView activityText = (TextView) getView().findViewById(R.id.activity_text);
activityText.setText("success");
}
});
return root;
}
you can use view.findViewById(R.id.activity_text) instead of the method from the activity.

How to show empty text in list fragment?

I am using Google Place API to find nearest places. I am displaying map and list on two tabs. I have made two fragments. In one i am showing map and in second one i am using list. I have used an editext box on actionbar. When i am running my app it is crashing and giving nullpointer exception at setListAdapter.
It is my ListFragment file
import android.support.v4.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.aquib.android.place.Place;
import com.aquib.android.place.PlaceAdapter;
import com.aquib.android.place.R;
import java.util.List;
/**
* Created by dell on 2/9/2015.
*/
public class ListItemFragment extends ListFragment{
private PlaceAdapter adapter;
List<Place> placeList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, null);
TextView emptyTextView = (TextView) view.findViewById(android.R.id.empty);
emptyTextView.setTextSize(10);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
adapter = new PlaceAdapter(getActivity(), placeList);
setListAdapter(adapter);
}
}
and my fragment_list.xml file
<?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">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#android:id/list" />
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="No data"/>
</LinearLayout>
When i will give input in edittext box and call place api and then parse json data. I have written Place class and then add place object in list. so please someone tell me that how to display empty text. app is showing exception in arrayadapter.getCount() method.
Your placeList is never initialized.
Moreover, in onCreateView(), you should probably create your view like this:
View view = inflater.inflate(R.layout.fragment_list, container, false);

Nested Fragments (multi-pane in tab)

i have problems to use a fragment in a fragment. The first fragment is a tab view an in one tab i want to have a multi-pane Layout like this:
The error is:
android.view.InflateException: Binary XML file line #8: Error
inflating class fragment
The tab fragment (SettingsFragmentBox):
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SettingsFragmentBox extends Fragment implements SettingsFragmentBoxList.OnItemSelectedListener{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_settings_box, container, false);
return rootView;
}
public void onBoxSelect(int id) {
SettingsFragmentBoxDetail fragment = (SettingsFragmentBoxDetail) getFragmentManager().findFragmentById(R.id.box_detail);
if (fragment != null && fragment.isInLayout()) {
fragment.setText(id);
} else {
Intent intent = new Intent(getActivity(),SettingsActivityBoxDetail.class);
intent.putExtra(SettingsActivityBoxDetail.EXTRA_ID, id);
startActivity(intent);
}
}
}
The xml (fragment_settings_box.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="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:id="#+id/box_list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
class="de.resper.e2cast.SettingsFragmentBoxList"
tools:layout="#layout/fragment_settings_box_list">
</fragment>
<fragment
android:id="#+id/box_detail"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
class="de.resper.e2cast.SettingsFragmentBoxDetail"
tools:layout="#layout/fragment_settings_box_detail">
</fragment>
</LinearLayout>
Usually this is done using fragments in ACTIVITIES, not in other fragments. Are you sure you really want fragments in other fragments ?
The picture you are referring to is by the way showing this scenario (ACTIVITIES contain fragment A or B).
You should read http://developer.android.com/training/multiscreen/screensizes.html to handle different screensizes. There is an example with a layout containt two fragments in it. Also learn how to adapt to it by reading this http://developer.android.com/training/multiscreen/adaptui.html

Can a fragment switch from Dialog to Embedded on rotation?

So, I have a Search Criteria Fragment, where search criteria can be entered, and when the search is performed, the results of the search are shown in a Search Results Fragment. In landscape on a tablet, the two fragments naturally can be displayed side by side. This is straightforward to implement so far.
In portrait orientation, and on a phone, I'd like the Search Criteria fragment to be displayed like a popup dialog instead of beside the search results. In the Selecting Between Dialog or Embedding section of the DialogFragment, I see that I can either embed the fragment, or show it as a dialog. This might work for me if it weren't complicated by orientation changes.
If I am using <fragment> XML tags in the layout for the activity, I get into all sorts of trouble when I make orientation changes.
EDIT: Today I decided to try and see if I could get a simple workflow using a DialogFragment toggling between showing a dialog and embedded depending on the orientation of the device. This turns out to be quite difficult, and I still haven't found something that works. Here's what I have so far.
package org.nsdev.experiments;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class FragmentSearchTestActivity extends FragmentActivity
{
private static SearchCriteriaFragment searchCriteriaFragment;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
View container = findViewById(R.id.search_criteria_container);
android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (searchCriteriaFragment == null)
{
searchCriteriaFragment = SearchCriteriaFragment.newInstance();
searchCriteriaFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0);
}
android.support.v4.app.Fragment f = getSupportFragmentManager().findFragmentByTag("search_criteria");
if (f != null)
{
ft.remove(f);
}
if (container == null)
{
searchCriteriaFragment.setCancelable(true);
searchCriteriaFragment.setHasOptionsMenu(false);
searchCriteriaFragment.show(getSupportFragmentManager(), "search_criteria");
}
else
{
ft.remove(searchCriteriaFragment);
ft.add(R.id.search_criteria_container, searchCriteriaFragment, "search_criteria");
ft.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
if (item.getItemId() == R.id.menu_item_search)
{
searchCriteriaFragment.show(getSupportFragmentManager(), "search_criteria");
}
return super.onOptionsItemSelected(item);
}
}
Specifically I was unable to get anything working unless I kept a static copy of the SearchCriteriaFragment and reused it whenever onCreate was called in the Activity. This seems very wrong to me.
SearchResultsFragment.java:
package org.nsdev.experiments;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SearchResultsFragment extends android.support.v4.app.Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.results, container);
}
}
SearchCriteriaFragment.java:
package org.nsdev.experiments;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SearchCriteriaFragment extends android.support.v4.app.DialogFragment
{
private static final String TAG = "SearchCriteriaFragment";
View v;
static SearchCriteriaFragment newInstance()
{
Log.e(TAG, "newInstance");
SearchCriteriaFragment d = new SearchCriteriaFragment();
return d;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if (v == null)
{
v = inflater.inflate(R.layout.criteria, container, false);
}
else
{
if (v.getParent() instanceof ViewGroup)
{
Log.e(TAG, "Removing from viewgroup");
((ViewGroup)v.getParent()).removeAllViews();
}
}
return v;
}
}
You can see, here, that I had to work around a problem with the view being reused. There was an error stating that the view already had a parent and would need to be removed from it before it could be added to another parent. Again, this seems like I must be doing it the wrong way.
res/layout/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:id="#+id/search_results"
android:name="org.nsdev.experiments.SearchResultsFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
res/layout-land/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/search_criteria_container"
android:layout_width="wrap_content"
android:layout_height="fill_parent" />
<fragment
android:id="#+id/search_results"
android:layout_toRightOf="#+id/search_criteria_container"
android:name="org.nsdev.experiments.SearchResultsFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
You can see from these two layouts, what I am trying to do. In the normal orientation, the FrameLayout doesn't exist, so we can detect this and show the DialogFragment instead. Otherwise, we can embed the DialogFragment into the FrameLayout.
The final two layouts I've just put placeholders in for the results and criteria layouts:
res/layout/criteria.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" android:background="#300F">
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="21dp"
android:paddingRight="30dp"
android:text="Test Criteria" />
</RelativeLayout>
res/layout/results.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" android:background="#f00">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:text="Results"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
I thought I had figured it out until I started rotating the device and checking the checkbox on an ICS device. Notice that I've set the color to be semi-transparent for the criteria.xml RelativeLayout background. What I noticed was that in landscape orientation, the embedded view was actually keeping old versions of the view around, and these would be overlaid with newer copies of the view each time I switched to portrait and back again. That's one of the reasons I tried to keep only one copy of the view returned in from the onCreateView of the SeachCriteriaFragment. This does not fix this problem.
I can only come to one conclusion: I must be doing this wrong. I suspect that the Fragments framework was never designed to do this kind of fragment reuse. How can I get a nice rotation working where in Portrait I show the DialogFragment as a dialog, and in Landscape it is embedded? Can I get the framework to do something like this more automatically?
I tried setting searchCriteriaFragment.setRetainInstance(true) and all hell broke loose, so I deleted that line immediately.
Thanks for any help getting me on the right track here.
I would say this.
On the phone make the SearchFormFragment an Activity and give it the theme Dialog.
Then the SearchResultsFragment is also a separate Activity on it's own.
The SearchForm xml would look like:
<LinearLayout >
<fragment class="com.your.package.ui.fragment.SearchFormFragment" />
</LinearLayout>
To get the Dialog theme:
<manifest . . . >
<application . . . >
<activity
android:name=".ui.phone.SearchFormFragmentActivity"
android:theme="#android:style/Theme.Dialog" . . . >
<activity
android:name=".ui.phone.SearchResultsFragmentActivity" . . . >
This makes orientation change simple using onSaveInstanceState and onRestoreInstanceState and the activity lifecycle.
Then on the tablet you have another activity with your two fragments in.
<activity
android:name=".ui.tablet.SearchFragmentActivity" . . . >
SearchFragmentActivity.xml:
<LinearLayout >
<fragment class="com.your.pacakage.ui.fragment.SearchFormFragment"/>
<fragment class="com.your.package.ui.fragment.SearchResultsFragment" />
</LinearLayout>
Simplified.

Difficulties with basic fragment layout

I'm trying to get my head around fragments in order to have my apps prepped for ICS.
I have the following files to just get the most basic fragment app you can have. It should have this when launched: One Fragment Layout with a text view "Fragment 1" and next to it another Fragment Layout with "Fragment2".
My package name is com.mwerner.fragments
My files are:
FragmentsActivity.java
ExamplesFragment.java
ExamplesFragment2.java
examples_fragment.xml
examples_fragment2.xml
main.xml
The code for FragmentsActivity.java is:
package com.mwerner.fragments;
import android.app.Activity;
import android.os.Bundle;
public class FragmentsActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
ExamplesFragment.java
package com.mwerner.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ExamplesFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.examples_fragment, container, false);
}
}
ExamplesFragment2.java
package com.mwerner.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ExamplesFragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.examples_fragment2, container, false);
}
}
The examples_fragment.xml files just have a linear layout with a textview in it...
Here is the code for the main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<fragment
class="com.mwerner.fragments$ExamplesFragment"
android:id="#+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="fill_parent"
/>
<fragment
class="com.mwerner.fragments$ExamplesFragment2"
android:id="#+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="fill_parent" />
</LinearLayout>
The app crashes on startup with the error
11-07 18:12:12.519: E/AndroidRuntime(696): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mwerner.fragments/com.mwerner.fragments.FragmentsActivity}: android.view.InflateException: Binary XML file line #7: Error inflating class fragment
Can you please tell me what is wrong here? I pretty much copied / pasted the code from the google developers page for fragments.
You defined the path to your fragments incorrectly in your layout xml. Correct the class attributes. Try this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<fragment
class="com.mwerner.fragments.ExamplesFragment"
android:id="#+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="fill_parent"
/>
<fragment
class="com.mwerner.fragments.ExamplesFragment2"
android:id="#+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="fill_parent" />
</LinearLayout>
Try extending FragmentActivity
public class FragmentsActivity extends FragmentActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
When I was writing my first program on Fragments using I incurred same error. Instead of extending "Activity" extend "FragmentActivity" in your launcher activity.

Categories

Resources