Hurrah for me! Yes I realise that 50,000+ apps got there before mine but heh I am entitled to be a bit excited. It is called “Running Low”, and is available now for your Android device
<EDIT>
A few people have asked what it actually does so here is the blurb from Android Marketplace
Remember when you were supposed to be meeting someone and the phone died.
Remember getting home to "Where've you been? I have been trying to get call you!". Not your fault the phone was dead and you just didn't realise.
Well Running Low will message ahead and tell them "You're about to go offline"
Location optional
</EDIT>
Anyway whilst the issues I came up against while developing “Running Low” are covered already, elsewhere on the net I wanted highlight the PITA that is signing of your app.
The official android docs covering “Signing Your Applications” are here. IMHO Plusminus’ post on andxdev.org “Signing your apk/application for release (keytool,jarsigner)” does a better job of explaining key creation and signing than the official docs, and his is partly in German!
UPDATE
1. Hours after adding the app to the marketplace i checked my install of the app and found it had failed. Minor panic as I had to assume everyone trying to download it would get the same error of “package file was not signed correctly”. I double checked the signing process but all looked good then i read this post saying remove your dev version of the app before installing signed one from marketplace. I uninstalled the copy of my app that I had deployed during development, downloaded again from marketplace, and all worked fine.
2. I was a bit disappointed to see the 0 downloads on the Android Developer Console but supposedly Google are having some issues with the statistical reporting.
I was trying to build an app today that responded to the BATTERY_LOW warning. I managed to connect to the running emulator, using the port number, that is in the Window Title. However once connected I was getting error messages reported against the syntax of my command
“unknown command, try help”
I checked the command and everything was fine. It turns out that the Telnet connection to the emulator console can get itself all confused and starts to fail on commands that are correct. If you get this don’t give up and think you are doing something wrong it is just the Telnet communications being a bit flaky.
One thing that does seem to reliably upset it is when you try correcting a typo with the backspace key. I know it sounds crazy but it is true. I almost gave up.
Recently I was asked to produce a web page with the following layout for some of its list data
Floating all items, left
My first thought was “a single list ordered list, with all the list items floated left”. That worked well but didn’t really read all that well with each “row” running left to right rather than up and down, which is how people prefer to read lists. The other problem I had was when one of the items wrapped onto multiple lines. The extra height of wrapped items meant items on the next “row” would get stuck trying to float past it. See the “Koodoo” in the following list of Animals
The issue was easy to get around by clearing on every 5th item i.e. The start of each “row”. The floating left technique works OK if the list has no particular order such as a list of images but for the data I was going to have to display left to right layout just wasn’t going to cut it. The trouble is that browsers just don’t do vertical wrapping of lists. It was at this point I was directed towards Paul Novitski’s A List Apart article, Multi-Column Lists.
EDIT: Check out the use of inline-block, rather than floats, described at sitepoint, for this kind of layout.
A List Apart’s approach
I am not going to repeat the entire article here it is well worth reading yourself. The author takes a very thorough approach showing 6 different methods with the 6th one being his and my preferred approach. Once you have read it come back and we can discuss where I went from there because that was certainly not the end of the journey for me.
Phew! You know that you are going to be in for a bumpy ride when the author describes what you are trying to achieve as a “minor holy grail of XHTML and CSS”. What I had to do over and above Paul’s solution was deal with dynamic data and mark-up generated on the server. The first thing I am going to show is the ASP.NET code and then finally the Javascript work I had to do.
Generating the mark-up
The only thing that was fixed was the number of columns, 4. The number of items varied from 1 to 100. The alistapart article has a fixed set of items and includes column classes in the static mark-up, mine are added in the ItemDataBound event of a repeater.
1: int wrapAfterCount = Math.Max(textArray.Length / NumberOfColumns, 10);
2:
3: private void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
4: {
5: if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
6: {
7: Repeater repeater = sender as Repeater;
8:
9: TextContent text = e.Item.Controls[0] as TextContent;
10: int wrapAfterCount = Convert.ToInt32(ViewState[String.Concat(repeater.ID, "_wrapAfterCount")]);
11:
12: double colPos = (double)(e.Item.ItemIndex + 1) / wrapAfterCount;
13: double col = Math.Min(Math.Ceiling(colPos), NumberOfColumns);
14:
15: string columnClass = string.Format("col{0}", col);
16:
17: text.AddClassName(columnClass);
18:
19: string key = String.Format("{0}_firstItemFor_{1}_Output", repeater.ID, columnClass);
20: bool firstItemForColumnOutput = this.ViewState[key] != null ? true : false;
21:
22: // Mark the FIRST item of each column with the 'topItem' class (other than the first column). This class
23: // is used in the client side script to offset column positions aliging the "tops" of them
24: if (col > 1.0 && firstItemForColumnOutput == false)
25: {
26: text.AddClassName("topItem");
27: this.ViewState.Add(key, "true");
28: }
29:
30: text.Text += Convert.ToString(e.Item.DataItem).Trim();
31: }
32: }
wrapAfterCount (Line 1) was set when the repeater was created and had its DataBind called. The reason for the Math.Min is that if the wraps list after less than 10 they look unnaturally short. It kind of depends how much room you have to play with in your layout but for me having 10 items wrapping to 4 columns after two items, looked wrong. The rest of the code runs in the ItemDataBound event
Setting the offset in Javascript
Having basically ported the static mark-up of the alistapart article to ASP.NET I found that the reality of real data meant it was a lot harder. Originally the offset for columns 2, 3 and 4 was NumberOfItemsInColumn x LineHeightOfSingleItem. This of course falls down when items start to wrap and you can’t know the height of a single item until it has been loaded in the browser . Therefore I decided the offsetting calculation was going to have to be done in Javascript. Now that may well upset a few but it is not difficult to ensure this layout degrades well when Javascript is not present.
function alignHorizontallyWrappedList(list, colCount) {
var accumulatedHeight = 0;
var accumulatedHeights = new Array();
// Obtain the height if each column. This height will be used to offset the next column so that the tops of columns > 1 are
// all aligned
for (var col = 1; col <= colCount; col++) {
accumulatedHeight = 0;
jQuery('.col' + col, list).each(function(index) {
accumulatedHeight += jQuery(this).outerHeight(true);
})
accumulatedHeights[col - 1] = accumulatedHeight;
}
// The margin tops are set once all columns are measured rather than as we go because the margining effects the height.
for (var heightIndex = 0; heightIndex <= accumulatedHeights.length - 1; heightIndex++) {
jQuery('.col' + (heightIndex + 2) + '.topItem', list).css('marginTop', '-' + accumulatedHeights[heightIndex] + 'px')
}
jQuery(list).addClass('wrapped');
}
You may well be asking “Was it really worth it”, well that is not for me to decide but it was a fun and interesting challenge and that is why we are developers right? Many thanks to Paul Novitski as without his original article I would have given up much earlier in the search for this “holy grail”
I had to post a link to this MSDN article because its title really made me chuckle, MSDN Article - CSS Enhancements in Internet Explorer 6. Anyone who has had to develop web sites that work with IE6 as well as modern browsers such as FF3, Chrome and Safari will know what a total piece of crap IE6 and its apparent “CSS Enhancements” are.
I know it is a bit unfair to pick on old articles as computing moves so fast but if there was a Microsoft product that deserves my hatred it is You, IE6.
Like most software developers, especially those involved in UI work, I am used to working with a multi monitor setup. I have two Widescreen Dells in the Munkiisoft office but recently I needed to remote onto a client's development workstation. I was dreading the experience, until I found that Remote Desktop can be run to span multiple monitors.
This post describes how to run Remote Desktop so that it will span muiltiple monitos, essentially it is the “/span” command line switch that you need.
Great I thought but the experience was not what I hoped for because everytime I maximised a window it stretched across both monitors, boo! This is probably more annoying than just having it on a single monitor. Not wanting to give up, having come so close, I started Googling\Binging; I found SplitView. SplitView runs on the machine that you are remoting to and gives you proper multi-monitor support. Awesome, exactly what I was after.
As of 18/02/2010 this router does not work out-of-the-box with an Xbox 360,no matter what firmware version you have but there is a solution.
There are a couple of “me too” threads on forum.netgear.com that make for some depressing reading. However if you don’t want to wade through everyone saying “It doesn’t work for me either” jump straight to the solution. Many thanks to runDMB.
Basically the v5 router has issues automatically dishing out IP addresses to certain devices, it works for my work laptop, desktop, wireless music streamer and phone. The fix involves reserving an IP address for the MAC address of the 360
An intertesting event happened to me today. For the first time in over a year I read about something and though “cool, that is worth sharing”. The semantic marking up of Event data and what google is going to be doing with it.
I am currently working for a large “organiser of trade and consumer events” where we are in the process of building a CMS platform, on top of EPiServer, to enable the different events to have a compelling presence on the Internet. We often have to display Event data and from time to time I have looked at using Microformats but mainly ‘cos I thought that was the right thing to do not because i could see any really compelling use of them, until now.
Last year Google introduced “Rich Snippets”. Using microformats to signal particular datatypes Google could pull through that data and display it alongside the Site Title in the Google results
This image shows a search result displaying a Review, Google also added support for People and later Video. On Friday Google posted on the Webmaster Central Blog (an excellent read) that they are now supporting Event data. Whilst I am going to have to wait a while to get that on our official Product Backlog and I am going to mark this auspicious event (me posting a blog for the first time in over a year) with some Event mark-up.
Blog Post After a year in the wilderness (to be swiftly followed by another
year) Pat Long blogs When:
Jan 24, 10:40PM -
11:01PM Where:
Munkiisoft Ltd,
322 Kingston Road,
New Malden,
Surrey
Category: Blog post
So we all know of IE6 and the problem it can have have when you have multiple submit buttons on a form and you press enter in an edit control. IE6 gets confused over what button should be sent to the server as the submit button. This annoyance is covered here and here.
The issue I had recently was that even though I was directly clicking on a button (the search button on this page) ASP.NET was firing the code for the final button on the page (which in this instance was a "Finish" button). Once I realised that this is what was happening i took a look at the form that was being posted to the server. In the form variables collection I found both button elements! This is is an IE6 only issue and darn annoying.
The fix was to disable the unneeded buttons, which stops them being included as part of the form post. More specifically I hook the click event on all the input and button elements, of type "submit", on the page, when it first loads. Then when the click happens I disable all the button elements and reenable them using setTimeout after 2 seconds.
The only exception to this disabling is if it was a button that caused the click. That button is obviously not disabled.
You can see the solution on this page here http://www.ditto.net/Topics/MoviesMakeMeLaugh/fill in the function hookAllButtonsForDisabling().
Originally published on my old Charteris blog
This is part 6 of the training course originally described here with parts 2,3, 4 and 5 available here, here, here and here respectively. So far we have covered WPF fundamentals, XAML, brushes, shapes, controls, styling, resources and layout.
Part6
- Data
- Binding class
- Converter property
- ElementName property
- Mode property
- Path property
- RelativeSource property
- XPath property
- LAB12 - Databinding elements to each other
- DataContext
- DataProviders
- LAB13 - Binding to an ObjectDataProvider
- DataTemplates
- DataTemplateSelector
- ItemsControl
- Introduction
- ItemsSource property
- ItemTemplate property
- ItemsPanel property
- ItemContainerStyle
- LAB14 - Using ItemControl with ItemsSource, ItemsPanelTemplate, ItemsPanel, ItemContainerStyle and DataTriggers
Download Part6.zip which includes a slide deck and the 3 labs. Code to get you started with the labs is included.
Originally published on my old Charteris blog
Seeing as I blogged the Behind The Scenes look at Microsoft Surface I thought it only fair to give equal attention to this very funny (IMHO) tongue-in-cheek look at Microsoft Surface.
Microsoft Surface Parody on YouTube