My name is Juri Strumpflohner and this is my technical blog. I'm a software architect, .Net, Android, Web and Java dev, TDD and best practices promoter and martial arts practitioner.

Recent Posts Subscribe

Dear reader of Juri's TechBlog,
I moved my blog to a new domain and a new hosting solution as well. I'm now blogging on juristr.com.

HowTo: Fade out div after some seconds using jQuery

Today I made a quick change to my blog. I don't know whether many of my readers noticed the possibility of expanding the reading area by clicking on the gray vertical bar which separates the left column with the post content.

Therefore, what I wanted to change was to automatically hide the left navigation bar after a certain amount of time and so to give maximum focus on the written content, which is, after all, the most important part :) .
Shouldn't be a problem with jQuery and so the first Google query brought me directly to StackOverflow (who wonders ;) ). The raised question there is exactly what I needed, I was however not really satisfied by the accepted answer. Its author suggests to use the jQuery's fadeOut method

$("#myDiv").fadeOut(5000);

This however does not cause a delay of 5 seconds but specifies the timespan of the fade-out process itself. Being not satisfied about the answer I went ahead in search of an alternative and came up with this solution, which btw is actually a workaround. What I did is to make use of the "fadeTo" method which allows takes two parameters:
  1. The speed of the process of "fading to". One can indicate milliseconds as well as semantic names like "slow".
  2. The percentage of opacity, where 1 = 100% opacity.
I specified it like
$("#sidebar-column").fadeTo(15000,1).fadeOut(1000);
So the process starts immediately and for 15 seconds it fades (an already 100% opaque container) to 100% opacity, i.e. nothing changes. This to simulate the delay. Then the fadeOut will start for a timespan of 1 second. VoilĂ . You have your delay. Now, of course you can find the "correct" solution, using other jQuery plugins which have been made just for the purpose of creating a delay (like pause(...) ?) etc.

The mentioned solution has some advantages which I'd not disregard:
  • it is a simple one-liner
  • you don't need any additional plugins
Here's my SO contribution.

Android SMS activity doesn't fill phone number

Today while fixing a bug for our current project we develop for the Android phone I found a strange behavior when trying to launch the phone's SMS sender activity. For those of you non-Android-devs, Android has the concept of Intents.

An intent is an abstract description of an operation to be performed. [...]
(from the Android docs)
This is a really nice mechanism. Basically you launch an Intent, specifying what you'd like to do and those activities out there which may be able to respond to your needs will answer. (a bit simplified of course ;) )

So in our code we launched the phones SMS sender activity by specifying the intent as
Intent smsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:3330349"));
smsIntent.setType("vnd.android-dir/mms-sms");

startActivity(smsIntent);
The problem as you can see:

...the phone number that has been passed in the intent-uri is not displayed on the SMS activity as it should. I searched a bit around and well...there shouldn't be "tel:...." in the Uri but rather "smsto:...". Fair enough, although by specifying the type of the intent I'd expect to get it anyway. So what I did is to change the intent Uri to..
Intent smsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("smsto:3330349"));
smsIntent.setType("vnd.android-dir/mms-sms");

startActivity(smsIntent);
..expecting to get it to work now: nothing. Still the same result, the activity opens but there's no phone number displayed. So...?! *confused*
Well, I found that you basically have the following possibilities.
  1. Just specify the Uri. Ok, it's enough, you have all of the needed information encoded in it, but again, additionally specifying the intent type shouldn't be a problem.
    Intent smsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("smsto:3330349"));
    //smsIntent.setType("vnd.android-dir/mms-sms");
    
    startActivity(smsIntent);
  2. Specify the phone number by adding it to the intent bundle data.
    Intent smsIntent = new Intent(Intent.ACTION_VIEW);
    smsIntent.putExtra("address", "3330349");
    smsIntent.setType("vnd.android-dir/mms-sms");
    
    startActivity(smsIntent);
Both will bring you the expected result


I understand, specifying the uri containing the "smsto" and the type is somehow redundant information, but anyway I wouldn't expect that it doesn't work at all.

Creating Test Suites with jUnit 4

A while back I've posted about how to enable the automatic (jUnit 3.8-style) creation of test suites in Eclipse. That was necessary for Eclipse 3.1.2 and previous. With Eclipse 3.2 and newer in combination with jUnit 4 there is no such wizard like with jUnit 3.8 which automatically creates you the test suite class, but you can use annotations for defining the jUnit 4 tests to run. So you basically create your test

public class MyJUnitTest{

   @Before
   public void setUp(){
      //do your setup stuff
   }

   @After
   public void tearDown(){
      //clean up
      //note setUp and tearDown can be named differently as you want
      //I just find it more clear to stick to this naming convention
   }

   @Test
   public void testSomething(){
      //the test
   }
}
...and then you define your test suite.
import org.somepackagename.someprog;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith( Suite.class )
@SuiteClasses( {MyJUnitTest.class} )
public class UnitTests {
}

Then you launch it like you would with any other normal unit test.

I like this grouping in test suites because in this way you go to your main package in your test project and just launch the tests you're interested (unit tests, integration tests...).

The power and simplicity of the Command pattern

Never thought of how to implement an "undo" function? Not that easy, huh? People in our architecture class today came up with quite creative solutions: two separate stacks storing operations, versioning of the object to go back etc... All quite complex. Well, I've thought about that already about a year ago, so it was quite easy for me and there you actually see how simple such a task becomes if you know the right pattern (I'll come to it immediately).

The key is actually to encapsulate the operation and the object the operation acts on. If you encapsulate that within an object you're already pretty much done. Every time you perform an operation you create such an object encapsulating that operation.



If you knew about it already...yes, it's the Command pattern :) . Now the interface above is the standard implementation, but adding undo is not a major difficulty. You can either add the method to the ICommand interface or create another abstract class/interface UndoableCommand using ICommand. Take for instance the operation "make bold" of a word within a document. Applying the Command pattern and adapting it for undo and redo functions is quite simple



For each concrete command you implement the interface. So an example implementation of such a BoldCommand could look like

public class BoldCommand implements ICommand{
   private Word aWord;

   public BoldCommand(Word aWord){
      this.aWord = aWord;
   }

   public void execute(){
      //call some appropriate object that knows how to perform
      //the action, i.e.
      aWord.setBold(true);   
   }

   public void undo(){
      //undoing is easy since we know here what we did previously and
      //we have the reference to the object we acted upon
      aWord.setBold(false);
   }

   public void redo(){
      execute();
   }
}
I guess this should look now pretty obvious to you. Of course this is just a simple code for demonstrating the idea. You need some more sophisticated structures that take care of these command objects. For the undo/redo you'd probably have some list that tracks all of these objects, removes old ones etc...
If you programmed already for the Eclipse platform, you probably came across the IAction interface and Action classes. Well that's one implementation of such a command pattern. They use it quite heavily there.

Now that you know the pattern, think about the solution you came up with previously (2 stacks, operations, undo operations etc..). Quite complicated :) I like this example because I think this example of the undo/redo functionality explains quite clearly the improvement of your code if you know the right - and obviously suitable - pattern.

MapView doesn't fire onLongClick event

Here's another curiosity I came across today while programming on my Android project. I was creating a MapView for displaying some interesting stuff on it.

Update: This post got a bit lengthy due to different problems that popped up while I was writing the post. So if you prefer to jump directly due to the final solution, feel free to do so.

Now there are different events the user may interact when having a map on the screen like just simple clicks or even moves when navigating on the map. So first of all I have my MapActivity class which again loads a MapView on it, defined in some layout xml file. So far so good. For reacting on click or move events I had to override the MapActivities "dispatchOnTouchEvent" method.

public class MyMapActivity extends MapActivity {
   ...
   @Override
   public void onCreate(...){
      super.onCreate(...);
      setContentView(R.layout.mymapviewlayout);

      this.mapView = (MapView)findViewById(R.id.myMapView);
      this.mapView.set....
      ...
      this.mapView.setClickable(true);
      ...
   }

   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
      int actionType = ev.getAction();
      switch (actionType) {
         case MotionEvent.ACTION_MOVE:
       //react properly
              break;
      }

      return super.dispatchTouchEvent(ev);
   }
   ...
}
That worked pretty well. Now comes the strange behavior. I wanted to differentiate the action of a simple click (press down with immediate release) from a longer click (press down, hold a while and then release again). A fast search on the Android docs revealed the "setOnLongClickListener(OnLongClickListener)" method. Pretty nice, so I just needed to implement the listener an that's it? Actually that didn't work I adjusted my view s.t. it sets the necessary flags and implements the correct listeners...
public class MyMapActivity extends MapActivity {
   ...
   @Override
   public void onCreate(...){
      ...
      this.mapView.setClickable(true);
      this.mapView.setLongClickable(true);
      //direct listener implementation
      mapView.setOnLongClickListener(new OnLongClickListener() {
         public boolean onLongClick(View v) {
            //react
            return false;
         }
      });
      ...
   }

   ...
}
...however with no success. The event just didn't fire. I also tried to adapt the overridden dispatchTouchEvent method s.t. it forwards the event to the MapView like
@Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
      int actionType = ev.getAction();
      switch (actionType) {
         case MotionEvent.ACTION_MOVE:
       //react properly
              break;
      }

      return this.mapView.dispatchTouchEvent(ev);
   }
..which would sound plausible, however with no success.

So the final solution I came up with was to add a GestureDetector to my MapActivity and delegate all touch events to that object. The according OnGestureListener implements a couple of event handlers, under which also the "onLongPress(...)" event handler. So I had to change my implementation to the following
public class MyMapActivity extends MapActivity implements OnGestureListener {
   ...
   private GestureDetector gestureDetector;

   @Override
   public void onCreate(...){
      super.onCreate(...);
      setContentView(R.layout.mymapviewlayout);

      this.gestureDetector = new GestureDetector(this);
      this.gestureDetector.setIsLongpressEnabled(true);

      this.mapView = (MapView)findViewById(R.id.myMapView);
      this.mapView.set....
      ...
      this.mapView.setClickable(true);
      ...
   }

   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
      int actionType = ev.getAction();
      switch (actionType) {
         case MotionEvent.ACTION_MOVE:
       //react properly
              break;
      }

      return gestureDetector.onTouchEvent(ev);
   }
   ...

   //other methods of the OnGestureListener interface
   public void onLongPress(MotionEvent e) {
      ActivityUtils.showToast(this, "Pushed down", 3000);
   }
   ...
}
The result after doing a "long click" on the map:

That looks like it works :) . Don't ask me why it didn't work by just attaching the OnLongClickListener on the map and dispatching events to the MapView. It's now 11:40 PM and I think it's time to have a bit of sleep.

Update:
Indeed, it was late last night. Today morning when I launched my MapView the onLongClick worked, but everything else didn't work any more including move events click events etc. The reason is obvious: I forward everything to my GestureDetector wherefore the MapView will never get the events.
Due to a suggestion of Paul (see comments), I checked the inheritance hierarchy of the MapView and it inherits from ViewGroup. The LongClick event is defined on the level of the View object and for some reason the MapView doesn't react on it nor it lets you override the behavior.

So the final solution to the problem is to handle it on your own. What I did is to create my custom MapView which inherits from MapView. On that class I've overriden the onTouch event and made some kind of hack on it to achieve a long-touch event. The approach was basically to measure the time between the MotionEvent.ACTION_DOWN and the MotionEvent.ACTION_UP event.
public class MyMap extends MapView{
   ...

   public MyMapView(Context context, AttributeSet attrs) {
      super(context, attrs);
   }

   @Override
   public boolean onTouchEvent(MotionEvent ev) {
      if(ev.getAction() == MotionEvent.ACTION_DOWN){
         //record the start time
         startTime = ev.getEventTime();
      }else if(ev.getAction() == MotionEvent.ACTION_UP){
         //record the end time
         endTime = ev.getEventTime();
      }

      //verify
      if(endTime - startTime > 1000){
         //we have a 1000ms duration touch
         //propagate your own event
         return true; //notify that you handled this event (do not propagate)
      }
   }

}
What I left out here (since I don't want you to steal your own creativity ;) ) is to handle moves on the map which may also otherwise result in a long click. It's quite simple to fix that.