Renoki: Making An Android Game (part 14)

I wanted to finally fix some lingering issues with Renoki and get the final version up on the market. This will be version 4.0 and I believe that this will be my final version for now.

I have been struggling with tablet resolutions for a while now. When I was first designing the graphics, I made a stupid decision and created them for a 480×854 resolution, because I thought that would be the largest resolution I would support. Unfortunately, a bunch of other phones came out with enormous resolutions (1280×720) and I realized that my app was still showing up for tablets.

Supporting Tablet Resolutions
One of the annoying things I ran into was that I set Renoki to have a minimum Android API level of 7 (froyo). This means that any device with froyo or newer can download it. Given that ~25% of phones are still running froyo (, I felt this was a good decision to make. Unfortunately, if you do not want to support tablet resolutions, there is no way to make your app not show up,). There are some things in the Android Manifest you can do (support-screens, compatible-screens) but the useful mechanism were not introduced until API level 9. This means it is IMPOSSIBLE to prevent a level 7 app from appearing on tablets.

The next best thing I could do is run the app in screen compatibility mode. What this would do is create the smaller resolution game in the middle of the screen and surround it with a black border for all the unused pixels. While this doesn’t offer a full experience, it would at least prevent the game from crashing. The problem was that the view the game was in was still the entire screen size (e.g. 1280×720), but I was only drawing within my original 960×540. I had a few things based on the screen width which were screwed up by this, and images I had go “offscreen” didn’t really go offscreen and instead just drew on the black border. It was in general a very screwed up thing.

The solution I realized was to hardcode my base view to a specific height and width, and use the view width to do my calculations. This basically solved all my problems and allowed it to run correctly on any resolution.

My app has 1 FrameLayout (@id=frameLayout) that contains a single custom SurfaceView. By creating a set of LayoutParams and setting the width, height, and gravity, I made that root FrameLayout conform to the size I wanted. Then, my app always thinks it is running on the correct resolution, regardless of the actual device resolution. I also made sure to multiply by the pixel density “dip” to make sure it works on all devices.

So now I have an app that “works” on all resolutions, although it is extra tiny on big tablets. However, this is good enough for me and I definitely don’t want to spend the time creating all the images for this game at bigger resolutions.

Renoki: Making An Android Game (part 12)

FrameLayout with a ScrollView

My game consists of a single FrameLayout with a child SurfaceView. This essentially gives me a blank canvas to draw anything I want to, which works fine because I have a static background. What I wanted was when the user presses the “About” button, I would display the credits and the user could vertical swipe to scroll through them. At the bottom there would be an exit button. A bonus would be I could interweave images in between the credit lines, but that wasn’t necessary.

I think the typical way to do this would be to create a new activity that you create with the credits. However, I didn’t want to stop my current activity because I use a gameloop and gamestate that is local to my main activity. What I really wanted was for when the user touches the “About” button, a new ScrollView appears on top of my current SurfaceView and I change the gameState to be the ABOUT state. This is a surprisingly annoying topic to search and I had to look at a dozen posts online until I could get something to work.

First of all, you will need to create your ScrollView programmatically instead of through XML. One of the things that originally turned me off of Android was how they used XML to define the layout of the UI. I’m sure there is a good reason why they did it, but all I’ve noticed is it pisses me off and makes it harder to find the answer because most of the time people provide XML solutions. Anyway, you need to make sure your FrameLayout has an ID field so you can get a reference to it in your code.

A FrameLayout can have multiple children views, where each view will overlap the previous one.  So what I want is to create a ScrollView and add it to the FrameLayout.  A ScrollView can only have 1 child view (you can only insert 1 view into it).  Because I want to display both images and text in the scrolling area, what I did was insert a LinearLayout into the ScrollView.  Inside that Linear Layout, you can insert as many ImageViews, TextViews, etc that you want.  It will all be scrollable.

Lastly, when you want to close the ScrollView, you merely remove it from the FrameLayout. You can remove it either by passing the same View you originally created or passing the index of the View you want to remove and using removeViewAt(int ID);

The neat thing about this is if you set the size of the ScrollView to be less than the fullsize of the original SurfaceView, you can still see whatever is underneath it. TouchEvents on the non-covered sections will still trigger on the original SurfaceView, so you can reuse whatever touch logic you have from your original SurfaceView. This is how I close the ScrollView.