Wednesday, March 14, 2018

Load Libgdx game to a Fragment shows a black screen on android

Leave a Comment

The following code shows how I load a Libgdx game (MyGdxGame) to a LinearLayout. on game create I set up a camera and load a small wav sound file. Texture is loaded after view is loaded.

The issue is during fragment transition to this fragment, there is a noticeable black flash and delay. Is it possible to reduce this some how and improve the fragment transition.

 public View onCreateView(LayoutInflater inflater, ViewGroup container,                          Bundle savedInstanceState) {     View view = null;     Bundle bundle = getArguments();     if (bundle != null) {         this.input = bundle.getParcelable(Utils.FRAGMENT_INPUT_KEY);     } else {         input = new FragmentInput();     }      view = inflater.inflate(R.layout.solve, container, false);     surface = (LinearLayout) view.findViewById(R.id.puzzleView);      activity = (MainActivity) getActivity();      com.badlogic.gdx.graphics.Color color = new com.badlogic.gdx.graphics.Color(Color.red(input.backColor) / 255f,             Color.green(input.backColor) / 255f,             Color.blue(input.backColor) / 255f, 1.0f);     size = input.pieceCount;     cols = input.columns;     GameData gdata = new GameData();     gdata.rows = size / cols;     gdata.columns = cols;     gdata.backColor = color;     gdata.setCategory(input.category);     if (input.rotated) {         gameView = new MyGdxGameRotate(this, gdata);     } else {         gameView = new MyGdxGame(this, gdata);     }      if (surface != null) {         AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();         View game = initializeForView(gameView, config);         surface.addView(game);     }     return view; } 

2 Answers

Answers 1

onCreateView is called before the fragment is shown, doing heavy work here means you delay showing that view (the 'black flash'), instead you should start by moving the heavy work into onResume or at least onViewCreated

Secondly, place the load on a background thread so the UI thread can continue to process the display of the fragment. The simplest way to do this in Android is to use an AsyncTask which will allow you to easily notify the UI when everything is loaded

public void onViewCreated() {     new AsyncTask<Void, Void, Void>() {         public Void doInBackground() {             //Do your loading         }          public void onPostExecute(Void aVoid) {             //Update display, play sound (on resumed fragment)         }     }.execute(); } 

If you are new to Android, be careful about leaking context with this approach

Answers 2

I am not familiar with Libgdx so my observations are not specific to Libgdx. If the view initialization takes time, and assuming that it must be done on the UI thread, maybe you can use a Framelayout and overlay a startup graphics in an ImageView that is placed on top of the current puzzleView, with its initial visibility set to visible in the xml. In the onCreateView, inflate the view as you are doing, and then only find a reference to the puzzleView, but don't do any initialization. You can then check if the view is initialized when the onResume method is called (create a new boolean field for that) and if not, then initialize it and then set the visibility of the top layer to invisible to reveal the puzzleView. The delay will still be there, but the screen will be covered by the top layer graphics until the onResume() returns, by which time (presumably) the initialization is complete. If the heavy part of the initialization can be done on a background thread, then maybe you fire off a background thread that does the the work, when the onCreateView is called, and change the visibility of the top layer and finishing part of the initialization (which almost certainly needs to be done on the UI thread) to a Runnable which should get started via a runOnUiThread() method from the background thread.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment