Understanding Model-View-Controller

I was listening to a podcast on software architecture, where they were discussing the MVC and other architectures, when I decided to write this post. This post discusses what MVC architecture is and how it works.

History

As always, here’s the mandatory history lesson. The MVC architecture was invented by a Smalltalk programmer named Trygve Reenskaug. In his words,

The essential purpose of MVC is to bridge the gap between the human user’s mental model and the digital model that exists in the computer.

Model

Models represent knowledge. A model could be a single object (rather uninteresting), or it could be some structure of objects.

The model represents knowledge. It is the data that will be displayed in the view.

View

A view is a (visual) representation of its model.

The view is what the user sees. The view works with the model to get the necessary data to display. When the model data changes, the view changes.

Controller

A controller is the link between a user and the system.

The controller receives such user output, translates it into the appropriate messages and pass these messages onto one or more of the views.

The controller translates the user’s interactions with the view into actions that the model will perform. In a stand-alone GUI client, user interactions could be button clicks or menu selections, whereas in an enterprise web application, they appear as GET and POST HTTP requests.

To sum it up, here’s how MVC works:
Model: what to render,
View: how to render,
Controller: user inputs

To put it graphically, here’s the image from Trygve Reenskaug’s paper:
MVC
Conceptually, the user is manipulating the data model directly as is shown by the blue line. In reality, however, the user’s interaction with the model is via the controller which is translating the user actions like clicks to actions on the method.

Putting it all together

The view registers as a listener on the model. Any changes to the underlying data of the model immediately result in a broadcast change notification, which the view receives. The model is not aware of the view or the controller — it simply broadcasts change notifications to all interested listeners. The controller is bound to the view. This typically means that any user actions that are performed on the view will invoke a registered listener method in the controller class. The controller is given a reference to the underlying model.

Once a user interacts with the view, the following actions occur:
The view recognizes that a GUI action — for example, pushing a button or dragging a scroll bar — has occurred, using a listener method that is registered to be called when such an action occurs.
The view calls the appropriate method on the controller.
The controller accesses the model, possibly updating it in a way appropriate to the user’s action.
If the model has been altered, it notifies interested listeners, such as the view, of the change.

Source: http://www.oracle.com/technetwork/articles/javase/index-142890.html#2

So thats’s it on MVC๐Ÿ™‚

Context Menus in Android Part 3

In this last post of the 3 part series, I will be showing you how to create a popup menu. A popup menu displays a modal window that is anchored to a specific view. It appears below the view or aboove it if there is no room. Like the previous two posts, I will be using a ListView and the menu will provide the user with the option to delete the list item. Let’s begin.

Step 1: Create the menu

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/delete"
        android:title="Delete" />
</menu>

Step 2: Create an adapter

import android.content.Context;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.PopupMenu;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SimpleAdapter extends BaseAdapter{
    private Context context;
    private String[] data;

    public SimpleAdapter(Context context, String[] data){
        this.context = context;
        this.data = data;
    }
    //----------------------------------------------------------------------------------------------
    @Override
    public int getCount() {
        return data.length;
    }
    //----------------------------------------------------------------------------------------------
    @Override
    public Object getItem(int position) {
        return data[ position ];
    }
    //----------------------------------------------------------------------------------------------
    @Override
    public long getItemId(int position) {
        return position;
    }
    //----------------------------------------------------------------------------------------------
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if( convertView == null ){
            LayoutInflater inf = LayoutInflater.from(parent.getContext());
            convertView = inf.inflate(R.layout.list_item,parent,false);
        }

        TextView text = (TextView) convertView.findViewById( R.id.text );
        ImageButton anchor = (ImageButton) convertView.findViewById(R.id.anchor);

        text.setText(data[position]);
        final PopupMenu menu = initPopup( anchor );

        anchor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                menu.show();
            }
        });

        menu.setOnMenuItemClickListener( new IndexedMenuItemClickListener(position) );

        return convertView;
    }
    //----------------------------------------------------------------------------------------------
    private void delete( int index ){
        List<String> newDataList = new ArrayList<>();
        Collections.addAll(newDataList,data);
        newDataList.remove( index );
        data = new String[ data.length - 1 ];
        newDataList.toArray( data );
        notifyDataSetChanged();
    }
    //----------------------------------------------------------------------------------------------
    private PopupMenu initPopup(View anchor){
        PopupMenu menu = new PopupMenu(context,anchor);
        menu.getMenuInflater().inflate(R.menu.context_menu,menu.getMenu());
        return menu;
    }
    //----------------------------------------------------------------------------------------------
    private class IndexedMenuItemClickListener implements PopupMenu.OnMenuItemClickListener{

        private int index;

        public IndexedMenuItemClickListener(int index){
            this.index = index;
        }

        @Override
        public boolean onMenuItemClick(MenuItem item) {
            delete( index );
            return true;
        }
    }
    //----------------------------------------------------------------------------------------------
}

Apart from overriding the usual methods of the BaseAdapter, there are a few extra methods. delete( ) deletes the item at a given index. initPopup( ) creates and returns a popup menu. In the getView( ) method, we wire the menu with the anchor view. When the anchor view is clicked, the menu is displayed by calling its show( ) method.

We need to be able to listen to the menu item being selected and for that we need a MenuItemClickListener. There’s a private class named IndexedMenuItemClickListener which takes an index of the list item it is associated with and handles the menu item click.

In your activity, all you need to do is set the adapter for the list.

The end result:
screen1

Context Menus in Android Part 2

Continuing my series on contextual menus, we will be talking about contextual action bar. Contextual action bars can be activated by long clicking on either a specific view or by long clicking on an item in a list or a grid. In this post, I will be talking about creating contextual action bar (CAB, for short) that works with ListView. Creating a CAB to work with a list is a slightly involved process requiring us to wire together a few parts. Let’s get right into it.

Step 1: Create a custom adapter

We need to create a custom adapter that keeps track of selected items in the list. I have made a class named SelectableArrayAdapter that extends BaseAdapter. Here’s the code:

import android.content.Context;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class SelectableArrayAdapter extends BaseAdapter{

    private SparseArray<Boolean> selectedItems = new SparseArray<>();
    private String[] data;
    private Context context;

    public SelectableArrayAdapter(Context context, int resource, String[] objects) {
        data = objects;
        this.context = context;
    }


    public void setSelection(int index,boolean isSelected){
        if( isSelected ){
            selectedItems.put(index, isSelected);
        }else{
            removeSelection( index );
        }
        notifyDataSetChanged();
    }

    public void removeSelection(int position){
        selectedItems.remove(position);
        notifyDataSetChanged();
    }

    public void clearAllSelections(){
        selectedItems.clear();
        notifyDataSetChanged();
    }

    public boolean isSelected(int index){
        Boolean result = selectedItems.get(index);
        return result == null ? false : result;
    }

    public void deleteSelectedItems(){
        String[] newData;
        List<String> newDataList = new ArrayList<>();
        Set<Integer> selected = getSelectedPositions();

        for(int i = 0; i < data.length; i++){
            if(!selected.contains(i)) newDataList.add( data[i] );
        }

        newData = new String[ newDataList.size() ];
        newDataList.toArray( newData );
        data = newData;


        selectedItems.clear();
        notifyDataSetChanged();
    }

    public Set<Integer> getSelectedPositions(){
        int size = selectedItems.size();
        Set<Integer> integers = new HashSet<>();
        for(int i = 0; i < size; i++){
            integers.add( selectedItems.keyAt(i) );
        }
        return integers;
    }

    public int getSelectedCount(){
        return selectedItems.size();
    }

    @Override
    public int getCount() {
        return data.length;
    }

    @Override
    public Object getItem(int position) {
        return data[ position ];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    // http://stackoverflow.com/questions/31590714/getcolorint-id-deprecated-on-android-6-0-marshmallow-api-23
    @Override
    public View getView(int position,View convertView,ViewGroup parent){

        if(convertView == null){
            LayoutInflater inf = LayoutInflater.from(parent.getContext());
            convertView = inf.inflate(android.R.layout.simple_list_item_1,parent,false);
        }

        int bgColor = isSelected( position ) ?
                        ContextCompat.getColor(context,android.R.color.holo_blue_light) :
                        ContextCompat.getColor(context,android.R.color.background_light);
        convertView.setBackgroundColor( bgColor );
        ((TextView)convertView).setText( data[position] );
        return convertView;
    }
}

Step 2: Create the menu file

The menu file is simple with a delete item. Here’s the XML:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_action_delete"
        app:showAsAction="ifRoom|withText"
        android:title="Delete" />
</menu>

Step 3: Creating MultiChoiceModeListener

The contextual actions provided to the user are a system implementation of ActionMode. The ActionMode represents the contextual mode of the UI. Since we are working with a list, we need to be able to deal with muliple views being selected simultaneously and take an appropriate action on them. To do that, we use MultiChoiceModeListener which will receive the events from the ActionMode and let us process them.

I created a class named MultiChoiceListener and implemented the MultiChoiceListener interface. The code looks like this:

import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.AbsListView;


public class MultiChoiceListener implements AbsListView.MultiChoiceModeListener{
    private SelectableArrayAdapter adapter;

    public MultiChoiceListener(SelectableArrayAdapter adapter){
        this.adapter = adapter;
    }

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
        // Here you can do something when items are selected/de-selected,
        // such as update the title in the CAB
        adapter.setSelection(position,checked);
        int count = adapter.getSelectedCount();
        String title = "";
        title = count == 1 ? " item selected" : " items selected";
        title = count + title;
        mode.setTitle( title );
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate the menu for the CAB
        MenuInflater inf = mode.getMenuInflater();
        inf.inflate(R.menu.context_menu,menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        // Here you can perform updates to the CAB due to
        // an invalidate() request
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        // Respond to clicks on the actions in the CAB
        switch( item.getItemId() ){
            case R.id.delete:
                adapter.deleteSelectedItems();
                mode.finish();
                return true;
            default:
                return false;
        }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        // Here you can make any necessary updates to the activity when
        // the CAB is removed. By default, selected items are deselected/unchecked.
        adapter.clearAllSelections();
    }
}

Here is how it works:
onItemCheckedStateChanged() let’s us handle the selection and deselection of list items. In our case, we just let the adapter keep track of it for us. We then update the title using the setTitle( ) of the ActionMode.

onCreateActionMode( ) lets us inflate the menu that will be shown to the user. We use a menu inflater to inflate the menu and return true to indicate that we have created the menu.

onPrepareActionMode lets us update the CAB dynamically. In our case, there isn’t anything to do so we simple return false.

onActionItemClicked( ) is where the magic happens. Similar to onOptionsItemSelected( ), we switch the menu ID and take an action. Since we only have a delete option, we delete the data from the adapter and return true.

Finally, in onDestroyActionMode( ), we update the adapter to clear all selections.

Step 4: Wiring it all together

Wiring it all together is surprisingly easy. In your activity

list = (ListView) findViewById(R.id.list);
list.setAdapter( selectableAdapter ); 
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list.setMultiChoiceModeListener(new MultiChoiceListener( selectableAdapter ));

The result looks like this:
screen1

In the next post we will be looking at popup menus๐Ÿ™‚

Context Menus in Android Part 1

Menus are a common UI component that present a list of options to the user. These may be generic menus providing a set of general options or contextual menus that provide options that are specific to a particular view. In this post I will be talking about contextual menus. There are three ways in which contextual menus may be shown.

  • As a floating menu – this is what you see when you long press a WhatsApp conversation
  • As a contextual action bar – this is what you see when you long press some text. The “Cut”, “Paste”, etc. options that show up at the top of the screen are the contextual action bar.
  • As a popup menu – this is what you see when you click on the overflow icon (three vertical dots). Popup menus are anchored to a specific view

I will be splitting each of these three methods into a post of its own, beginning with a floating menu. Let’s get right into it.

XML for floating menu

The XML for context menu is rather simple. It’s a single item to delete the data.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/delete"
        android:title="Delete" />
</menu>

Layout for activity

The layout for activity is a ListView nested inside a parent RelativeLayout. I am using ListView over RecyclerView for the sake of simplicity. Here’s the layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin">

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>

Code for the activity

Here’s the code for the activity that I will be explaining subsequently:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListView list;
    private List<String> items = getItems( 20 );
    String[] itemsAsArray;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        list = (ListView) findViewById(R.id.list);
        setAdapter();
        registerForContextMenu( list );
    }
    //----------------------------------------------------------------------------------------------
    private List<String> getItems( int count ){
        List<String> items = new ArrayList<>();
        for(int i = 0; i < count; i++){
            items.add( "Item: " + i );
        }
        return items;
    }
    //----------------------------------------------------------------------------------------------
    private void setAdapter(){
        itemsAsArray = new String[ items.size() ];
        items.toArray( itemsAsArray );
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,itemsAsArray);
        list.setAdapter( adapter );
    }
    //----------------------------------------------------------------------------------------------
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
                                    ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu,v,menuInfo);
        MenuInflater inf = getMenuInflater();
        inf.inflate(R.menu.context_menu,menu);
    }
    //----------------------------------------------------------------------------------------------
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        long index = ((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).id;
        switch( item.getItemId() ){
            case R.id.delete:
                items.remove( items.get((int) index) );
                setAdapter();
                return true;
            default:
                return false;
        }
    }
    //----------------------------------------------------------------------------------------------
}

We have a method named getItems( ) which generates some dummy items. These are stored in a List that we eventually convert into an array and pass to an ArrayAdapter.

The registerForContextMenu( ) method lets us specify which view will be showing the context menu when it is long pressed. In our case, it is the ListView. Having registered the view, we still have two things to do: populating the menu, and handling menu item clicks and for that we use onCreateContextMenu( ) and onContextItemSelected( ) methods, respectively.

In the onCreateContextMenu( ), we inflate the menu using MenuInflater similar to how we would do it in onCreateOptionsMenu. Here we are inflating the menu that we created at the start of the post. In onContextItemSelected( ) we first retrieve the index of the list item for which the context menu was displayed, and then we remove it from the list of data that we have.

The end result looks like this:

screen1

In the next post I will be talking about contextual action bars.๐Ÿ™‚

Understanding CoordinatorLayout

Android’s design library includes the CoordinatorLayout. It is similar to FrameLayout with some added super powers. In this post we’ll be looking at CoordinatorLayout and how it works.

Let’s begin with a simple example.

Step 1: Add design library to your build.gradle

compile 'com.android.support:design:23.1.1'

Step 2: Create a simple layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.FloatingActionButton
        android:src="@drawable/ic_action_share"
        android:id="@+id/fab"
        android:layout_gravity="bottom|center_horizontal"
        android:layout_width="wrap_content"
        android:layout_margin="16dp"
        android:layout_height="wrap_content" />

</android.support.design.widget.CoordinatorLayout>

Step 3: Show a Snackbar when FAB is clicked

public class MainActivity extends AppCompatActivity {
    private FloatingActionButton fab;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(v,"This is a snackbar",Snackbar.LENGTH_LONG).show();
            }
        });
    }
}

The first thing that you’ll notice is that the FAB changes its position to accomodate the snackbar. This is made possible by CoordinatorLayout. Another, not-so-visible, behavior is that you can swipe the snackbar out of the screen. Again made possible by CoordinatorLayout. If you were to use LinearLayout instead, this wouldn’t work.

What is all this magic?

The real power of CoordinatorLayout is in CoordinatorLayout.Behavior class. This class defines how one view behaves with respect to another. If you look at the soure code of FAB, you’ll come across this:

public static class Behavior extends CoordinatorLayout.Behavior<FloatingActionButton>

There are two main methods here:

  • layoutDependsOn( )
  • onDependentViewChanged( )

The layoutDependsOn( ) method is used to see if two views depend on each other. In case of FAB, the layout depends upon AppBarLayout and SnackbarLayout.

If there is a dependency between the two views, then there has to be a way to update one view with respect to another. onDependentViewChanged( ) does just that. Quoting the docs:

This method is called whenever a dependent view changes in size or position outside of the standard layout flow. A Behavior may use this method to appropriately update the child view in response.

In case of FAB and snackbar, FAB changes its Y-coordinate with respect to snackbar.

Wait, there is more…

CoordinatorLayout is also used with AppBarLayout, Toolbar, and a scrolling view to create the effect of a disappearing toolbar. For the scrolling view to affect the toolbar, AppBarLayout expects a app:layout_behavior attribute which provides a fully qualified name of the class that implements the behavior.

CoordinatorLayout also provides layout_anchor and layout_anchorGravity attributes which can be used to glue one view, such as FAB, to another. This way, if the view moves, FAB moves along with it.

And finally, CoordinatorLayout allows you to create collapsing toolbars when used in conjunction with Toolbar, AppBarLayout, and CollapsingToolbarLayout

In Summary

In this post we have looked at CoordinatorLayout and its Behavior class. It is this Behavior class that gives CoordinatorLayout its magic powers. In the next post, we will look at using the AppBarLayout to create a disappaering toolbar.

Sliding Views in Android

One of the best ways to learn Android is to try and replicate the system apps without looking at their source code. I was replicating the alarm clock app and one of the features that intrigued me was to swipe a slider to either snooze or cancel the alarm. After some research (read “StackOverflow”), I was able to make it work. In this post I will be explaining how I made it.

To begin, make an activty. Since we are replicating the slider’s behavior, we need three main views in our layout – a slider thumb and two views on either sides that represent the options. My layout looks like this:

	<FrameLayout
	    xmlns:android="http://schemas.android.com/apk/res/android"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent">
	    <RelativeLayout
	        android:padding="@dimen/activity_horizontal_margin"
	        android:layout_width="match_parent"
	        android:layout_height="match_parent">

	        <ImageButton
	            android:id="@+id/snooze"
	            android:src="@drawable/ic_action_snooze"
	            android:background="@drawable/circle"
	            android:layout_centerVertical="true"
	            android:layout_alignParentLeft="true"
	            android:layout_width="72dp"
	            android:layout_height="72dp" />

	        <View
	            android:id="@+id/slider"
	            android:layout_centerInParent="true"
	            android:layout_width="72dp"
	            android:layout_height="72dp"
	            android:background="@drawable/circle" />

	        <ImageButton
	            android:id="@+id/cancel"
	            android:src="@drawable/ic_action_cancel"
	            android:background="@drawable/circle"
	            android:layout_centerVertical="true"
	            android:layout_alignParentRight="true"
	            android:layout_width="72dp"
	            android:layout_height="72dp" />

	        <TextView
	            android:id="@+id/time"
	            android:layout_above="@id/slider"
	            android:layout_centerVertical="true"
	            android:layout_centerHorizontal="true"
	            android:textSize="64sp"
	            android:layout_marginBottom="@dimen/activity_vertical_margin"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content" />
	    </RelativeLayout>

	    <TextView
	        android:id="@+id/action"
	        android:background="?attr/colorPrimaryDark"
	        android:textColor="@android:color/white"
	        android:visibility="invisible"
	        android:gravity="center"
	        android:layout_gravity="center"
	        android:textSize="64sp"
	        android:layout_width="match_parent"
	        android:layout_height="match_parent" />
	</FrameLayout>

Here snooze and cancel are the options and slider is the actual slider thumb. I used a simple shape drawable to give them a circular look. These are the main components I will be focussing on. The rest are just there to give it a more alarm clock appearance. With this layout, my screen looks like this:

screen1

In onCreate( ), after having set the layout and retrieved references to the views, create a android.graphics.PointF object. This represents the original position of our slider thumb. We will use this to bring the slider thumb back to its original position when the user lifts the finger. Create the PointF object as follows:

PointF ref = new PointF(slider.getX(),slider.getY());

Now we need to create a class that will implement View.OnTouchListener and provide the appropriate behavior. Create a class named SliderListener, implement View.OnTouchListener, and override the onTouch( ) method. The skeletal class should look like this:

public class SliderListener implements View.OnTouchListener{
	@Override
    public boolean onTouch(View v, MotionEvent event) {

	}
}

We want this class to handle the touch for the slider thumb and also know when the slider thumb is over the left or the right options. We also want this class to be able to communicate back which option was selected. To do this, I created an interface inside SliderListener with two methods: onLeftSelected and onRightSelected. With this addition, the class should look like this:

public class SliderListener implements View.OnTouchListener{
	@Override
    public boolean onTouch(View v, MotionEvent event) {

	}
	//------------------------------------------------------------------------------------------
	interface OnSliderOptionSelectedListener{
        void onLeftSelected();
        void onRightSelected();
    }
}

SliderListener has no knowledge of the views it will be managing. So we will create a constructor that takes in 5 parameters – the left view, the slider thumb view, the PointF object representing the original position, the right view, and a OnSliderOptionSelectedListener. With this addition, the class should look like:

public class SliderListener implements View.OnTouchListener{
	private View left;
    private View right;
    private View slider;
    private PointF reference;
    private OnSliderOptionSelectedListener listener;
    //------------------------------------------------------------------------------------------
    public SliderListener(View left, View slider, PointF reference, View right,
                          OnSliderOptionSelectedListener listener){
        this.left = left;
        this.reference = reference;
        this.right = right;
        this.slider = slider;
        this.listener = listener;
    }
    //------------------------------------------------------------------------------------------
	@Override
    public boolean onTouch(View v, MotionEvent event) {

	}
	//------------------------------------------------------------------------------------------
	interface OnSliderOptionSelectedListener{
        void onLeftSelected();
        void onRightSelected();
    }
}

We need two additional PointF objects inside SliderListener to keep track of the user’s finger. Add the following two global variables:

private PointF touchDown = new PointF();
private PointF touchStart = new PointF();

We need a method to find out if the slider is within the bounds of either the left or the right view. So, add the following method to SliderListener:

private boolean isWithinBounds(float x,float y,View v){
    float viewX = v.getX();
    float viewY = v.getY();
    boolean isWithinBounds = true;

    isWithinBounds &= (x >= viewX && x <= viewX + v.getWidth());
    isWithinBounds &= (y >= viewY && y <= viewY + v.getHeight());

    return isWithinBounds;
}

Finally, onTouch( ) is where magic happens. Here’s the code which I will explain subsequently:

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch( event.getAction() ){
        case MotionEvent.ACTION_MOVE:
            PointF mv = new PointF( event.getX()-touchDown.x, event.getY()-touchDown.y );
            float newX = touchStart.x + mv.x;
            if( newX < left.getX() ){
                v.setX( left.getX() );
                touchStart = new PointF( v.getX(),v.getY() );
            }else if( newX > right.getX() ){
                v.setX( right.getX() );
                touchStart = new PointF( v.getX(),v.getY() );
            }else{
                v.setX( newX );
                touchStart = new PointF( v.getX(),v.getY() );
            }
            break;
        case MotionEvent.ACTION_DOWN:
            touchDown.x = event.getX();
            touchDown.y = event.getY();
            touchStart = new PointF( v.getX(),v.getY() );
            break;
        case MotionEvent.ACTION_UP:
            int sliderCenterX = (int) (slider.getX() + (slider.getWidth()/2));
            int sliderCenterY = (int) (slider.getY() + (slider.getHeight()/2));
            if( isWithinBounds(sliderCenterX,sliderCenterY,left) ){
                listener.onLeftSelected();
            }else if( isWithinBounds(sliderCenterX,sliderCenterY,right) ){
                listener.onRightSelected();
            }else{
                v.animate().translationX(reference.x).setDuration(250).start();
            }
            break;
        default:
            break;
    }
    return true;
}

The easiest case to understand is ACTION_DOWN. Here we begin keeping track of the x and y coordinates of the finger.

In case ACTION_UP we have to decide what action the user has selected or not selected anything at all. We do so by first finding out the center of the slider. We then check if the center is within the bounds of either of the views. Using the center of the slider ensures that the listener gets called only when the slider is at least halfway through the other view. If the user lifted the finger without choosing any option, we just animate the slider back to its original position.

Case ACTION_MOVE is the slightly more involved one. We begin by calculating how far the finger has moved. If the slider moved to the right, this would be a positive value. If the slider moved to the left, this would be a negative value. We then calculate the new x coordinate for the the slider. The if conditions ensure that the slider cannot be slid out of the screen. The maximum they can slide is as far as each of the options. We update the touchStart variable to get the proper x value next time around.

Heading back to the activity, implement the SliderListener.OnSliderOptionSelectedListener interface and override its methods. Provide an appropriate definition. Finally, do this:

slider.setOnTouchListener( new SliderListener(snooze,slider,ref,cancel,this) );

Done!๐Ÿ™‚

Complete code for SliderListener can be found at: https://gist.github.com/littlejavachild/ae179e167a08d36365d2

Android Interview Questions – Ultimate Guide (The Manifest)

1. What is AndroidManifest.xml?
The AndroidManifest.xml file provides essential information about your application that the system must have before it can run any of the app’s code. This information includes the screens the app supports, the permissions it needs, etc.

2. What is the root element in the manifest file?
The root element of the manifest file is manifest. This element specifies the package name for your app, the version code, the version name, install location, etc.

3. What is the significance of the application element?
The application element is the declaration of your application. This element has sub-elements that declare the components of your application like activities, receivers, etc. It also specifies the title for your app that will be displayed in the launcher, the icon, the theme, etc.

4. How would you list all the activities in your application?
To list all the activities that the application has, an activity element, per activity, will need to be added to the application element. The android:name attribute would be set to the class name of the activity. For example:

<application...>
<activity android:name=".ActivityOne" android:label="@string/title1"/>
<activity android:name=".ActivityTwo" android:label="@string/title2"/>
</application>

5. How would you list all the services in your application?
For every service that the application has, add a service element as a child of the application element. For example,

  
<application ..>
<service android:name=".MyService" android:enabled="true" />
</application>

6. How would you list all the broadcast receivers in your application?
For every broadcast receiver, add a receiver element to the application element. For example,

<application ...>
<receiver android:name=".MyStartServiceReceiver" />
</application>

7. What does the uses-permission element do?
The uses-permission element specifies the permission that the application needs. It is a sub-element of the manifest element. If the application needs permission to access the internet, for example, it will do it as follows:

<manifest ...>
<uses-permission android:name= "android.permission.INTERNET" />
</manifest>

8. How would you create a custom permission?
To create a custom permission, we first need to declare it in our app like so:

<permission android:name="your.namespace.permission.TEST" 
android:protectionLevel="normal" android:label="This is my custom  permission" />

and then, other applications can ask for that permission as follows:

<uses-permission android:name="your.namespace.permission.TEST" />

9. What is the use of permission-group element?
permission-group allows us to define a logical grouping of permissions. Members of the group are presented together in the user interface. For more, http://stackoverflow.com/questions/17371326/what-is-the-use-of-permission-group-in-android

10. How would you specify the screens your app supports?
The supports-screens element specifies all of the screens sizes that the application supports. That is, all of the screen sizes on which the layouts will work properly.

11. What do the receiver and provider tags do?
The receiver element specifies all the broadcast receivers that are a part of the app and the provider element specifies the content providers that are a part of the app.

Android Interview Questions – Ultimate Guide (The Basics)

1. What is the structure of an Android project in Eclipse?
Android Project

Image taken from TutsPlus

The src folder contains all the source code.
The gen folder contains all the auto-generated classes. The R class is in this folder. The contents of the gen folder are regenerated whenever you recompile your project or add resources. These contents should not be committed to source control nor edited manually.
Then there is the library against which you are compiling. In this case, Android 4.1.
Android Dependencies folder contains other jar files that your application depends on like the AppCompat library.
The assets folder contains files like fonts, etc. if you choose to add them.
The bin folder contains the APK file, dex file, etc. of your app once it compiles successfully.
The res folder contains various resources like strings, colors, images, styles, etc. for your Android application.
The libs folder contains third party libraries that you might want to add to your project.
The AndroidManifest.xml specifies the configuration of your app. It contains information like what permissions your app needs, what devices it supports, etc.
The proguard-project.txt file contains configuration information for ProGuard. It specifies what code gets obfuscated and what doesn’t.
The project.properties file contains configuration information for Eclipse.

2. What are the contents of res folder?
The res folder contains the various resources for your project like images, menus, layouts, etc. All of these are arranged in their corresponding sub-folders. For example, layouts are stored under layout folder. These folders may also be qualified for supporting various screen sizes or languages. For example, layouts for high pixel density phones will go under layout-hdpi.
Similarly, the drawable folder contains various drawables like images, etc. Akin to the layout folder, the drawable folder may also be qualified.
The menu folder contains files which contain information for creation of menus.
The xml folder contains files which contain information for creating preference screens (settings screen).
A complete list of the folders supported under the res folder can be found at http://developer.android.com/guide/topics/resources/providing-resources.html

3. What happens if you store resource files outside the res folder?
Storing the resource files outside the res folder will result in a compiler error.

4. What are density independent pixels?
Specifying the sizes of UI controls, etc. in pixels makes them device dependent. This means that depending upon the pixel density of the device the UI controls (or text or whatever) are rendered on, the physical size may vary. For example, a 100px long UI control will look big on a low density device and small on a high density device. Density independent pixels provide a density-agnostic way of specifying the size of your UI controls (or whatever!). A UI control that is 220dp (dp = density independent pixels) long will look exactly the same across all devices, irrespective of its pixel density. For more, watch the DevBytes video on DPs https://www.youtube.com/watch?v=zhszwkcay2A

5. What are the contents of the assets folder?
The assets folder provides an easy way to store your files that cannot be placed under the res folder. You can place any file you want under this folder and then access it in your application. The files in the assets folder may also be organized into subfolders. To access these files, you need a reference to the AssetManager instance. Using the open() method, you can get an InputStream to the file. The following snippet shows how to load an image from the assets folder. For more, http://www.wiseandroid.com/post/2010/06/14/Android-Beginners-Intro-to-Resources-and-Assets.aspx

ImageView img = (ImageView) findViewById(R.id.image_view);
AssetManager mgr = getAssets();
InputStream is = mgr.open("images/img1.jpg");
Bitmap bmp = BitmapFactory.decodeStream(is);
img.setImageBitmap(bmp);

Android Interview Questions – Ultimate Guide (Overview)


1. What is Android?
Android is Google’s mobile OS based on the Linux kernel. Android is designed primarily for touchscreen devices like phones and tablets but provides user interfaces for televisions (Android TV), cars (Android Auto), and wristwatches (Android Wear).

2. What is an APK file?
APK is the abbreviation for Android Package. It is the file format used to distribute applications onto the Android operating system. To make an APK file, the Android program is first compiled, and then all of its parts are packaged. The APK contains all of the program’s code, resources, assets, certificates, and a manifest file. APK files are created by AAPT (Android Asset Packaging Tool).

3. What are the tools that come with the Android SDK?
The Android SDK includes a number of tools that allow you to write app for the Android OS, communicate with your app, etc. These include Android Virtual Device Manager, Android Emulator, Hierarchy Viewer, SDK Manager, lint, mksdcard, DDMS, Android Debug Bridge, etc.

4. What is AAPT?
AAPT is the abbreviation for Android Asset Packaging Tool. It is a part of the Android SDK and allows you to view, create, and update zip-compatible archives like APK, JAR, and ZIP. AAPT is located at $ANDROID_HOME/build-tools/$SDK/ and has a list of useful commands. For example, the list command that lists the contents of the APK file. For more, http://elinux.org/Android_aapt

$ aapt list myapp.apk 
META-INF/MANIFEST.MF
META-INF/CERT.SF
META-INF/CERT.RSA
AndroidManifest.xml
classes.dex
res/drawable-hdpi/app_icon.png
res/drawable-mdpi/app_icon.png
res/layout/activity_main.xml
res/xml/abc.xml
resources.arsc

5. What is DDMS?
DDMS is the abbreviation for Dalvik Debug Monitor Server. It is a debugging tool that comes with the SDK and provides thread and heap information, logcat, screen capture, etc. Android IDEs like Eclipse and Android Studio provide a UI view of the information provided by DDMS.

6. What is Hierarchy Viewer?
Hierarchy Viewer lets you debug and optimize your user interfaces. It provides a visual representation of the layout’s View hierarchy and also provides performance measures like the measure time, layout time, and draw time.

7. What is adb?
adb stands for Android Debug Bridge. It is a command line tool that lets you communicate with your emulator or device. It includes commands that let you list the device connected, move files from your computer to your emulator or device, get files from your emulator or device onto your computer, etc. For more, http://www.vogella.com/tutorials/AndroidCommandLine/article.html

adb pull /sdcard/log.txt /home/codelatte/

This will copy the log.txt file from the SD Card into the home folder.

8. What is Dalvik VM?
Dalvik VM is the virtual machine that executes the Android applciations. It executes .dex (Dalvik Executable) codes. Every Android app runs in its own instance of Dalvik VM.

9. What is ART?
Android Runtime (ART) is the virtual machine that replaces Dalvik. It was introduced as a feature in Android 4.4 but became the defacto VM Android 5.0. ART focuses on improving the app performance. To do this, it introduces ahead-of-time (AOT) compilation. Using AOT, the dex codes are precompiled to machine code. This eliminates the time to interpret them when the app is run.

10. Explain Android’s Architecture
Android Architecture
At the bottom of the Android software stack is the modified Linux kernel. The kernel provides features like memory management, power management, process management, etc. On top of this kernel are libraries and APIs written in C. These libraries include WebKit for rendering webpages, SQLite for data storage, OpenGL for graphics rendering, etc. The Android runtime is also at this level. Depending on the Android version, this could be either Dalvik or ART. Then there is the Android application framework which allows developers to write applications. Finally, there are the apps. For more, https://en.wikipedia.org/wiki/Android_%28operating_system%29#Software_stack

Simplyfying Node EventEmitters

Node is centered around events. Whenever something interesting happens, an event is triggered and you have the ability to respond to that event. All this magic is possible because of EventEmitters. In this post I will give you a quick introduction to EventEmitters.

Node comes built-in with a lot of EventEmitters. For example, every readable stream is an EventEmitter. All readable streams have data and end events associated with them. The request object of an HTTP server is a readable stream.

Responding to Events

You can respond to the events by registering callbacks for the events you are interested in. This is done by calling the on() method of the EventEmitter and passing it the string representing the event, and a callback to be called. For example, when the request to the server has completed its arrival, you may want to do something:

request.on("end",function(){
	// do something
});

The on() method calls the callback as many times as the event happens. If you only want to respond only once, replace on() with once():

request.once("end",function(){
	// do something
});

Creating your own EventEmitter

Every EventEmitter signals the happening of an interesting event by calling its emit() method. The emit() method takes in a string as a required argument and optional arguments that provide more information about the event. To show you how this works, and also to show you how you can create your own EventEmitter, here is a code snippet:

var fs = require("fs");
var events = require("events");
var watcher = new events.EventEmitter();
const WATCH_DIR = ".";
const CHANGE = "change";

fs.watchFile(WATCH_DIR,function(){
	watcher.emit(CHANGE);
});

watcher.on(CHANGE,function(){ console.log("dir has changed"); });

What I have done here is create a simple EventEmitter that watches the current directory and emit()s an event whenever a change has been made. The callback simply logs a message to the console.

It is also possible to extend the functionality provided by EventEmitters by using inheritance. This can be done as follows:

var events = require("events");
function Watcher(watchDir){
	this.watchDir = watchDir;
}
Watcher.prototype = Object.create(events.EventEmitter.prototype);
Watcher.prototype.watch = function(){ ... };
// add more methods

Adding / Removing Listeners

It possible to provide multiple listeners for a particular event, each of which does something different. Here:

var callback1 = function(){ ... };
var callback2 = function(){ ... };
.
.
.
request.on("data",callback1);
request.on("data",callback2);

You can remove one of the listeners by using the removeListener() method:

request.removeListener("data",callback1);

or you could remove all the listeners for a particular event as:

request.removeAllListeners("data");

Setting a Maximum Limit on Listeners

By default, EventEmitters will print a warning if you add more than 10 listeners for a particular event. You can increase mthis limit on the number of listeners by using the setMaxListeners method:

request.setMaxListeners(50);

That’s it on EventEmitters. For more, you can always look at the official docs.