I'm quite new to Android dev and I followed the official Android's "Get started".
The fact is, my fragment is not displayed on the main activity ( it worked well few days ago but I changed some lines, I don't remember which ones ). I think it's a very basic problem as I don't use sophisticated fragments : it's basically one fragment inside an activity.
This is my activity :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mysecond.MainActivity"
tools:ignore="MergeRootFrame" />
My fragment :
<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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</RelativeLayout>
And the java code for this activity (I have some other activities in the app, based on the same pattern "one fragment inside one activity" and they work well...)
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container1, new PlaceholderFragment()).commit();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
}
Any ideas ?
Thank you :)
[edit]
so this is my new onCreate method :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction().replace(
R.id.container1, new PlaceholderFragment()).commit();
}
Still not working for this activity (If I add a button in activity_main.xml I'll be able to see it but the I'm not able to see the TextView in the fragment...)
No errors in logcat and yes the activity is launched (I added some Log.e in onCreate and onCreateView and I cas see them)
In your onCreate methode you don't have to check if the savedInstanceState is null but if the the content of the FrameLayout you use is null
Or you simply always replace the fragment with a new one and ommit any checking.
Instead of add, you can use replace.
You can do it like below shown code:
getSupportFragmentManager().beginTransaction().replace(
R.id.container1, new PlaceholderFragment());
For me this work. Implementa a interface FragmentActions with the init() method and use this
private void showFragment(String fragmentTag){
FragmentTransaction trasaction = getSupportFragmentManager().beginTransaction();
FragmentActions fragment = (FragmentActions) getSupportFragmentManager().findFragmentByTag(fragmentTag);
if(fragment==null ){
if(lastFragmentviewed!=null)
trasaction.hide(lastFragmentviewed);
fragment = (FragmentActions) newInstance(fragmentTag);
trasaction.add(R.id.content_frame,(Fragment) fragment,fragmentTag);
}else{
if(lastFragmentviewed!=null && !lastFragmentviewed.equals(fragment))
trasaction.hide(lastFragmentviewed);
if(getSupportFragmentManager().findFragmentByTag(fragmentTag)!=null){
fragment.init();
trasaction.show((Fragment) fragment);
}else
trasaction.add(R.id.content_frame,(Fragment) fragment,fragmentTag);
}
lastFragmentviewed=(Fragment) fragment;
trasaction.commit();
}
Related
This question already has answers here:
android.content.ActivityNotFoundException:
(24 answers)
Closed 4 years ago.
i just want to open SkipActivity from MondayFragment, and fail in error. The swipe between fragments is work, but when i click on skip button move to another Activity- the app is crushed(closed):
All relevant code is attached, please help:
public class MondayFragment extends Fragment {
final String LOG_TAG="myLogs";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragment_monday, container, false);
TextView txt=(TextView) v.findViewById(R.id.skip);
txt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((TextView)getActivity().findViewById(R.id.skip)).setText("Access from Monday Fragment");
//Start your activity here
Intent i = new Intent(getActivity(),SkipActivity.class);
startActivity(i);
}
});
return v;
}
}
This is java Activity class :
public class SkipActivity extends AppCompatActivity {
#Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.after_skip_scr);
}
}
This is MainActivity class - i think there is nothing to change here:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.activity_main);
// Find the view pager that will allow the user to swipe between fragments
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
// Create an adapter that knows which fragment should be shown on each page
SimpleFragmentPagerAdapter adapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager());
// Set the adapter onto the view pager
viewPager.setAdapter(adapter);
}
}
Below is res-layout files: The first one is for monday fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/monday_main"
android:background="#a7cbeb">
<TextView
android:id="#+id/welcome_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_centerInParent="true"
android:textColor="#191970"
android:text="Welcome to Circles"
android:textSize="29sp"
/>
<TextView
android:id="#+id/skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="54px"
android:textStyle="italic"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginRight="25dp"
android:layout_marginTop="25dp"
android:text="skip"
android:textColor="#ffffff"
android:onClick="openSkipActivity"
/>
</RelativeLayout>
And this one is for main activity:
<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"
tools:context="MainActivity">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
you can call activity by :
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(getActivity(), Contact_Developer.class);
getActivity().startActivity(intent);
}
});
why are you take this line
((TextView)getActivity().findViewById(R.id.skip)).setText("Access from Monday Fragment");
and share logcat error log.
or try this
decalare this
Context context;
txt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, SkipActivity.class);
context.startActivity(intent);
}
});
Your app is crashing on click event because your view is null the reason is you are trying to find out the view by using activity.findViewById which will obvious return null.
((TextView)getActivity().findViewById(R.id.skip)).setText("Access from Monday Fragment");
Change above line with this
((TextView)v.findViewById(R.id.skip)).setText("Access from Monday Fragment");
After all you are launching activity from onClick event so doesn't make sense to update the text of skip textview. but if still you want to do that, no problem.
Just replace the above line of code, it should fix your issue.
As a suggestion in case you want to update the skip textview text in on click event or any other place, create a class level instance say TextView skipTextView and initialize in onCreateView then simply use skipTextView.setTex("<text>")" all over the place where ever required.
#Dima , Try this :
public class MondayFragment extends Fragment implements OnClickListener
{
final String LOG_TAG="myLogs";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragment_monday, container, false);
// Views
TextView txt=(TextView) v.findViewById(R.id.skip);
txt.setOnClickListener(this);
return v;
}
// onClick Method
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.skip:
((TextView)getActivity().findViewById(R.id.skip)).setText("Access from Monday Fragment");
Intent i = new Intent(getActivity(),SkipActivity.class);
startActivity(i);
break;
default:
break;
}
}
}
tnx for answers!
The problem was - i didn't declare the SkipActivity in manifest file.
At the moment i did it- the app is running and i can swipe between fragments and launch another Activity from fragment.
tnx a lot!
I am trying to figure out why I am suddenly getting an error when I try to add a fragment.
public class MainActivity extends Activity implements Communicator {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView((int) R.layout.activity_main);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragA, new FragmentA());
//I get errors on each of the adds
ft.commit();
FragmentTransaction ft2 = getFragmentManager().beginTransaction();
ft2.add(R.id.fragB, new FragmentB());
ft2.commit();
FragmentTransaction ft3 = getFragmentManager().beginTransaction();
ft3.add(R.id.fragC, new FragmentC());
ft3.commit();
}
public void respond(String str) {
//I also get an error on the following line
((FragmentB)getFragmentManager().findFragmentById(R.id.fragB)).changeText(str);
}
}
Just using the import of FragmentTransaction, I haven't made my own class.
This is my fragment A code:
public class FragmentA extends Fragment implements OnClickListener {
Button btn;
Communicator comm;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fraga, container, false);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.btn = (Button) getActivity().findViewById(R.id.buttonA);
this.btn.setOnClickListener(this);
this.comm = (Communicator) getActivity();
}
public void onClick(View v) {
this.comm.respond("Hello from Fragment A");
}
}
xml for the activity, I am not a hundred percent sure if this will fix it but would raising the API of the project make any difference at all?
<?xml version="1.0" encoding="utf-8"?>
<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.tannerlangan.week11fragtalk.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#ff83ff3e"
android:id="#+id/fragA"></RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:background="#ff71e7ff"
android:id="#+id/fragB"></RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:background="#ff6d9aff"
android:id="#+id/fragC"></RelativeLayout>
</RelativeLayout>
Your fragments probably using android.support.v4.app.Fragment instead of android.app.Fragment. The quick fix is to change the signature of your fragments to something like this:
public class FragmentA extends android.app.Fragment implements OnClickListener
This is very common with programs that mix the components from support libraries and the non-support one
Try using getSupportFragmentManager() instead of getFragmentManager(). getSupportFragmentManager() is for API<14.
In your project check whether you have imported the same Fragment class in both your FragmentA and MainActivity. You might have imported android.support.v4.app.Fragment in your fragment and in MainActivity you may have imported android.app.Fragment.
If you're minSdk is <14 use fragment, fragmentManager etc from the support library(i.e android.support.v4.app.fragment and same for the fragment manager) else just import the standard fragment class(i.e android.app.Fragment).
P.S : It would be really helpfull if you provide your Error in the question as well.
Solved! Thanks everyone for your help.
I am struggling with Fragments as a concept, and especially seem stuck on this one thing. What I'm trying to do is, using my fragment, manipulate its own layout's data. Every time I try to access an ImageButton from within the Fragment, it crashes the application. It works fine from the activity. Am I just misunderstanding Fragments fundamentally?
Code(cut down for size)-
This is the beginning of the activity my fragment is called from:
Display.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragmentClass MyFragment = new MyFragmentClass();
fragmentTransaction.add(R.id.fragment_container, MyFragment);
fragmentTransaction.commit();
The XML for that Activity:
activity_display.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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.mycompanyname.myprojectname.Display"
android:id="#+id/display_layout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container">
</FrameLayout>
</RelativeLayout>
The Fragment
MyFragmentClass.java
public class MyFragmentClass extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_layout_screen, container, false);;
}
public void MethodTest()
{
}
}
The Fragment's XML file:
fragment_layout_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<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:id="#+id/fragment_layout_screen"
tools:context="com.mycompanyname.myprojectname.MyFragmentClass">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/my_button"
android:clickable="true"
android:onClick="buttonPress"
android:src="#drawable/button"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
Basically I had all of this originally in Display.java, but wanted to add fragments, so I'm trying to move stuff out and into fragments, but I still need the ability to manipulate the xml info, I just can't.
From inside the Display.java activity I can easily call the ImageButton like this:
ImageButton myButton = (ImageButton) findViewById(R.id.my_button)
but if I do the same from MethodTest in the fragment, the app crashes.
I've searched many suggestions on here, trying various solutions from here: findViewById in Fragment but none of those seemed to work.
I've been reading through this for the setup: http://developer.android.com/guide/components/fragments.html and can't seem to find what I'm doing wrong.
Any help would be appreciated, and if you have any questions about my setup, please ask.
declare on fragment private View rootView;
On the onCreateView(...) set rootView = inflater.Inflate(..); and then access the imagebutton as ImageButton mButton =(ImageButton) rootView.findViewById(..);
Do like this in fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.gridview, container, false);
GridView gridview = (GridView) view.findViewById(R.id.grid);
return view ;
I found the template that ADT generates for a Master/Detail Flow Activity to be rather obtuse, and I don't like the fact that the ListView is not declared in a layout file which forces me to work with it programatically. For example, instead of just setting android:background on the ListView in a layout file, I'm forced to find the ListView via findViewById in the fragment's onCreateView(...) method, then call setBackground(...). For maintainability and general readability, I'd like to do the same thing via a layout file.
Instead, I'm trying to inflate a custom layout in the onCreateView method of the "master" fragment:
public class InboxFragment extends ListFragment {
public InboxFragment() {}
private ListView listView = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
listView = (ListView) inflater.inflate(R.layout.inbox_fragment_layout,
null);
return listView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// the following doesn't work
listView.setAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
DummyContent.ITEMS));
// nor does this
//setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),
// android.R.layout.simple_list_item_activated_1,
// android.R.id.text1,
// DummyContent.ITEMS));
}
}
However, calling setListAdapter (or even setAdapter) doesn't seem to do anything, even though I've given the ListView an id of android:id="#id/android:list" in R.layout.inbox_fragment_layout:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#D3D3D3" />
My "master" activity just calls a fragment layout:
public class InboxActivity extends FragmentActivity {
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inbox_phone_layout);
}
}
inbox_phone_layout.xml:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentPhoneInbox"
android:name="com.justin.inbox.InboxFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
Instead, I'm greeted with a blank page and it doesn't look like the ListView is loaded at all. What am I doing wrong, here? Sample project on GitHub.
I fixed your issue by changing inbox_phone_layout.xml to the following:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentPhoneInbox"
android:name="com.justin.inbox.InboxFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I decided to switch from multiple activities to one activity which switches between fragments however the application now crashes.
Here is the activity I am adding the fragment to
public class MainActivity extends SherlockFragmentActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyFragment fragment = new MyFragment();
fragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, fragment).commit();
}
Here is the fragment its an observer and has functionality but to save space ill just show the creation
public class MyFragment extends SherlockFragment implements Observer{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.my_fragment, container, false);
}
Heres my_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
... HAS SOME TEXT VIEWS HERE!
</RelativeLayout>
The crash I get is
02-15 16:17:41.079: E/AndroidRuntime(18668): FATAL EXCEPTION: main
02-15 16:17:41.079: E/AndroidRuntime(18668): java.lang.RuntimeException:
Unable to start activity ComponentInfo{com.example.myapp/com.example.myapp.MainActivity}:
java.lang.IllegalArgumentException:
No view found for id 0x7f040036 for fragment MyFragmentt{41a05910 #0 id=0x7f040036}
Can anyone help me out here? I can't really figure out what is causing this. I know if I comment out getSupportFragmentManager() in main activity (the top code block in this post) it will run just not draw anything in my fragment.
UPDATE
The frame_container which I'm not sure where to place
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
So the way you can use Fragments in your applications are two.
First way is if you declare the Fragment in your xml file like this :
<fragment android:name="com.example.news.ArticleReaderFragment"
android:id="#+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
The second way is if you add / replace your Fragments dynamically to your container which in the most examples is FrameLayout. Here is how you can do that :
In your main FragmentActivity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myFragmentContainer);
}
and in your xml myFragmentContainer.xml is where you place your fragment_container and it looks like :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
and you are adding and replacing your Fragments like this :
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
// Create an instance of ExampleFragment
HeadlinesFragment firstFragment = new HeadlinesFragment();
// if there are any extras
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
and for the next Fragment which you want to show just do :
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, secondFragment).commit();