Elad Katz - Cool Stories

Showing posts with label UI. Show all posts
Showing posts with label UI. Show all posts

Monday, May 4, 2009

Overcoming the AbsoluteLayout deprecation, Part Deux

Okay, so I fixed the bottom part as well - it was not fun...
first thing I did was to replace the absolutelayout to linearLayout
Surprisingly there were no compilation errors however when I tried running it, it crashed...

So I went about fixing it, but in order to explain the process I'm gonna have to give a little background, it's gonna be as short as possible, I swear!
The project I'm currently working on is a card game, and in it there is a method for redrawing the player's cards. It does this by going over the logical card objects and checking some properties and drawing them according to it. One of these properties is the "isSelected" status of the PlayingCard object. According to this property, we draw the card - if it is indeed selected - we show it as slightly (10px) above the rest of the cards, else, it is in line with the others.
One final thing to note is that this method is called after every action is done on any cards, and that this method is called and will henceforth be referred to as redrawHand().
The redrawHand() method used to draw the selected cards using absouluteLayout like this:
boolean isSelected = hand.isCardSelected(i);
android.view.ViewGroup.LayoutParams currentParams = cardView[i].getLayoutParams();
cardView[i].setLayoutParams(
new AbsoluteLayout.LayoutParams
(currentParams.width,currentParams.height,
((AbsoluteLayout.LayoutParams)currentParams).x,
isSelected ? 0 : 10));

basically, I would set the 'y' location (relative to it's container) to 0 or 10 according to the isSelected status.
Unfortunately, this is not possible in other layouts. and that's why the run failed on the first run after the change.
what I did next is try to use some of the properties inherited from LinearLayout to acheive the same result. I tried:
  • setting the Layout_gravity of the selected cards to top and the others to bottom
  • setting the Gravity of the selected cards to top and the others to bottom
    • (Ever wonder what the difference is between Layout_Gravity and Gravity? well, it's simple - Layout_Gravity is the gravity of the view in relation to it's parent and Gravity is the gravity of the contents of the view itself)
  • setting the bottom_padding to 10px for the selected cards
  • setting the layout_margin_bottom to 10px for the selected cards
  • setting the height to 10px bigger for the selected cards
  • and other fun stuff...
as you can imagine, none of these worked - most of them did the same thing - when one card is selected, the others appear selected as well - the cards go up as one...
after allot of digging and frustration i figured it out - the container for the cards was in a wrap content mode in layout height and when one of the cards was selected, all the cards filled the content of the parent and in effect went up. now I know this doesn't make a whole lot of sense now, but after a while you get used to these things and they start making sense...
So I managed to get it to work in the layout xml (was able to change the bottom margin for 2 cards and see them up) , but when it came to run-time that was a whole different story: for some strange reason - when I clicked on one of the cards, it did seem selected, but it would be the only one I could select - now this was really weird for a few reasons: a) the method worked with absoluteLayout and b) the behaviour was extremely strange: if I pick card 2 and then card 3, card 2 will pop up but 3 won't, and if I would want to show 3 as selected, i would have to click it again (to unselect it) and then unselect card 2 and then select card 3.
WTF???
after posting yet another question on the group I was told to use the container.requestLayout() method at the end of the redraw method. What this method does is basically invalidate the view so that on the next drawing cycle, it will appear as dirty and will have to be drawn again by the graphics engine. Now this all would make perfect sense if it werent for the fact that I have have been using this method for a whole bunch of other stuff and they worked and the fact that have something that's supposed to do just that - the container.invalidate() method.
Amazingly - this fixed it - I'm still not completly sure how this miracle occured but I'm gonna get to the bottom of it and let you know if there are requests for that.
so now it all works, and you are all encouraged to go the project site and look at the code - should be intersting...
http://code.google.com/p/bestcardgameever-android/
Enjoy!

Overcoming the AbsoluteLayout deprecation, Part I

Hello constant readers :)
As you have probably read in the previous post, I've been having some problems with the new 1.5 SDK, one of which was to get the AbsoluteLayout removed from my project since it has been deprecated...
Now as I showed you before, I have two instances of it in my project - one for the thrown cards (in the middle of the screen) and one for the player hand (bottom of the screen).
The reason that I used the Absolute Layout for the thrown cards was that I needed to show cards that were overlapping. Now even as I was writing it, I thought to myself that using absolute layout would be a bad idea - why? because unlike the Iphone, the android system is not limited to one device and one screen size - at this time, there are NetBooks with 12" screens with a resolution of 1024X768 that can run android as well as more than 10(!!!) new devices scheduled to come out this or next year. So that means you cant count on absolute positioning by pixels because they can change and the game should work on all of them...


Android Netbook

So the mistake came back to bite me in the ass, and I needed to fix it, only question is how???
After making a few inquiries (1,2) it was pretty clear what I had to do - make a custom layout - and once again the question remained how...
I was starting to read up on that but have decided that before I'm going to go head first into a world of unknown pain, I'm gonna play around with the properties of the layouts I know.
Here is the process in pictures:







My first attempt:
I decided I'm going to use a FrameLayout instead of my AbsLay and add left padding for each card, thus creating an overlap...
what I got was kinda weird (Isn't it always in UI?)
The cards got smaller as the padding got bigger.
so I had to scratch that idea...



Attempt 2:
Tried using left margin instead of padding - that didn't work, all that happened was that all the cards were on the same location - you could say that they were overlapping at 100% :)
scratch that too...



Attempt 3:
Switched to LinearLayout and gave it some left margins - notice what happened there? the margins made the cards seem further apart instead of overlapping - and when you think about it - it makes sense - so what did i do? see attempt 4 below...

1 - one card on the table


2- several cards on the table


Attempt 4:
You guessed it!
I used negative values...
as you can see - that got me a little closer but not quite there yet...
for some reason - the first card had almost no overlapping and it seemed like the overlapping between the last two cards was exactly what i was looking for
so I was encouraged and made some more attempts...



Attempt 5 :
here I tried reversing the order of the margins - so the card were now arranged in ascending negative margin order - I got the exact opposite of the previous attempt...
wanna guess what I did next?
I'll give you a hint - in attempt 4 I used descending negative values between cards and in 5, ascending...
guess!




Attempt 6.1
Perfect, almost...
Here I used a constant negative left margin (of 10 pixels)
only problem was that I also sized the frame that contains all the cards with the sum of the cards images so it won't shrink the cards on the right and left of it and for it cropped the right of that King card there...



Attempt 6.2
So I gave it a little extra - what do I mean?
The cards were 72px wide each, I have 5 cards and a margin of 10 for each card so it should have been 72+10+10+10+10 = 112
it worked with 130 :)
good enough for me :D
so there you have it, success, sorta.

So I managed to do it without creating a new Layout, but next I'm going to have to change the layout for the bottom cards, will I be able to do that without creating a new layout? It's gonna be fun finding out!
Stick around for more, and comment if you like it or if you feel something is missing!
See you soon
Elad Katz