Saturday, April 26, 2014

AngularJs Pass Data Between Controllers

Hello,

This is my first blog on AngularJs. I have been working with AngularJs since last three or four weeks and I am very excited about this Framework. It has nice features like two way data binding, templates, MVVM model, directives. That makes this framework super cool. I will be adding more blogs in future for AngularJs. In this blog I will explain how to pass data between controllers.

For this first we have to understand $rootScope. Every AngularJs application has one root scope and all other scopes are children of root scope. It's like application wide global variable.

Now lets see how we can use this to share data between controllers. First we need a service which is common in both controllers. We will invoke a service function from a controller which wants to send data. Service will broadcast it and using $rootScope. While the receiver controller will listen to the broadcast event and receives that data. First lets crete a service and function.

var servicesModule = angular.module('myapp.broadcastservice', []);

servicesModule.factory('BroadcastService', ['$http', '$rootScope', function ($http, $rootScope) {

   var service = {};
   service.sendData = function(data){

      $rootScope.$broadcast('message', data);
   }

}

Now lets create sender controller.

appRoot.controller('SenderController', ['$scope', 'BroadcastService',
   function ($scope, BroadcastService) {
        $scope.sendData = function(){
              BroadcastService.sendData("My Message");
        }
   }
]);

Now lets create a receiver controller

appRoot.controller('ReceiverController', ['$scope', 'BroadcastService',
    function ($scope, BroadcastService) {
        $scope.$on('message', function(response, data) {
            console.log(data);
       });
    }
]);

As you can see from sender controller we invoke service function and broadcast message with event message and in receiver controller we receive it by listening to message event using $scope.$on.

This way you can pass data between AngularJs controllers. Hope this post helps you.   

Android Slide Menu like Facebook With Effect Like Navigation Drawer

Recently in one our project we have to build slide out menu like Facebook but with some difference. In Facebook app when slide menu opens the main content screen also goes left or right. While in our case main content should stat and menu should come over the content like Navigation Drawer. For certain reasons we could not use Navigation Drawer class as we have the fragments in the application.

So we accomplished it with some different manner. In this blog I will explain you how to do this. First lets see our Main Layout XML file.

&ltcom.myapp.layout.MainLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#221010" >

<!-- This holds our content -->
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

         <FrameLayout
                android:id="@+id/activity_main_content_fragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/white" >
         </FrameLayout>
         <RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="70dip"
                android:alpha="0.9"
                android:background="#d84047"
                android:orientation="horizontal" >

                <Button
                    android:id="@+id/activity_main_content_button_menu"
                    android:layout_width="30dip"
                    android:layout_height="30dip"
                    android:layout_marginBottom="10dip"
                    android:layout_marginTop="18dip"
                    android:background="@drawable/menu"
                    android:onClick="toggleMenu" />
         </RelativeLayout>
    </FrameLayout>

 <!-- This holds our menu -->

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
    </LinearLayout>

</com. myapp.layout.MainLayout>

So in our layout we have FrameLayout with top toolbar with menu button which will open our menu. and a content layout which holds out main content. Now our menu should occupy 70% of available space when it opens so for that we have to set width and height for it. Lets create MainLayout class in app and configure this.

package com. myapp.layout;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.Scroller;


public class MainLayout extends LinearLayout {

int mainLayoutWidth;
private View menu;
private View content;
private int contentXOffset;
private MenuState currentMenuState = MenuState.HIDDEN;
private enum MenuState {
        HIDING,
        HIDDEN,
        SHOWING,
        SHOWN,
};
public MainLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
}

public MainLayout(Context context) {
        super(context);
}

// Overriding LinearLayout core methods
   
   
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);      
        mainLayoutWidth = MeasureSpec.getSize(widthMeasureSpec);
    }
   
    // This is called when MainLayout is attached to window
    // At this point it has a Surface and will start drawing.
    // Note that this function is guaranteed to be called before onDraw
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
       
        // Get our 2 child View
        menu = this.getChildAt(1);
        content = this.getChildAt(0);  
       
        // Initially hide the menu
        menu.setVisibility(View.GONE);

    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
     
        if(changed) {
            LayoutParams contentLayoutParams = (LayoutParams)content.getLayoutParams();
            contentLayoutParams.height = this.getHeight();
            contentLayoutParams.width = this.getWidth();

            // menu View occupies the full height, but certain width
            LayoutParams menuLayoutParams = (LayoutParams)menu.getLayoutParams();
            menuLayoutParams.height = this.getHeight();
            menuLayoutParams.width = mainLayoutWidth;
        }
        // Layout the child views  
       
        menu.layout(left, top, mainLayoutWidth*0.7 , bottom);
        content.layout(left, top, right , bottom);
       
    }

    public void toggleMenu() {
    this.calledFromToggleMenu = true;
        // Do nothing if sliding is in progress
        if(currentMenuState == MenuState.HIDING || currentMenuState == MenuState.SHOWING)
            return;
       
        switch(currentMenuState) {
        case HIDDEN:
        //show menu here
        Log.v("log","current state is hidden");
       
        TranslateAnimation moveLefttoRight = new TranslateAnimation(menu.getWidth()*-1, 0, 0, 0);
       
        moveLefttoRight.setAnimationListener(new Animation.AnimationListener(){
           @Override
           public void onAnimationStart(Animation arg0) {
            menu.setVisibility(View.VISIBLE);
            menu.bringToFront();
           }          
           @Override
           public void onAnimationRepeat(Animation arg0) {
           }          
           @Override
           public void onAnimationEnd(Animation arg0) {
           
           }
        });
       
            moveLefttoRight.setDuration(300);
            moveLefttoRight.setFillAfter(true);
            menu.startAnimation(moveLefttoRight);
            currentMenuState = MenuState.SHOWN;
            break;
        case SHOWN:
        //hide menu here
        Log.v("log","current state is visible");
        TranslateAnimation moveRightoLeft = new TranslateAnimation(0, menu.getWidth()*-1, 0, 0);
        moveRightoLeft.setDuration(300);
        moveRightoLeft.setFillAfter(true);
            menu.startAnimation(moveRightoLeft);
            currentMenuState = MenuState.HIDDEN;
            moveRightoLeft.setAnimationListener(new Animation.AnimationListener(){
           @Override
           public void onAnimationStart(Animation arg0) {
           
           }          
           @Override
           public void onAnimationRepeat(Animation arg0) {
           }          
           @Override
           public void onAnimationEnd(Animation arg0) {
            Log.v("log","hiding menu");
            content.bringToFront();
           }
        });
            break;
        default:
            break;
        }
        // Begin querying
        //menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);
       
        // Invalite this whole MainLayout, causing onLayout() to be called
        //this.invalidate();
    }

}

As you can see in above class we have extended LinearLayout and it's core method and created an extended class. Where onLayout method we are hiding the menu and setting it's width to 70% width of the screen. Key function here is toggleMenu. It identifies the state of the menu and based on that show animation and show/hide the menu. You just have to call toggleMenu function when users taps on button. To close the menu user has to swipe left on the screen and it will close the menu. See the below code.

package com.myapp;
import com.myapp.layout.MainLayout;

public class MainActivity extends FragmentActivity implements
OnTouchListener{
public static MainLayout mainLayout;
      protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_market_place);
mainLayout = (MainLayout) this.getLayoutInflater().inflate(
R.layout.activity_main, null);
setContentView(mainLayout);
                btMenu = (Button) findViewById(R.id.activity_main_content_button_menu);
btMenu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Show/hide the menu
mainLayout .toggleMenu(v);
}
});
      }

      @Override
       public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
super.dispatchTouchEvent(ev);

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN: {
// store the X value when the user's finger was pressed down
downXValue = ev.getX();
downYValue = ev.getY();
Log.v("", "= " + downYValue);
break;
}

case MotionEvent.ACTION_UP: {
// Get the X value when the user released his/her finger
float currentX = ev.getX();
float currentY = ev.getY();
// check if horizontal or vertical movement was bigger

if (Math.abs(downXValue - currentX) > Math.abs(downYValue
- currentY)) {
Log.v("", "x");
// going backwards: pushing stuff to the right

Log.v("log", " downXvalue - currentX "
+ (downXValue - currentX));

if (downXValue < currentX) {
Log.v("", "right");
if (-150 > (downXValue - currentX)) {
Log.v("log", "right if");
mainLayout.toggleMenu("OPEN");
} else {
Log.v("log", "right else");
}
}

// going forwards: pushing stuff to the left
if (downXValue > currentX) {
mainLayout. toggleMenu("CLOSE");

}

} else {
Log.v("", "y ");

if (downYValue < currentY) {
Log.v("", "down");

}
if (downYValue > currentY) {
Log.v("", "up");

}
}
break;
}

}
return true;
}
}

As you can see in above code we are setting MainLayout as content layout for the activity added on click listener for menu button. Which invokes toggleMenu function of mainLayout and toggles the menu. Also we have added dispatchTouchEvent method where we tracking user motion and invoke toggle menu method.

Hope this helps.

Android Use FrameLayout for Overlapping Items

Hello,

Recently in one of my project we have a layout where we have transparent top and bottom bar and which overlaps content of the screen. Content was the list view so when you scroll up or down the list view content goes under overlapping top and bottom bar where we can see it as the both top and bottom bars were transparent. Something like this.


So in this blog I am going to explain how to do this type of layout. I have used FrameLayout for this. As FrameLayout automatically sets the z-index for all it's child items as per the order. So following is our layout XML for this.

 <!-- Main frame layout -->
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

<!-- Main Content layout -->
<LinearLayout
            android:layout_width="fill_parent"
            android:id="@+id/contentPane"
            android:layout_height="wrap_content"
            android:layout_weight="1" >
</LinearLayout>

<!-- Relative Layout for top and bottom bar -->
<RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

<!-- top bar -->
<RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="70dip"
                android:alpha="0.9"
                android:orientation="horizontal" >
 </RelativeLayout>

<!-- Bottom bar -->
<RelativeLayout
                android:layout_width="fill_parent"
                android:layout_alignParentBottom="true"
                android:layout_height="70dip"
                android:alpha="0.9"
                android:orientation="horizontal" >
 </RelativeLayout>

</RelativeLayout>

</FrameLayout>

As you can see in above XML first we have frame layout inside frame layout we have linear layout as our content layout where we have set layout weight property as 1 so this component will take whole space for the frame layout.  After that we have used Relative layout and inside it we have or top and bottom bar as relative layout for bottom bar we are using android:layout_alignParentBottom config and set is true so it will go to bottom.  This is how you can have overlapping views in android.  Hopw this helps you.



Monday, April 21, 2014

Cordova build JAR File From Source Code (For MAC OSX only)

As we know that now Cordova only support command line interface. Earlier with download you get cordova.jar file, that you can directly import to eclipse project and create android cordova file. Now with new download you only get source code, you have to manually generate cordova.jar file and import to eclipse. In this blog I will explain you the steps. First download Cordova source code from the Download.

Extract the content on the desktop. Now you will need following two things.

Apache Ant 1.8.0 or greater
Android SDK which you can download from Android Developer Portal

Download and extract SDK to desktop. Now we will install apache ant. Open the terminal and run following command.

ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

After homebrew is installed we will install ant.

brew install ant

Now ant is installed, we will configure modify paths in bash profile file for android SDK. Run following command in terminal

nano ~/.bash_profile

Go to and of the file and paste following code.


export PATH=/Users/yourusername/Desktop/adtdirectotyname/sdk/tools:$PATH

Click Control+X, Y, Enter. It will save your new file. Now go to your Cordova source code and go to cordova-android/framework and run following command.

android update project -p . -t android-19
ant jar

And it will generate cordova .jar file in the framework folder, you can use that file in your eclipse.

Saturday, April 19, 2014

How to solve MySql errorno : 150 "Can't Create Table"

Recently I faced one issues while creating tables in database. I was adding primary and foreign key in tables and I get errorno : 150 "Can't Create Table" I took almost couple of hours to resolve that error so in this blog I am going to explain what could be possible cause for this error. If you get this error check following possible cause.

1) The two tables must have same storage ENGINE

As we know we can configure storage engines like MyISAM, InnoDB. When you add foreign key to the table both parent and reference table should have same storage engine.

2) The two tables must have the same charset.

MySql supports more than 30 character sets. Both parent and reference table should have the same charset.

3) Primary key and Foreign key column must have same datatype.

When you add a foreign key, the primary key in parent table must have the same datatype as foreign key. For example if you have following definition of primary key

id INT UNSIGNED NOT NULL AUTO_INCREMENT

then you must define foreign key as

pk_id INT UNSIGNED NOT NULL

Else it will give you an error and will not work.

4) Primary key and Foreign key column must have same collation type

MySql supports more than 70 collation type. To define primary key and foreign key both columns should have same collation type

5) If there is already data is must match 

If there are already data in both the tables it should match otherwise MySql will not allow to add foreign key. If there is data inconsistency, first delete the inconsistent data and then add primary key.

6) If the reference column is part of composite primary key, it may not work.

If the referenced column is part of composite primary key it may not work so if it's not required to have composite primary key, just define single column as primary key.

Hope this helps you.

Add Tap Hold Event in Sencha Touch panel

Recently in one of my project, requirement was to display context menu when user tap and hold on sencha touch panel. We all know we can add itemtphold event on sencha touch list. But in my case I have to use panel. In this blog I will explain how to add tap hold event to sencha touch list.

The logic is simple , first of all we have to bind touchstart and touchend event on panel. When touch starts we will check after some interval if touchend event is fired or not. If there is no touch event fired that means user is still holding tap. See the code below.

{
      xtype: 'panel',
      html: 'tap and hold',
     listeners: {
                            painted: function(element){
                            var isTouch = false;
                            element.on({
                            touchstart: function(){
                            isTouch = true;
                            setTimeout(function(){
                            if(isTouch == true){
                                 //There is a tap hold
                            }
                            }, 2000);
                            },
                            touchend: function(){
                            isTouch = false;
                            }
                            });
                            }
                            }
}

As you can see in above code after touch start event we are setting timeout to check isTouch variable after two seconds. You can change the interval according to your need. If touch ends before two seconds we set isTouch to false. So after timeout when this variable is checked you will get false and tap hold event is not fired.  This way you can add tap hold event to any of the sencha touch component.