2 GB > 1 GB!

November 5, 2009 by maohao

I just upgraded my old Dell Inspiron 5150 by replacing a 2X512MB (HYNIX DDR/PC2700) with 2 X 1G RAM (Crucial 200 pin/DDR/PC3200) and I realize it IS faster!

OS (Windows XP Pro) booting seemingly faster;

Firefox 3.5 loading web pages seemingly faster;

Running Photoshop CS2 seemingly faster;

Compiling Flex projects in FB3 seemingly faster;

I will have to check out hulu.com to see if the Flash Player will still blow up my machine.

Just a note for self. Because like in early 90’s, I overheard someone complained that adding more RAMs on top of the 512MB(?) didn’t really help/didn’t seem to make too much of a difference.

Refer to component in Flex with curly braces

November 3, 2009 by maohao

Always use curly braces/brackets to refer to your component by id. Like this:

<mx:Panel …
showEffect=”{shake}”>

<pg:ShakeEffect id=”shake”/>

</mx:Panel>

You can probably do without the curly brace to refer to an effect component if you are in the main application mxml; but it won’t work for a component.

See also:

Notes for Building iPhone With HTML, CSS and JavaScript by Jonathan Stark

October 17, 2009 by maohao

The book. Author: Jonathan Stark.

  • Page scaling in iPhone
    By default Mobile Safari will zoom out for a page that is wider than 980px unless you specify “viewport” <meta> tag to tell it not to;

    <meta name = "viewport" content = "user-scalable=no, width=device-width" />
  • CSS for iPhone
    <link rel=”stylesheet” type=”text/css” href=”styles/iphone.css” media=”only screen and (max-device-width: 480px)” />
    <link rel="stylesheet" type="text/css" href="styles/desktop.css" media="screen and (min-device-width: 481px)" />
    <!--[if IE]>
    <link rel="stylesheet" type="text/css" href="styles/desktop.css" media="all" />

    <![endif]-->
  • Icon for iPhone home screen, a.k.a. “web clip icon”By default, this is a 57px by 57px named “apple-touch-icon.png” in your web root. iPhone will add gloss and 10px(?) radius rounded corner to it. If you don’t want the iPhone to add effects to your webclip icon, change the name of the file to “apple-touch-icon-precomposed.png“.In the case you want to add a web clip icon for an individual page that is different from the rest of the site, add one of the following lines to the of the page:

  • <link rel="apple-touch-icon" href="myCustomIcon.png" />
    <link rel="apple-touch-icon-precomposed" href="myCustomIcon.png" />

  • Full-screen modeAdd the following line to the of your page and your web app will in display full screen mode when launched from the web clip icon, which will give you an extra of 104 px in height:

    <meta name="apple-mobile-web-app-capable" content="yes" />

    Once you’ve added the apple-mobile-web-app-capable meta tag, you have the option to control the background color of the 20 pixel status bar at the top of the screen using the apple-mobile-web-app-status-bar-style meta tag. The normal gray Safari status bar is the default, or you can change it to black. You can also set it to black-translucent which makes it partialy transparent and additionally removes it from the document flow. In other words, your content will be shifted up by 20 pixels and behind the status bar the when page first loads, so you might have to position your header a little lower to compensate.

  • Here are some webkit(?)/Safari specific CSS or newer CSS3 attributes or confusing ones:

  • text-shadow
    text-shadow: 0px 1px 0px #fff;

    The parameters: horizontal offset, vertical offset, blur, and color.
  • -webkit-gradient
    background-image: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#999));
    a CSS gradient can be used anywhere you would normally specify a url() (e.g. background image, list style image). The parameters from left to right are as follows: the gradient type (can be linear or radial), the starting point of the gradient (can be left top, left bottom, right top, or right bottom), the end point of the gradient, the starting color, and the ending color.
  • -webkit-border-top-left-radius, etc.
    #header ul li:first-child a {
    -webkit-border-top-left-radius: 8px;
    -webkit-border-top-right-radius: 8px;
    }
  • first-child/last-child pseudo classes

    #header ul li:first-child a {
    -webkit-border-top-left-radius: 8px;
    -webkit-border-top-right-radius: 8px;
    }
    #header ul li:last-child a {
    -webkit-border-bottom-left-radius: 8px;
    -webkit-border-bottom-right-radius: 8px;
    }

    The first-child and last-child pseudo classes can be a bit confusing. For example, li:first-child will select the first li that is the child of its ul parent. It does not select whatever is the first child of the li.
  • rgb/rgba
    text-shadow: rgba(125,125,125,0.6) 0px -1px 0px;
  • -webkit-border-image and border-width
    border-width: 0 8px 0 8px;
    -webkit-border-image: url(images/button.png) 0 8 0 8;

    These two propoerties together allow you to assign portions of a single image to the border area of an element. They are similar to 9-slice scaling in Flash or 9-patch in Android. The parameters in border-width refer to top/right/bottom/left side of the image.

Shortcuts for Microsoft Visio 2007

October 8, 2009 by maohao
  • Ctrl+Shift->  Zoom/pan with magnifying glass. Left click for zooming in; right click for zooming out;  Left drag an rectangle to zoom in to area; Right drag to pan;
  • Ctrl+drag-> Duplicate object;
  • Ctrl+k-> Add hyperlink to object;
  • Ctrl+Shift+g-> Group shapes;
  • Ctrl+Shift+u->Ungroup shapes;
  • Double click on Textbox -> Select all text in the Textbox;
  • Size/position object manually -> Select >View > Size/Position Window

Type of View.OnTouchListener

October 4, 2009 by maohao

I found the documentation on the type of android.view.View.OnTouchListener misleading. It says: “Return true if the listener has consumed the event, false otherwise.”

For me, it looks like it should almost be the opposite:

“Return true if the event is allowed to propagate, false otherwise.”

//Sample code

public boolean onTouch(View v, evt:MotionEvent) {
switch(evt.getAction) {
case MotionEvent.ACTION_DOWN:
return true; // should allow propagate since we need to handle it in MOTION_MOVE block
case MotionEvent.ACTION_MOVE:
Log.d(“TOUCH”, “historical size is “+getHistoricalSize());
return false;
default:
break;
}
return false;//for any motions other than DOWN, we choose to block them. Unless other code want to handle it.
}

Please do feel free to correct me if I am wrong. Thanks.

Canvas.save, Canvas.restore; Camera.save, Camera.restore

September 30, 2009 by maohao

Android graphics package contains android.graphics.Canvas and android.graphics.Camera classes, both of which allow you to manipulate the “Modelview” transformation matrix, with the latter manipulating your drawing in “3D”.

Basically the ability to manipulate complex, hierarchical transformation is achieved by an(?) internal matrix stack with the top matrix being the current one in effect and the one that you are manipulating. All the transformations you are making on the current matrix are cumulative; so if you were just to manipulate the current matrix, it’s going to be a big pain to draw something like a car or a human figure which conceptually is assembled by different parts.  Canvas.save()/Camera.save() is to push a matrix into the stack; the result is the transformation you’ve made is saved into the stack.  Canvas.restore()/Camera.restore() is to discard the current transformation and go back to the last saved one and continue on it. So if you want to continue with some transformation you made a while ago, you should first save/push it into the stack first so that you can go back to it by restoring/popping it out from the stack. See the following pseudo code for how we go about drawing a drag race car with huge wheels:

//setup/clean up stuff
canvas.save(); // remember where we are since we’d like to go back to this original transformation later;
// move the front wheel to front left
// make it twice as big as the normal wheel
// draw front-left wheel in normal size
canvas.restore(); // go back to the identity matrix;
// move the front wheel to front right
// make it twice as big as the normal wheel
// draw front-right wheel in normal size
canvas.restore();
//… draw body
canvas.restore();
//… and other wheels…

The pattern is

  • If you want to go back to the current state in terms of transformation, you should remember where you are by calling Canvas.save() or Camera.save());
  • Transform the matrix (via Canvas or Camera methods such as Canvas.translate() and Camera.rotateY();
  • Do drawing;
  • Go back to the transformation state you remember in step 1 by calling Canvas.restore()/Camera.restore() if you want to continue from the transformation you left in step 1;
  • In theory, if you only have one matrix transformation saved in the stack, you can simply push it out by calling Canvas.restore()/Camera.restore() again and again. But in the real world (at least applying for cupcake and donut),  I’ve found I have to keep “saving” before each new transformation and “restoring” after it, even if I was “saving”/”restoring” an identity matrix. So this means you would normally call Canvas.save()/Camera.save() each time before a new transformation;
  • Transform the matrix;
  • Do drawing;
  • Canvas.restore()/Camera.restore();

To summarize (applying to android.graphics.Camera as well), you repeatedly do the following cycles:

  1. canvas.save();
  2. transform matrix;
  3. draw;
  4. canvas.restore();

Note that in android, #2 transformation should be coded before #3 drawing to make the drawing stick to the transformation. If you reverse 2/3, your drawing won’t be affected by the transformations that come after it. This is kinda “counter-intuitive” at least for me since you have always need to set your canvas in position before you paint but not the other way around.

Check out the “Red book” for “Manipulating the Matrix Stacks” to get a better understanding. And here is a sample code showing you how I draw the awesome Batmobile (Spiderman’s car) crawling on a skyscraper (use your imagination for the wall and other details as I am still polishing my drawing skill. Please hold on for the next episode!):

package com.mh.android.test;

import android.app.Activity;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;

public class HelloAndroidAgain extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyTestView(this));
}

private static class MyTestView extends View {

public MyTestView(Context context) {
super(context);
setMinimumWidth(200);
setMinimumHeight(200);
//camera = new Camera();
}
private Camera camera = new Camera();
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);

camera.save();
camera.rotateY(60f);
camera.applyToCanvas(canvas);

canvas.drawColor(Color.DKGRAY);
Paint paint = new Paint();
paint.setTextSize(24);

//front left wheel
canvas.save();
canvas.translate(50f, 50f);//xCtr, yCtr
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“FL”, -10, 10, paint);//string
canvas.restore();

//front right wheel
canvas.save();
canvas.translate(150f, 50f);
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“FR”, -10, 10, paint);
canvas.restore();

//rear left wheel
canvas.save();
canvas.translate(50f, 150f);
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“BL”, -10, 10, paint);
canvas.restore();

//rear right wheel
canvas.save();
canvas.translate(150f, 150f);
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“BR”, -10, 10, paint);
canvas.restore();

//body
canvas.save();
canvas.translate(100f, 100f);
paint.setColor(Color.RED);
canvas.drawRect(-50, -50, 50, 50, paint);
canvas.restore();

camera.restore();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
}

}
}

Uninstall Adobe AIR application in Linux/Ubuntu

September 11, 2009 by maohao

I am talking about AIR 1.5.2 installer and Ubuntu 9.04 (cat /etc/lsb-release to find out your Ubuntu version).

Simple run the installation package file (*.air, which is basically an zip file) again. If you don’t know where it is (and presumably still in your machine), go to “Applications->Accessories->Adobe AIR Application Installer”, which opens the most recently installed AIR package (*.air), then click “Uninstall”.

Multiple offline devices attached

September 10, 2009 by maohao

This was driving me crazy this morning as I was debugging using G1 phone on Eclipse. Basically the Android AVD Manager sees multiple offline devices attached, although they are all the same device (sometimes it sees one online device sometimes none online device); despite that “adb devices” reports the correct info about device attached.

So basically Mr. Mark Murphy’s suggestion solved my problem:

1. Unplug all devices from computer and shut down all instances of emulators;

2. Run “adb kill-server“;

3. Run “adb devices” and you should see an empty list of devices;

4. Plug back in your device or re-lauch emulator. Now hopefully AVD Manager should now act normally.

Building mix-up custom Android component/widget using Java class and XML layout

August 27, 2009 by maohao

A lot of times you would find it convenient to just create “compound components” or what Commons guy called “meta” widgets.These widgets are compositions of other widgets. Most of the work involved would be to layout those compound components, bind data and wire up controls. For the layout part, it’s convenient to just use mixture of a Java class and a corresponding xml layout file, as opposed to using a pure Java class. Here is how:

1. Create the Java class. It usually extends a Layout class such as a LinearLayout or a RelativeLayout.  You have to define a constructor in the flavor of

public MyHomeBrewedComp(Context context, AttributeSet attr)

If you just use "public MyHomeBrewedComp(Context context)“,  you would get an “java.lang.NoSuchMethodException" error from Console and a “android.view.InflateException: Binary XML file line #nnn: Error inflating class com.mh.android.test.MyHomeBrewedComp" from CatLog at runtime.

2. Create the corresponding xml layout file under the package “res/layout” folder.  This is the xml version of your Java class, which means the root node should be the identical class to your Java class.

3. Layout compound widgets in your enclosing widget. If you are doing layout in the xml file, you will then have to inflate the xml in your java file programmatically. You do this by overriding the widget’s onFinishInflate () method.

@Override
protected void onFinishInflate(){
super.onFinishInflate();
((Activity)getContext()).getLayoutInflater().inflate(R.layout.myhomebrewedComp, this);
//other code comes here, such as wiring up controls
...
}

4. TODO: setting up attributes in the custom widget

5.  Using the widget in XML.  First of all you will need a new namespace when you refer to any property/attribute in your widget; second you have to use the full-qualified class name in the xml file. Here is a sample:

<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res/com.mh.android.test”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>

<com.mh.android.test.MyHomeBrewedComp
android:id=”@+id/panel”
app:velocity=”30″
app: friction=”.7f”
android:orientation=”horizontal”
android:layout_width=”fill_parent”
android:layout_height=”75px”
android:layout_alignParentTop=”true”
/>

</RelativeLayout>

Synchronizing small projects in eclipse

August 17, 2009 by maohao
  • To export the project as a zip: File>General>Archive File;
  • To import it back to the workspace: File>General>Existing Projects into Workspace
    and select the aforementioned zip file. This will result in a new folder in the root of the current workspace.