David Janes' Code Weblog

October 29, 2011

Good-bye Delicious

startups,tips · admin · 5:46 am ·

Yahoo sold Delicious to another company and for the most part it hasn’t worked for me since the transition. I don’t use the “social” part of the bookmarking: I just try to bookmark every interesting page I read in case I need to find it again in the future. If Yahoo had been clever, they could have built cleverer search infrastructure around bookmarking information but of course “Yahoo” and “clever” rarely appear in the same sentence with being chaperoned by “not”.

I know startups are hard and I feel a little bit bad about kicking them when they’re down but features likely multi-word tagging are not so nearly interesting to me as “working” so it’s off to Evernote which has a lot more powerful clipping capabilities, is well funded, charges money – free doesn’t stay in business.

Here’s how I did the migration:

  • If you have 8747 bookmarks like me, you’ll need to do this and do two export / imports. Delicious’ new API only exports 1000 entries (f*ck you very much), so you’ll have to hack your DNS a little to pull the API data from the old Yahoo servers that are still up and running. I hand edited the exports to avoid duplicates though maybe Evernote is clever enough to figure this out on it’s own.
  • Follow the instructions on this page. Basically:
    • curl https://USERNAME:PASSWORD@api.del.icio.us/v1/posts/all > backup.xml
    • paste into here http://jsdo.it/palaniraja/uphW/fullscreen (on a Mac anyway)
    • save the results as toimport.enex
    • run Evernote and run File > Import

October 24, 2011

Automatically Binding Resources to Methods in Android Applications

android,code fragments,java · admin · 4:33 pm ·

AKA I’m as mad as hell at Java and not taking it any more Part II.

When developing Android applications, binding resources to end method calls is even more annoying than binding resources to variables.

One approach is to create an anonymous inner classes implementing various listener interface.

UIButton postButton = (Button) findViewById(R.id.share_post);
postButton.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
    // do stuff ...
  }
}

The other is to just implement the listener interface with whatever activity you’re using and figure out what button is being pressed.

I’d just as soon have the data wired up automatically to functions if it’s there. Here’s how I’m doing it now.

In MyActivity:

// class fields
public ImageButton uiButtonDining;

// in onCreate
UIHelper.bindImageButtons(this);

This will automatically wire to the following function

public void uiButtonDining_onClick(ImageButton _imageButton)
{
  // ... do stuff ...
}

I’ve only done this for ImageButton so far but I’m hoping this approach will scale for various other widgets.

The Code

Here’s The Magic for UIHelper.java:

static public void bindImageButtons(final Activity _activity) {
  Field[] instance_fields = _activity.getClass().getDeclaredFields();
  for (final Field instance_field : instance_fields) {
    if (!ImageButton.class.isAssignableFrom(instance_field.getType())) {
      continue;
    }

    LogHelper.debug(true, _activity, "field=" + instance_field.getName());

    try {
      final ImageButton button = (ImageButton) instance_field.get(_activity);
      if (button == null) {
        LogHelper.debug(true, _activity,
        "Button is stil NULL", "field=" + instance_field.getName());
        continue;
      }

      String callback_onClick_name = instance_field.getName() + "_onClick";
      try {
        final Method callback_onClick = _activity.getClass().getMethod(
         callback_onClick_name, ImageButton.class);

        button.setOnClickListener(new View.OnClickListener() {
          public void onClick(View v) {
            LogHelper.debug(false, _activity, "clicked", "field=" + instance_field.getName());

            try {
              callback_onClick.invoke(_activity, button);
            } catch (IllegalAccessException x) {
              LogHelper.debug(true, _activity,
              "Couldn't invoke callback", "callback=", callback_onClick, x);
            } catch (InvocationTargetException x) {
              LogHelper.debug(true, _activity,
              "Couldn't invoke callback", "callback=", callback_onClick, x);
            }
          }
        });
      } catch (NoSuchMethodException x) {
        LogHelper.debug(true, _activity,
        "no callback", "method=", callback_onClick_name);
      }
    } catch (IllegalAccessException x) {
      LogHelper.debug(true, _activity,
      "Can't set R.id", "name=", instance_field.getName(), x);
    }
  }
}

October 23, 2011

Dynamically resize and stack many UIViews

code fragments,iphone · admin · 5:58 pm ·

The iOS’s UILabel is kind of an annoying beast – out-of-the-box it takes coding to get the correct height or to “top justify” it. If there’s too much text inside a UILabel, sometimes it shrinks the text which visually doesn’t make it look that great – the ideal solution would be to split the text over multiple lines and adjust everything else downward dynamically. Also if you have to have multiple labels with different styles a typical solution would be to use a UIWebView controller. However, this isn’t really suitable inside a UITableView where you have to have many views and you need to know the exact space to allocate.

Here’s a helper function that will take an Array of UIViews and stack them up, returning the height. If any of the UIViews are UILabels, it’ll resize them to the appropriate height.

/*
 *  Stack views on top of each other starting at a point.
 *  If they are labels, we resize. Return the height used.
 */
+ (CGFloat) uiStack:(NSArray*)_views startingAt:(CGPoint)_point
{
  if (!_views || !_views.count) {
    return  0;
  }

  for (UIView* view in _views) {
    if ([view isKindOfClass:[UILabel class]]) {
      UILabel* label = (UILabel*) view;
      CGSize labelSize = [label.text
                sizeWithFont:label.font
                constrainedToSize:CGSizeMake(label.frame.size.width, 1000.0)
                lineBreakMode:label.lineBreakMode];

      label.frame = CGRectMake(_point.x, _point.y, view.frame.size.width, labelSize.height);
      _point.y += labelSize.height;
    } else {
      view.frame = CGRectMake(_point.x, _point.y, view.frame.size.width, view.frame.size.height);
      _point.y += view.frame.size.height;
    }
  }

  return _point.y;
}

Enjoy!

Automatically Binding Resources to Fields in Android Applications

android,code fragments,java · admin · 4:53 pm ·

AKA I’m as mad as hell at Java and not taking it any more.

Here’s how I’ve been getting access to various UI resources in my Android applications. Almost certainly, you’re doing the same thing too.

layout/file.xml:

<TextView android:id="@+id/title" ... />

File.java:

TextView title = (TextView) parent.findViewById(R.id.title);

Over and over for as many UI elements as I need to access. To hell with that.

Here’s my new method of doing this

First, give the ID and the Fields the same name:

layout/file.xml:

<TextView android:id="@+id/uiTitleTextView" ... />

File.java:

public TextView uiTitleTextView;

Note that that’s a class field — it’s not in the method, and it must be public Then in onCreate I just do this:

UIHelper.bindViews(this);

And that’s it: every field just gets wired up.

The Code

Here’s The Magic for UIHelper.java:

static public void bindViews(Activity _activity)
{
  Field[] instance_fields = _activity.getClass().getDeclaredFields();
  for (Field instance_field : instance_fields) {
    if (!View.class.isAssignableFrom(instance_field.getType())) {
      continue;
    }

    try {
      Field id_field = R.id.class.getField(instance_field.getName());
      int r = id_field.getInt(R.id.class);

      View view = _activity.findViewById(r);
      if (view == null) {
        LogHelper.debug(true, _activity,
          "Field expected in Layout but not found", "name=",
          instance_field.getName());
        continue;
      }

      instance_field.set(_activity, view);
    } catch (NoSuchFieldException x) {
      LogHelper.debug(true, _activity,
        "Field expected in R.id but not found", "name=",
        instance_field.getName());
    } catch (IllegalAccessException x) {
      LogHelper.debug(true, _activity,
        "Can't set R.id", "name=",
        instance_field.getName(), x);
    }
  }
}

Making R.java universal in Android apps

android,java · admin · 4:03 pm ·

Android projects make R – the way of accessing resources by ID – tied to the particular project you’re building. This presents several problems:

  1. you can’t use the same source tree to general many applications, because your “common” source tree won’t be able to access R
  2. you can’t make universal libraries that work with R because R will be in some arbitrary package tied to a specific project

The solution is to make an R.java that’s not tied to a particular project. The method I came up for this is to duplicate the project specific R into a “well known” package. Because the ID names are the same in both Rs, you’ve essentially duck-typed yourself to a reusable R. Tim implemented this and has the details on his blog.

We’ll be making use of this in the next couple of blog posts.

How to use custom fonts in Android applications

android,code fragments,java · admin · 3:07 pm ·

Here’s how to use custom fonts in your Android application.

  1. Select your font – for example, Ubuntu. Make sure you use a royalty-free font (such as that one) or you pay the appropriate licensing fee (because you could get in a world of legal pain and because don’t be a dick)
  2. In the root folder of your Android project, make sure there’s a folder called assets/fonts. The fonts subdirectory is entirely optional but to my taste.
  3. You cannot specify the font (really the typeface) in your resources, so you have to do in code as follows
Typeface font = Typeface.createFromAsset(_activity.getAssets(), "fonts/Ubuntu-Bold.ttf");
textView.setTypeface(font);

And that’s it.

Powered by WordPress

Switch to our mobile site