fragmentactivity with custom surfaceview - android

i'm programming an android game and therefore im using a class that extends surfaceview.
My Activity looks like this:
public class GameActivity extends FragmentActivity {
private Fragment fragEnd;
private GameView gameView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new GameView(this);
setContentView(gameView);
fragEnd = (FragmentEnd) Fragment.instantiate(this, FragmentEnd.class.getName(), null);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add( WHAR COMES IN HERE??? , fragEnd);
ft.commit();
}
...
The GameView class extends the surfaceview.
My activity_game.xml layout file looks like this:
<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"
tools:context=".GameActivity"
android:id="#+id/myView">
</RelativeLayout>
So there is nothing special defined in my xml.
Now i want to use fragments in the game for options etc. I read some tutorials and added the components to my (Fragment)Activity. But i recieve an IllegalArgumentException: "no view found" while trying to create the fragment. i know that the problem is, that the current view (Surfaceview) cannot be found. in the tutorials, they only worked with layout xmls like writing:
setContentView(R.layout.activity_main);
And then get the component (for example the Relativelayout id "relativeLayoutView") of the activity_main to define the
ft.add( R.id.relativeLayoutView , fragEnd);
But in my case there is nothing in my activity_main because all happens ins the gameView-class.
How do i solve this to display fragments?

Create a layout like this and set to the activity .. Also add an interface in GameView and implement the interface in activity. when you show some thing in fragment , call the interface method from GameView and add the fragment into the activity using R.id.container or other approach is to show the options as dialog.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.examples.workapp.app.GameView
android:id="#+id/gameView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="200dp">
</FrameLayout>
</LinearLayout>

Related

fragment not shown on top in activity

i want to show a fragment when i click a item into my action bar, in code i do that:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.create_boundary:
Fragment boundary = new BoundaryFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.map_activity, boundary);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
break;
}
}
and the fragment:
public class BoundaryFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// create the view of the fragment associate with the maps activity
View view = inflater.inflate(R.layout.boundary_maps, container, false);
return view;
}
fragment's layout:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</GridLayout>
activity_map.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map_activity"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
</RelativeLayout>
onCreate of mapsActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
[...]
}
i don't understand why is not shown.Can someone tell me what's is wrong?
thanks in advance.
As stated in the official documentation for FragmentTransaction.replace(int,Fragment,String):
Parameters
- containerViewId Identifier of the container whose
fragment(s) are to be replaced.
- fragment The new fragment to place in
the container.
- tag Optional tag name for the fragment, to later
retrieve the fragment with FragmentManager.findFragmentByTag(String).
That means you are using the id in the transaction incorrectly. Also you may want to add the BoundaryFragment on top of the one defined in the XML layout, therefore you should use FragmentTrasaction.add(int, Fragment) instead.
To fix your problem anyway you should move your id to the RelativeLayout, as below:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map_activity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
</RelativeLayout>
First, you are using a Fragment as it would be a ViewGroup. You’re trying to place a Fragment inside another Fragment when you perform the next statement:
ft.replace(R.id.map_activity, boundary);
Second, you can’t replace a fragment that has been defined in the layout file. You can only replace fragments that you added dynamically using FragmentTransaction.
To achieve what you want, take a look at the sample code under the section:
"Or, programmatically add the fragment to an existing ViewGroup."

NullPointerException when using setText to set TextView (defined after setContentView(); object exits in .xml file)

I have checked the posts. And here is the checklist of what I have tried
Make sure that a TextView by that name exists
That all functions are called after setContentView() in onCreate()
It still continues to baffle me. Your help your be appreciated
Please note that this activity (for which the code is given) is trigger from a parent (as given in the Android Manifest snippet below).
The java code for the activity is: (This code has been changed to simplify the question)
public class MainActivity extends ActionBarActivity {
private TextView tDummy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tDummy=(TextView)findViewById(R.id.textViewDummy);
tDummy.setText("Testing.");
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
...
public void changeMsg(View view){
TextView dummy=(TextView)findViewById(R.id.textViewDummy);
dummy.setText("Changed!");
}
Why am I still getting a null pointer exception?!
It works fine when I click the button (which invokes the changeMsg function), but that just circumvents the problem.
I am using android studio.
XML file
(There are two: activity_main.xml and fragment_main.xml)
fragment_main.xml is as follows:
<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="mk.app.MainActivity$PlaceholderFragment">
<TextView
android:text="#string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textViewDummy" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textViewDummy"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="42dp"
android:layout_marginTop="26dp"
android:onClick="changeMsg"/>
</RelativeLayout>
main_activity.xml is:
<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="mk.app.MainActivity"
tools:ignore="MergeRootFrame" />
Could it be an issue with having using the fragment layout?
As the content is set to activity_main, but the definitions are in fragment_main.xml??
Just so this question has an answer, you need to make sure that your variables get defined in the layout that you have set in your onCreate method, in this case setContentView(R.layout.activity_main.xml); Since you have set your activity_main.xml as your content view for your Activity, you need to make sure that layout actually contains the views and id's you are trying to use. All you need to do is move the code from your fragment layout to your main layout and vice versa. Reason being, if a particular layout is not set as your content view, the content from that layout hasn't actually been loaded into your Activity to be referenced to.
If you are really intent on using the fragment, simply change this:
tDummy=(TextView)findViewById(R.id.textViewDummy);
tDummy.setText("Testing.");
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
to
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
tDummy=(TextView)findViewById(R.id.textViewDummy);
tDummy.setText("Testing.");
And it should work, since now your fragment has been loaded into your container

Fragment depending on another fragment in android

I am very new to Android programming. Following is what I am doing:
I have an EditTextBox. And when it is in focus I would want to display a custom number pad. To implement this, following are the code snippets:
layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_twopane"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"/>
<FrameLayout android:id="#+id/keyPadFragmentContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
In the Fragment class, defined a Callbacks interface which the parent activity has to implement
public interface Callbacks {
void onAnswerEditTextSelected(Fragment fragment);
}
Added a listener to the EditText
mAnswerEditText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!mNumberPadShown) {
mCallbacks.onAnswerEditTextSelected(QuizFragment.this);
}
});
In the Parent activity, I have the following:
#Override
public void onAnswerEditTextSelected(Fragment fragment) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment numFragment = NumberPadFragment.newInstance(fragment);
ft.add(R.id.keyPadFragmentContainer, numFragment);
ft.commit();
}
At runtime I get No view found for id 0x7f ...(classname:id/keyPadFragmentContainer) for fragment NumberPadFragment. Can you please tell me where I am going wrong.
Thank you
if it's just numbers that you need, there is already a way to do it without any customization . it's called inputType.
it can be done either in XML or programmatically.
example :
<EditText android:inputType="number" android:digits="0123456789."
.../>
for more buttons, you can create a custom keyboard, as shown here:
http://www.fampennings.nl/maarten/android/09keyboard/index.htm
http://tutorials-android.blogspot.co.il/2011/06/create-your-own-custom-keyboard-for.html
https://stackoverflow.com/a/14676866/878126
i'm pretty sure the API demos have a sample for it too.

Fragment not re-added after orientation change

The Fragments in my app are not re-added to the activity's view when the device is rotated. If i understand the documentation (and similar questions here on SO) correctly, this should be handled be the fragment manager (without having to specify android:configChanges in my manifest).
My Activity looks like:
public class MainActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null){
getSupportFragmentManager().beginTransaction()
.add(R.id.main_fragment_placeholder, new DashboardFragment(),"dashboard")
.commit();
}
}
}
And a Fragment looks like (omitted clicklisteners and so on for clarity):
public class DashboardFragment extends SherlockFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_dashboard, container, false);
}
}
The layout files look like (activity_main.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/main.main">
<FrameLayout android:id="#+id/main_fragment_placeholder"
android:layout_height="fill_parent"
android:layout_weight="1"
android:layout_width="0px"
/>
</LinearLayout>
And fragment_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main.wrapper"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<my.layout.DashboardLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/main.dashboard">
<!-- some buttons here -->
</my.layout.DashboardLayout>
</LinearLayout>
However, when i rotate my device the screen always becomes blank.
Turns out I did a Stupid Thing. I overrode the onSaveInstanceState(...) method in my activity, without calling super.onSaveInstanceState(), which resulted in the fragments not being recreated. Posting the answer here in hopes that I can save somebody else the time!
Fragments usually get recreated on configuration change. If you don't wish this to happen, use
setRetainInstance(true); in the Fragment's constructor(s)
This will cause fragments to be retained during configuration change.
http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)

Android: Change Background Color of Fragment

I tried changing the background color of a fragment, but a small problem occurred.
public class MainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
So, shown above is the code I had for my main class that calls the XML file for the fragment.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
android:id="#+id/fragment1"
android:name="com.northreal.practice.FirstFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#CBA" />
</LinearLayout>
Above is the main.xml layout that is called by the main class (MainActivity).
public class FirstFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.main, parent, false);
}
}
Above the XML file with the fragment calls this class.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BLAHHHH"
android:layout_gravity="center_vertical" />
</LinearLayout>
This layout above is inflated by the class FirstFragment
So, why doesn't this actually change the color of the background of my fragment?
Fragments don't inherit from View and thus don't have a set background method.
Any easy fix is to just grab the root view of fragment and set its background
fragment.getView().setBackgroundColor(Color.WHITE);
The reason why that doesn't work is because fragment is treated similar to an activity. It is a container that is the child of the main activity, and is used to display other items.
You need to put the android:background="#CBA" in the actual layout that holds the TextView and NOT the fragment itself.
Like so:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#CBA"
android:orientation="horizontal" >
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="BLAHHHH" />
</LinearLayout>
Get the fragment object like:
Fragment fragment = (Fragment) getFragmentManager().findFragmentById(R.id.fragmentId);
Change it's background like:
fragment.getView().setBackgroundColor(Color.WHITE);
In AndroidX you can use a FragmentContainerView instead of a Fragment to set a background:
<androidx.fragment.app.FragmentContainerView
...
android:background="#FFFFFF"/>
I have faced the same problem but my requirement was to set or change background drawable image of fragment. As Adam answered the approach is right and I would like to show the connection from fragment to activity.
The best practice is to use an interface named 'Connector'(or any name).Then from your fragment:
Connector connector = (Connector) getActivity();
connector.setIt(this);
Then in your activity which will implement 'Connector' interface and have the method.
#Override
public void setIt(Fragment fragment){
FirstFragment firstFrag = (FirstFragment) getSupportFragmentManager().findFragmentByTag("first");
firstFrag.getView().setBackgroundDrawable(getResources().getDrawable(R.drawable.app_background));
//or for color set
firstFrag.getView().setBackgroundColor(Color.WHITE);
}

Categories

Resources