Search code examples
androidandroid-fragmentssurfaceviewsetcontentview

Add fragment to underlying SurfaceView


How do I add a fragment to an underlying SurfaceView? I get the exception

java.lang.IllegalArgumentException: No view found for id 0x7f0b0050

I think this is due to not setting any layout in the setContentView such as

setContentView(R.layout.activity_main);

instead I set a reference to a custom surfaceview ...

final GameSurface gs = new GameSurface(this);
setContentView(gs);

Then in the surfaceview callback ontouch(...) - a fragment is supposed to load if the user clicks on the surface

@Override
public boolean onTouchEvent(MotionEvent event) {

 .....

        FragmentManager fragmentManager =((Activity)context).getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        ExchangeFragment fragment = new ExchangeFragment();
        fragmentTransaction.add(R.id.relLayout, fragment);
        fragmentTransaction.commit();

thanks in advance

Edit:

No crash any longer but the fragment wont show up. why? Thanks to @Kelevandos and the answer at another stack-thread

How to inflate one view with a layout

That is, I hade to add AttributSet to the custom surfaceViews constructor.

What is missing? Here is the xml-file

<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"
>


   <se.brickgame.brickbreaker.GameSurface

        android:id="@+id/surfaceId"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />

   <RelativeLayout

        android:id="@+id/relLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
    >
   </RelativeLayout>

edit 2:

I also added this to the code

 fragmentManager.executePendingTransactions();
 System.out.println("FRAGMENT ISADDED = " + fragment.isAdded());
 System.out.println("FRAGMENT VISIBLE = " + fragment.isVisible());
 System.out.println("FRAGMENT HIDDEN = " + fragment.isHidden());
 System.out.println("FRAGMENT ISINLAYOUT = " + fragment.isInLayout());

and got the following output

11-25 16:09:07.957 12155-12155/se.brickgame.brickbreaker ISystem.out: FRAGMENT ISADDED = true
11-25 16:09:07.957 12155-12155/se.brickgame.brickbreaker I/System.out: FRAGMENT  VISIBLE = true
11-25 16:09:07.957 12155-12155/se.brickgame.brickbreaker I/System.out: FRAGMENT HIDDEN = false
11-25 16:09:07.957 12155-12155/se.brickgame.brickbreaker I/System.out: FRAGMENT ISINLAYOUT = false

So .. it seems to be there but not in the layout - how to interpret that?


Solution

  • The problem is that your GameSurface does not have a view inside it with id R.id.relLayout. Fragment transaction must be given a container into which you want to put the fragment.

    One solution would be to create a layout for the Activity, like this:

    <RelativeLayout>
        <GameSurface/>
        <RelativeLayout/> //This is the Fragment container
    </RelativeLayout>
    

    set it as the content layout of your Activity and retrieve your GameSurface like this:

    final GameSurface gs = (GameSurface) findViewById(R.id.yourSurfaceId);
    

    This is actually the way layouts and Views should be handled in Android, so it will be best if you redesigned your solution like this.

    If for some reason you can't/don't want to, you will have to reconsider replacing the Fragment part with another approach, which will not require a Fragment.