Monday, March 16, 2015

Optical Illusions Why The Notion of Overnight Success is a Lie


Overview :



“Timing, perseverance, and ten years of trying will eventually make you look like an overnight success.” -Biz Stone, Co-founder of Twitter

5 years, 3 months.

That’s how long it takes Chinese Bamboo to grow to maturity. At its peak, this tree will stretch above the canopy, reaching heights of 80 feet or more. But for the first 1,825 days of its life, it appears to be nothing more than a stubby green shoot protruding from the soil.


That’s because the real growth is happening underground. For 60 months, that green shoot is fighting in an invisible battle, struggling day and night to establish a network of roots strong enough to support what will be a full-fledged tree. Once the root system is stable, the shoot grows rapidly in just 90 days to reach its full potential.


It would be foolish to assume that this bamboo tree matured overnight, when in truth, it is the culmination of over 5 years of struggle. And it is equally foolish to assume that any business or product can be successful without doing the same.


Yet people do just that. In my 20+ years of experience in the software industry, I’ve mentored countless young people. Whether they’re seeking advice on development, design, or entrepreneurship in general, I most commonly find myself having to dispel one misconception in particular: the notion of overnight success.


If there’s one thing nature teaches us, it is this: There is absolutely, unequivocally, no such thing as overnight success.


There may be the appearance of instant success, but that is illusory. True success is always the result of preparation and diligence.


In an age where videos and Tweets can go “viral” overnight, it’s no surprise that instant success seems to be a real phenomenon to many. But what many fail to consider are the months, years, or even decades of toil that made that moment possible.


We must look below the surface, beyond what things seem to be, to see the struggle, the sacrifice, and the failures that made that moment possible.


The universe demands that we all pay our dues. Nothing is for free– least of all success.



Naga is a Chairman & Director at Span Technology Services

Read More »

Monday, February 2, 2015

How To Use UIPageControl with UIScrollView in iOS


Overview :

A UIPageControl presents that set of horizontal dots representing pages. The current page representing the white dots (default color for dots). We can go to the next page or to the previous page.


Steps :
  1. Open Xcode 6.
  2. Create new project.
  3. Select: iOS ⇒ Application ⇒ Single View Application.
  4. Give the project name as PageControl, iPhone as target device and click Finish.
  5. Here, I have Customized the UIPageControl and UIScrollView with UIImageView.
  6. First we add UIScrollView delegate in .h file and declare PageControl, ScrollView and ImageView .h file.
  7. Import the FXPageControl.h and FXPageControl.m class file to the project from
    https://github.com/nicklockwood/FXPageControl
  8. Here, we add Class File for Page Control to give image for the indicator and set space and size for the indicator (dot size and dot space).


  9. In ViewDidLoad Method


- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
images=[[NSArray alloc]initWithObjects:@"image1.png", @"image2.png", @"image3.png", @"image4.png", nil];
///UIScrollView
scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 467)];
scrollView.backgroundColor = [UIColor clearColor];
scrollView.delegate = self;
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;
[scrollView setContentSize:CGSizeMake(scrollView.frame.size.width*images.count, scrollView.frame.size.height)];
/// PageControl
pageControl = [[FXPageControl alloc]init ];
[pageControl setFrame:CGRectMake(110, 540, 100, 36)];
pageControl.defersCurrentPageDisplay = NO;
pageControl.selectedDotColor = [UIColor redColor];
pageControl.backgroundColor = [UIColor clearColor];
pageControl.selectedDotSize = 15.0;
pageControl.dotSize = 11.0;
pageControl.dotColor = [UIColor blueColor];
pageControl.dotSpacing = 10.0;
pageControl.wrapEnabled = YES;
pageControl.selectedDotImage = [UIImage imageNamed:@"selectedslider.png"];
pageControl.dotImage = [UIImage imageNamed:@"unselectedslider.png"];
[pageControl addTarget:self action:@selector(pageChanged) forControlEvents:UIControlEventValueChanged];
UIImageView *dottedImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 434, 320, 27)];
[dottedImage setImage:[UIImage imageNamed:@"dottedline.png"]];
for (int i = 0; i <[images count]; i++)
{
CGRect frame;
frame.origin.x = scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = scrollView.frame.size;
UIImageView *imageView = [[UIImageView alloc] init];
imageView.image = [UIImage imageNamed:[images objectAtIndex:i]];
imageView.frame = frame;
[scrollView addSubview:imageView];
}
pageControl.numberOfPages = images.count;
pageControl.currentPage = 0;
[self.view addSubview:scrollView];
[self.view addSubview:pageControl];
}
10.This Method to change the Page
- (void)pageChanged
{
// pageControl.currentPage=PageIndicator.currentPage;
CGRect frame;
frame.origin.x = scrollView.frame.size.width * pageControl.currentPage;
frame.origin.y = 0;
frame.size = scrollView.frame.size;
[scrollView scrollRectToVisible:frame animated:NO];
}
11.We implement the ScrollView Delegate Method.
- (void)scrollViewDidScroll:(UIScrollView *)_scrollView
{
CGFloat viewWidth = scrollView.frame.size.width;
// content offset - tells by how much the scroll view has scrolled.
int pageNumber = floor((scrollView.contentOffset.x - viewWidth/50) / viewWidth) +1;
pageControl.currentPage = pageNumber;
}



Screenshot :









Udayapandi Mariappan is a Junior Software Engineer at Span Technology Services

Read More »

Wednesday, January 28, 2015

jQuery UI Datepicker Customization


Overview :

The jQuery UI Datepicker is a highly configurable plugin that adds datepicker functionality to our web pages. As we all know, we can customize the style, date format and language, restrict the selectable date ranges and add in buttons and other navigation options easily.

We came across a scenario where we needed the order of the years in the datepicker needs to be descending.

Example :

For a datepicker of the DOB its better if we have the year starting from current year and end in the least value we declare during initialization. i.e. from 2015 to 1955. Where as the original datepicker will have the years staring from the least value we assign i.e. from 1955 to 2015.

This change can be done by making a slight alteration in the base jquery UI script file. The changes are as follows.

There will be a section to generate the month and year header for the datepicker, a function named ‘_generateMonthYearHeader’:


Step 1 :

Find the ‘year selection’ section in that method





Step 2 :

Here the year list generated to display will initially be sorted ascending by default. We are now going to re-sort in descending order.





Step 3 :

We have added a new ‘for’ loop before the list is being created. Here, if the ‘reverseYearRange’ variable is ‘true’ the list will be sorted in descending order and ‘false’ gets a list in ascending i.e. the default order.


Step 4 :

Usage: The reverseYearRange variable should be assigned true where the datepicker is initialized for a textbox.





Note: The above change is made in jquery.ui version 1.8.24. The code snippet we discussed may have to be changed accordingly in the previous or newer versions.


Meyyappan M is a Junior Software Engineer at Span Technology Services

Read More »

Tuesday, January 27, 2015

Google Maps Android Marker Clustering


Overview

By clustering your markers, you can put a large number of markers on a map without making the map hard to read. The marker clustering utility helps you manage multiple markers at different zoom levels. To be precise, the 'markers' are actually 'items' at this point, and only become 'Markers' when they're rendered. But for the sake of clarity, this document will name them 'markers' throughout. When a user views the map at a high zoom level, the individual markers show on the map. When the user zooms out, the markers gather together into clusters, to make viewing the map easier. The marker clustering utility is part of the Google Maps Android API Utility Library. If you haven't yet set up the library, follow the setup guide before reading the rest of this page.

Step1:

In Eclipse goto File ⇒ New ⇒ Android Application Project

Step2:Downloading Google Maps Android API Utility Library.

https://developers.google.com/maps/documentation/android/utility/

Step3: Add a simple marker clusterer.

Here is a summary of the steps required:

  1. Implement ClusterItem to represent a marker on the map. The cluster item returns the position of the marker as a LatLng object.
  2. Add a new ClusterManager to group the cluster items (markers) based on zoom level.
  3. Set the map's OnCameraChangeListener() to the ClusterManager, since ClusterManager implements the listener.
  4. If you want to add specific functionality in response to a marker click event, set the map's OnMarkerClickListener() to the ClusterManager, since ClusterManager implements the listener.
  5. Feed the markers into the ClusterManager.

MyItem.java



package com.example.clustering;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.clustering.ClusterItem;
public class MyItem implements ClusterItem {
private final LatLng mPosition;
public MyItem(double lat, double lng) {
mPosition = new LatLng(lat, lng);
}
@Override
public LatLng getPosition() {
return mPosition;
}
}


MyItemReader.java



package com.example.clustering;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class MyItemReader {
private static final String REGEX_INPUT_BOUNDARY_BEGINNING = "\\A";
public List read(InputStream inputStream) throws JSONException {

List items = new ArrayList();
String json = new Scanner(inputStream).useDelimiter(REGEX_INPUT_BOUNDARY_BEGINNING).next();
JSONArray array = new JSONArray(json);
for (int i = 0; i < array.length(); i++) {

JSONObject object = array.getJSONObject(i);
double lat = object.getDouble("lat");
double lng = object.getDouble("lng");
items.add(new MyItem(lat, lng));
}
return items;

}
}


Step4:

MainActivity.java


package com.example.clustering;
import java.io.InputStream;
import java.util.List;
import org.json.JSONException;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import com.example.googlemapclustering.R;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.clustering.ClusterManager;
public class MainActivity extends Activity {
GoogleMap map;
private ClusterManager mClusterManager;
@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
map.setMyLocationEnabled(true);
map.getUiSettings().setZoomGesturesEnabled(true);
map.moveCamera(CameraUpdateFactory.zoomTo(13.2f));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10));
mClusterManager = new ClusterManager(this, map);
mClusterManager = new ClusterManager(MainActivity.this, map);
map.setOnCameraChangeListener(mClusterManager);
map.setOnInfoWindowClickListener(mClusterManager);
map.setInfoWindowAdapter(mClusterManager.getMarkerManager());
map.setOnMarkerClickListener(mClusterManager);
try {

readItems();
} catch (JSONException e) {
Toast.makeText(this, "Problem reading list of markers.", Toast.LENGTH_LONG).show();
}
}
private void readItems() throws JSONException {
InputStream inputStream = getResources().openRawResource(R.raw.radar_search);
List items = new MyItemReader().read(inputStream);
mClusterManager.addItems(items);
}
}



Step5:

activity_main.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout >



Step6:


res -> raw ->radar_search.json
Sample lat,lng
[
{ "lat" : 51.5145160, "lng" : -0.1270060 },
{ "lat" : 51.5064490, "lng" : -0.1244260 },
{ "lat" : 51.5097080, "lng" : -0.1200450 },
{ "lat" : 51.5090680, "lng" : -0.1421420 },
{ "lat" : 51.4976080, "lng" : -0.1456320 },
{ "lat" : 51.5046150, "lng" : -0.1473780 },
]


Step7:

AndroidManifest.xml


Declare google play service in manifest.xml


<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

<meta¬data
android:name="com.google.android.maps.v2.API_KEY"
android:value="API Key" />

Map permission


<permission
android:name="com.google.maps.android.utils.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />

uses permission:


<uses-permission android:name="com.google.maps.android.utils.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />




Screenshot:




Devarajan M is a Software Engineer at Span Technology Services

Read More »

Monday, January 19, 2015

How To Efficiently Display Annotation Pins on the Same Coordinate on iOS Maps


Overview :

This tutorial will demonstrate how to handle and display Same Coordinate of points of data on an iOS map in a way people understand and enjoy. We are going to make an iOS app which Shopping Center with 100 km areas, each with a coordinate, a name and a phone number and Profile Image. This app will update the map as the user pans and zooms, allowing the user to freely explore the data.


Framework : MKMapKit

Steps :
  1. Open Xcode 6.
  2. Create new project.
  3. Select: iOS, Application, Single View Application.
  4. Give the project a proper name. In the example, I’ve used the following:
    • Product Name: MapAnnotationCircle
    • Organization Name: XXXX
    • Class Prefix: XXX
  5. To keep stuff simple, I’ve selected iPad as target device.
    • Click Next.
  6. Now in project navigator you will find “Main.Storyboard”.
  7. Drag and drop MKMapView and add MKMapKit framework.
  8. Just Control-drag your map to the MapViewController.h file and create an IBOutlet. Let’s name our outlet iMapView.
  9. Import in your header file.
  10. First we group the annotations by coordinate.


for (int i=0; [latitude_MutableArray count]>i; i++)
{
NSString *latStr=[latitude_MutableArray objectAtIndex:i];
NSString *longStr=[longtitude_MutableArray objectAtIndex:i];
double lat=[latStr doubleValue];
double lan=[longStr doubleValue];
customAnnotation = [[BasicMapAnnotation alloc] initWithLatitude:lat andLongitude:lan];
customAnnotation.title =[centerName_MutableArray objectAtIndex:i];
[pinPointAnnotations addObject:customAnnotation];
}
[AnnotationCoordinateUtility mutateCoordinatesOfClashingAnnotations:pinPointAnnotations];
[self.iMapView addAnnotations:pinPointAnnotations];


11. The value of a entry in the dictionary is a NSArray of annotations at that coordinate. You can see this only matches on exactly equal coordinates, but it would be relatively straightforward to group on coordinates that were close by calculating the distance between them. Next we enumerate the NSArray looking for locations that have more than one annotation. When we find one, we reposition the annotations.


+ (void)mutateCoordinatesOfClashingAnnotations:(NSArray *)annotations {
NSDictionary *coordinateValuesToAnnotations = [self groupAnnotationsByLocationValue:annotations]; for (NSValue *coordinateValue in coordinateValuesToAnnotations.allKeys) {
NSMutableArray *outletsAtLocation = coordinateValuesToAnnotations[coordinateValue];
if (outletsAtLocation.count > 1) {
CLLocationCoordinate2D coordinate;
[coordinateValue getValue:&coordinate];
[self repositionAnnotations:outletsAtLocation toAvoidClashAtCoordination:coordinate];
}
}
}
+ (NSDictionary *)groupAnnotationsByLocationValue:(NSArray *)annotations {
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (id pin in annotations) {
CLLocationCoordinate2D coordinate = pin.coordinate;
NSValue *coordinateValue = [NSValue valueWithBytes:&coordinate objCType:@encode(CLLocationCoordinate2D)];
NSMutableArray *annotationsAtLocation = result[coordinateValue];
if (!annotationsAtLocation) {
annotationsAtLocation = [NSMutableArray array];
result[coordinateValue] = annotationsAtLocation;
}
[annotationsAtLocation addObject:pin];
}
return result;
}
+ (void)repositionAnnotations:(NSMutableArray *)annotations toAvoidClashAtCoordination:(CLLocationCoordinate2D)coordinate {
double distance = 3 * annotations.count / 2.0;
double radiansBetweenAnnotations = (M_PI * 2) / annotations.count;
for (int i = 0; i < annotations.count; i++) {
double heading = radiansBetweenAnnotations * i;
CLLocationCoordinate2D newCoordinate = [self calculateCoordinateFrom:coordinate onBearing:heading atDistance:distance];
id annotation = annotations[i];
annotation.coordinate = newCoordinate;
}
}


12. The pins are arranged in a circle around the contested point by dividing the circle by the number of contesting annotations. You can see that the distance from the contested coordinate to the new coordinate is a function of the number of annotations contesting – if there are few pins contesting the coordinate, then we have space to place the pins close to the coordinate.

Finally, the new coordinate is calculated using an implementation of the function from this excellent resource: Destination point given distance and bearing from start point


+ (CLLocationCoordinate2D)calculateCoordinateFrom:(CLLocationCoordinate2D)coordinate onBearing:(double)bearingInRadians atDistance:(double)distanceInMetres {
double coordinateLatitudeInRadians = coordinate.latitude * M_PI / 180;
double coordinateLongitudeInRadians = coordinate.longitude * M_PI / 180;
double distanceComparedToEarth = distanceInMetres / 6378100;
double resultLatitudeInRadians = asin(sin(coordinateLatitudeInRadians) * cos(distanceComparedToEarth) + cos(coordinateLatitudeInRadians) * sin(distanceComparedToEarth) *
cos(bearingInRadians));
double resultLongitudeInRadians = coordinateLongitudeInRadians + atan2(sin(bearingInRadians) * sin(distanceComparedToEarth) * cos(coordinateLatitudeInRadians),
cos(distanceComparedToEarth) - sin(coordinateLatitudeInRadians) * sin(resultLatitudeInRadians));
CLLocationCoordinate2D result;
result.latitude = resultLatitudeInRadians * 180 / M_PI;
result.longitude = resultLongitudeInRadians * 180 / M_PI;
return result;
}

Output :

1. Pins with inside the rectangle





2. After Zooming





Bharathimohan K is a Software Engineer at Span Technology Services

Read More »

View Debugging in Xcode 6


Overview :

Xcode 6 makes debugging your app's user interface much easier with the live view debugging feature. You are now able to pause your running app and dissect the paused user interface in a 3D view. The view debugger shows you your view hierarchy and Auto Layout constraints. If you select a view, you can inspect its properties in the inspector or jump to the relevant code in the assistant editor. With this, you can inspect issues such issues as Auto Layout conflicts, see why a view is hidden or clipped, etc.

To start the live view debugger :

1. Create a new project in Xcode
2. Design a sample page with multiple views under storyboard





3. Now launch your app and click the Debug View Hierarchy button on the debug toolbar.





Your app pauses and you're presented with a 3D visualization of its user interface. You can drag anywhere on the canvas to rotate the view





You can switch between various view states with the buttons below the canvas.

From left to right :

Show Clipped Content: This option hides or shows content that's being clipped in a selected view.

Show Constraints: It shows the Auto Layout constraints of a selected view.

Reset Viewing Area: This resets the canvas to its default state.

Adjust View Mode: This mode lets you select how you want to see your views. There's an option to see it as a wireframe, the view's contents, or both.

Zoom Out, Actual Size, Zoom In: This lets you set the view's scale.


Hyder Ali is a Junior Software Engineer at Span Technology Services

Read More »

Wednesday, January 7, 2015

Expand or Collapse TextView


Overview :

Expand/Collapse of Textview is the useful fuctionality in your application.

You can make a functionality like Expand/Collapse the Textview by clicking the "View More" text which is added at end of the textview.


Step 1 :

Create a new project in Eclipse File ⇒ New ⇒ Android Application Project. Fill in the details and name your project "ExpandTextViewApp".


Step 2 :

Here is a complete example of MainActivity.java


MainActivity.java


package com.sampleviewmore;

import android.app.Activity;

import android.content.Context;

import android.os.Bundle;

import android.widget.TextView;

public class MainActivity extends Activity {

TextView viewMoreTextView;

String ViewMoreString = "Displays text to the user and optionally allows them to edit it. A TextView is a complete text editor, however the basic class is configured to not allow editing; see EditText for a subclass that configures the text view for editing. To allow users to copy some or all of the TextView's value and paste it somewhere else, set the XML attribute android:textIsSelectable to true or call setTextIsSelectable(true). The textIsSelectable flag allows users to make selection gestures in the TextView, which in turn triggers the system's built­in copy/paste controls. If set, specifies that this TextView has a numeric input method and that these specific characters are the ones that it will accept. If this is set, numeric is implied to be true. The default is false.";

Context mContext = MainActivity.this;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

viewMoreTextView = (TextView) findViewById(R.id.ViewMoreOption);

if (ViewMoreString.length() > 300)

ViewMoreText.viewMoreTextView(mContext, viewMoreTextView,

else

}
}


Step 3 :

Coding to manage Expand/Collapse Textview


ViewMoreText.java


package com.sampleviewmore;
import android.content.Context;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.TextView;
import android.widget.TextView.BufferType;
public class ViewMoreText {
static Context mContext;
public static void viewMoreTextView(Context context,
final TextView tv, final String vieString, final int maxLine,
final String expandText, final boolean viewMore) {
mContext = context;
if (tv.getTag() == null) {
tv.setTag(vieString.trim());
}
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
try {
ViewTreeObserver obs = tv.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
if (maxLine == 300) {
String text = vieString.subSequence(0, 300) + " ... ";
SpannableStringBuilder ssb = new
SpannableStringBuilder(
Html.fromHtml(text));
ImageSpan imgSpan = new ImageSpan(mContext,
R.drawable.viewmore);
SpannableStringBuilder spanImage = new
SpannableStringBuilder(
" ");
spanImage.setSpan(imgSpan, 0, 1, 0);
ssb.append(spanImage);
ssb.append(" ");
ssb.append(expandText);
tv.setText("", BufferType.SPANNABLE);
tv.setTextSize(15);
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.append(addClickablePartTextViewResizable(ssb, tv,
vieString, maxLine, expandText,
viewMore));
}
else {
String text = vieString + " ";
SpannableStringBuilder ssb = new
SpannableStringBuilder(
Html.fromHtml(text));
ImageSpan imgSpan = new ImageSpan(mContext,
R.drawable.viewless);
SpannableStringBuilder spanImage = new
SpannableStringBuilder(
" ");
spanImage.setSpan(imgSpan, 0, 1, 0);
ssb.append(spanImage);
ssb.append(" ");
ssb.append(expandText);
tv.setText("", BufferType.SPANNABLE);
tv.setTextSize(15);
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.append(addClickablePartTextViewResizable(ssb, tv,
vieString, maxLine, expandText,
viewMore));
}
} catch (Exception e) {
// TODO Auto­generated catch block
e.printStackTrace();
}
}
});
}
private static SpannableStringBuilder addClickablePartTextViewResizable(
final Spanned strSpanned, final TextView tv,
final String viewString, final int maxLine,
final String spanableText, final boolean viewMore) {
String str = strSpanned.toString();
SpannableStringBuilder ssb = new SpannableStringBuilder(strSpanned);
try {
if (str.contains(spanableText)) {
ssb.setSpan(
new MySpannableText(false) {
@Override
public void onClick(View widget) {
if (viewMore) {
tv.setLayoutParams(tv.getLayoutParams());
tv.setText("",
BufferType.SPANNABLE);
tv.invalidate();
tv.setTextSize(15);
viewMoreTextView(mContext, tv,
­1, "View Less", false);
}
else {
tv.setLayoutParams(tv.getLayoutParams());
tv.setText("",
BufferType.SPANNABLE);
tv.invalidate();
tv.setTextSize(15);
viewMoreTextView(mContext, tv,
300, "View More", true);
}
}
}, str.indexOf(spanableText) ­ 2,
(str.indexOf(spanableText) ­ 2) +
spanableText.length() + 2, 0);
}
} catch (Exception e) {
// TODO Auto­generated catch block
e.printStackTrace();
}
return ssb;
}
}

Step : 4

Coding to differentiate the ViewMore/ViewLess Text


MySpanabbleText.java


package com.sampleviewmore;

import android.graphics.Color;

import android.graphics.Typeface;

import android.text.TextPaint;

import android.text.style.ClickableSpan;

import android.view.View;

public class MySpannableText extends ClickableSpan {

private boolean isUnderline = true;

public MySpannableText(boolean isUnderline) {

this.isUnderline = isUnderline;

}

@Override

public void updateDrawState(TextPaint ds) {

ds.setUnderlineText(isUnderline);

ds.setColor(Color.rgb(53, 144, 6));

ds.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));

}

@Override

public void onClick(View widget) {

}

}


Screenshot :



Neelavathi N is a Junior Software Engineer at Span Technology Services

Read More »

Monday, January 5, 2015

My First SEO Experience with ExpressTruckTax


Overview

You might have known many experiences of your colleagues on their first project, but for each one it is a different experience. It is sure that no one will forget their first project experience and here is mine!

ExpressTruckTax is my first project in STS and my role in this is an SEO Analyst. Though I’m good in SEO basics, I felt nervous because it is my first ever project with no in-hand experience behind me at all, since this is a successful project which have enormous user base. A strong bond developed between me and the domain when I started to learn about it since I like trucks from my childhood.

I felt that I’m liberated in handling it because I had a freedom to do what I wish. I like the fact that this role requires a lot of communication with designers, testers, developers and people working onsite and it is not just sitting behind the desk. I was trying to apply new ideas to it which I got from my training sessions and put them into practice. I felt this role is not just doing SEO, It is more than that..

I decided that, to handle this project effectively, I have to prepare To-Do list every morning before I begin my work. I learnt how to make Social Media work in the way that support website ranking. From the analysis on blog visitors, I felt blog roadmap and series can build a connection among each posts.

I was very keen on updating myself with Google updates since I don’t want any of my activity to violate Search Engine policy which may end up in website penalization someday. I had an idea to add structure data to site but got stuck with a question – How to proceed? Many webmaster forums help me to recover from errors and I got excited when snippet shown in Search Results.

When the peak season started, my first and foremost task turned out to check the website position in search results. I got addicted in checking the website baseline everyday which made me to check it even on weekends. I felt so happy when the position improved just by one and conversely felt bad when it gets decreased. I could effectively observe the support of off page stuffs in website ranking. I understood the importance of promo code submission when I found the large number of visitors came through it in Google Analytics.

My observation in webpage analysis is that the content flow in the webpage can make a visitor to stay connected to it and the breadcrumb navigation can improve the way visitors flawlessly traverse up their way around.

Even when the peak season of my project got over and I’m currently working on other projects, my love towards it never ends. I often monitor the search engine results of it and waiting for the next season of my first project!

Still I need to explore more from Google, A long way around..!


Kanagalakshmi is a Junior SEO Analyst at Span Technology Services

Read More »

Draw Circle around a point on an MKMapView


Overview:

This is simple app that have an MKMapView and want to draw a circle of particular radius around the user entered location. An overlay view allows us to overlay various shapes on top of a map to signify an area of interest, a route followed etc. There are various built in overlay views such as circles, polygons and lines which inherit from MKShape, but it is also possible to create your own shape.  We generally use one of the inbuilt MKShape objects and then use the corresponding MKOverlayView as a visual representation of our shape.

Framework : MKMapKit

Inherits from: MKOverlayView

Adding a Circle:

Steps:
  1. Open Xcode 6.
  2. Create new project.
  3. Select: iOS, Application, Single View Application.
  4. Give the project a proper name. In the example, I’ve used the following:
    • Product Name: MapCircleDemo
    • Organization Name: XXXX
    • Class Prefix: XXX
  5. To keep stuff simple, I’ve selected iPad as target device.
    • Click Next.
  6. Now in project navigator you will find “Main.Storyboard”.
  7. Drag and drop MKMapview and add MapKit framework.
  8. Just Control-drag your map to the ViewController.h file and create an IBOutlet. Let’s name our outlet mapView.
  9. Import <MapKit/MapKit.h> in your header file
  10. We now need to return the MKCircleView to display our MKCircle.  We do this using the delegate method mapView:viewForOverlay:  , Add below code

    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
        if ([overlay isKindOfClass:[MKCircle class]]) {
            MKCircleView *circleView = [[MKCircleView alloc] initWithCircle:(MKCircle*)overlay];
            circleView.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.2];
            circleView.strokeColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
            circleView.lineWidth = 2;
            return circleView;
        }
    }

  11. Design two textfield and get location and radius to draw the circle.
  12. Get location from google places API and get latitude and longitude.
  13. Pass latitude and longitude and radius of circle , Add below code in viewDidLoad.

    int meter = 25*1000;
    MKCircle *circle= [[MKCircle alloc]init];
     circle = [MKCircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(35.26944, -80.84333) radius:meter];
     [self.iMapView addOverlay:circle];


Bharathimohan K is a Software Engineer at Span Technology Services

Read More »