Tuesday, February 25, 2014

Inflating a ListView

We need to inflate a listview in 2 cases.

1. When we want to display a listview at run time
2. When we need a custom listview

We will see both the cases with examples.
Case 1: In this example we will  inflate a listview. See how

Android Layout File
File: res/layout/main.xml
<linearlayout 
android:id="@+id/layout1" 
android:layout_height="match_parent" 
android:layout_width="match_parent" 
android:orientation="vertical" 
xmlns:android="http://schemas.android.com/apk/res/android">

   <textview 
android:id="@+id/namelabel" 
android:layout_height="wrap_content" 
android:layout_width="wrap_content" 
android:text="Text Paragraph.">
    </textview> 
</linearlayout>
We have another layout file activity_main having listview in it.
File: res/layout/activity_main.xml
<ListView
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/listview"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:cacheColorHint="#EEEEEE"
 android:background="#CCCCCC" />
We are going to inflate layout activity_main in our main activity.Our main inflatelistview activity is as follows.
package com.example.inflatelistview;

import java.util.ArrayList;

import java.util.HashMap;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.Menu;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class inflatelistview extends Activity {
 LinearLayout ILayout;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

     final LayoutInflater  inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ListView t = (ListView)inflater.inflate(R.layout.activity_main,null);
        
        ILayout = (LinearLayout)findViewById(R.id.layout1);
        ILayout.addView(t);
     String[] values = new String[] { "Item1","Item2","Item3","Item4"};

     final ArrayList list = new ArrayList();
     for (int i = 0; i < values.length; ++i) {
       list.add(values[i]);
     }
     final OurArrayAdapter adapter = new OurArrayAdapter(this,
         android.R.layout.simple_list_item_1, list);
     t.setAdapter(adapter);

     
   }

   private class OurArrayAdapter extends ArrayAdapter {

     HashMap MapValue = new HashMap();

     public OurArrayAdapter(Context context, int textViewResourceId,
         List objects) {
       super(context, textViewResourceId, objects);
       for (int i = 0; i < objects.size(); ++i) {
         MapValue.put(objects.get(i), i);
       }
     }

     @Override
     public long getItemId(int position) {
       String item = getItem(position);
       return MapValue.get(item);
     }

     @Override
     public boolean hasStableIds() {
       return true;
     }

   }

 } 

The same thing we can do without inflating in a simple way by including listview in our main.xml and adding
final ListView listview = (ListView) findViewById(R.id.listview); 

instead of

final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ListView t = (ListView)inflater.inflate(R.layout.activity_main,null);
ILayout = (LinearLayout)findViewById(R.id.layout1);
ILayout.addView(t); 

Case 2: We will create a custom listview having a image & text in it. To create a custom listview,we need to create custom adapter. In this example we will use arrayadapter for easy understanding. You will need 2 layout files. One, main.xml, will define the attributes of the ListView. The other, mainlvitem.xml, will be the layout of each individual row in the ListView.

 File: res/layout/main.xml:
<ListView
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/listview"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:cacheColorHint="#EEEEEE"
 android:background="#CCCCCC" />
Next File,res/layout/mainlvitem.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="horizontal"
 android:paddingLeft="4dp"
 android:paddingRight="15dp"
 android:paddingTop="13dp"
 android:paddingBottom="13dp"
 android:weightSum="1"
 android:background="#FFFFFF" >

 <ImageView
  android:id="@+id/img"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center_vertical"
  android:layout_weight="0.10" />

 <TextView
  android:id="@+id/txt"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:layout_gravity="center"
  android:gravity="left"
  android:layout_weight="0.90"
  android:paddingLeft="10dp"
  android:textColor="#222222"/>
</LinearLayout>
Now the main activity is
package com.example.inflatelistview;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
 
public class customlistview extends Activity {
 
// We will declare some variables within the class, but outside of any method so that
// any method can use them.
 
ListView lv; // The ListView we will be building
 
// A String[] array that will hold the names of the items.
String[] mItems = { "Item1", "Item2", "Item3" };
 
// An Integer[] array that will hold the resource drawables that will be displayed as icons.
 Integer[] mIcons =
 { R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher };
 
// -----------------------------------------------
// onCreate()
// -----------------------------------------------
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    // Here we will take the ListView that we declared in activity_main layout
    
    lv = (ListView) findViewById(R.id.listview);
 
    // Instead of using a regular ArrayAdapter to pull Strings from an array,
    // we will create a custom ArrayAdapter below. This bit of code sets the adapter
    // of our ListView, lv, to our customer adapter.
    ArrayAdapter adapter = new CustomAdapter(this, R.layout.mainlvitem, mItems);
    lv.setAdapter(adapter);
 
 } // end onCreate
 
// -----------------------------------------------
// This is our custom ArrayAdapter, CustomAdapter
// -----------------------------------------------
 
 public class CustomAdapter extends ArrayAdapter
    {
        public CustomAdapter(Context context, int textViewResourceId, String[] objects)
        {
            super(context, textViewResourceId, objects);
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            // Inflate the layout, mainlvitem.xml, in each row.
            LayoutInflater inflater = customlistview.this.getLayoutInflater();
            View row = inflater.inflate(R.layout.mainlvitem, parent, false);
 
            // Declare and define the TextView, "item." This is where
            // the name of each item will appear.
            TextView item = (TextView)row.findViewById(R.id.txt);
            item.setText(mItems[position]);
 
            // Declare and define the TextView, "icon." This is where
            // the icon in each row will appear.
            ImageView icon=(ImageView)row.findViewById(R.id.img);
            icon.setImageResource(mIcons[position]);
 
            return row;
        }
    } // end CustomAdapter
}

We have used default images which comes with drawable folder ic_launcher in this program.However you can use any other image as you want. You need to put those images in appropriate folder.

Monday, February 17, 2014

Use of Fragments in Android with Working Example.



Fragment as it says is a part of a substance. Here in android fragment is a part of activity. One activity can have many fragments or alternatively we can say one fragment can be used in many activities. This helps in reusing particulat piece of code too.
This is introduced in Honeycomb API Level 11. In tablet as there are more space,to fill the space fragments are commonly used.
Two Fragments are displayed in Tablet

About the Demo Fragment Application

The application created in this blog will consist of a single activity and two fragments.
One fragment displays the list of friends & second fragment displays the twitter feeds of those friends.
The two fragments will be embedded within the main activity of the application and communication between two fragments happens in such a way that when the list item of  first friend fragment is clicked, twitterfeeds of that friend appears in second fragment .Let's see how.

Creating the Fragment Demo Project

Launch Eclipse and create an Android Application Project named FragmentDemo with the appropriate package name and with minimum required SDK as API 11-Android 3.0(Honeycomb) selections.  creat a blank activity and the use of the default launcher icons. On the New Blank Activity screen of the New Android Application wizard, set the Activity Name to MainActivity

FriendFragment is a ListFragment which displays list of friends name. We are creating dynamically with code like this.
 

package course.labs.fragmentslab;

import android.app.Activity;
import android.app.ListFragment;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class FriendsFragment extends ListFragment {

 private static final String[] FRIENDS = { "Barak Obama", "Clinton",
   "George Bush" };
 
 public interface SelectionListener {
  public void onItemSelected(int position);
 }

 private SelectionListener mCallback;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // use different layout definition, depending on whether device is pre-
  // or post-honeycomb

  int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? android.R.layout.simple_list_item_activated_1
    : android.R.layout.simple_list_item_1;

  // Set the list adapter for this ListFragment
  setListAdapter(new ArrayAdapter(getActivity(), layout, FRIENDS));
 }

  
 @Override
 public void onAttach(Activity activity) {
  super.onAttach(activity);

  // Make sure that the hosting Activity has implemented
  // the SelectionListener callback interface. We need this
  // because when an item in this ListFragment is selected, 
  // the hosting Activity's onItemSelected() method will be called.
  
  try {

   mCallback = (SelectionListener) activity;

  } catch (ClassCastException e) {
   throw new ClassCastException(activity.toString()
     + " must implement SelectionListener");
  }
 }

 // Note: ListFragments come with a default onCreateView() method.
 // For other Fragments you'll normally implement this method.
 //  @Override
 //  public View onCreateView(LayoutInflater inflater, ViewGroup container,
 //  Bundle savedInstanceState)

 
 @Override
 public void onActivityCreated(Bundle savedInstanceState) {
  super.onActivityCreated(savedInstanceState);

  Log.i(TAG, "Entered onActivityCreated()");

  // When using two-pane layout, configure the ListView to highlight the
  // selected list item
  
  if (isInTwoPaneMode()) {

   getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);

  }

 }

 @Override
 public void onListItemClick(ListView l, View view, int position, long id) {

  // Notify the hosting Activity that a selection has been made.

  mCallback.onItemSelected(position);

 }

 // If there is a FeedFragment, then the layout is two-pane 
 private boolean isInTwoPaneMode() {

  return getFragmentManager().findFragmentById(R.id.feed_frag) != null;

 }

}
FeedFragment which displays twitterfeeds is created by inflating feed layout which contains one textview .
Feed layout has this structure.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/feed_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/greeting" />

</ScrollView>
FeedFragment.java as follows
package course.labs.fragmentslab;

import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FeedFragment extends Fragment {

 private TextView mTextView;
 private static FeedFragmentData feedFragmentData;

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {

  return inflater.inflate(R.layout.feed, container, false);

 }

 @Override
 public void onActivityCreated(Bundle savedInstanceState) {
  super.onActivityCreated(savedInstanceState);

  // Read in all Twitter feeds 
  if (null == feedFragmentData) { 
   
   feedFragmentData = new FeedFragmentData(getActivity());

  }
 }


 // Display Twitter feed for selected feed

 void updateFeedDisplay(int position) {

  Log.i(TAG, "Entered updateFeedDisplay()");
    
  mTextView = (TextView) getView().findViewById(R.id.feed_view);
  mTextView.setText(feedFragmentData.getFeed(position));

 }

}

Adding the Fragments to the Activity

Fragments are attached to MainActivity as follows. MainActivity.java
package course.labs.fragmentslab;

import android.app.Activity;
import android.app.FragmentManager;

import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity implements
  FriendsFragment.SelectionListener {

 private static final String TAG = "Lab-Fragments";

 private FriendsFragment mFriendsFragment;
 private FeedFragment mFeedFragment;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main_activity);

  // If the layout is single-pane, create the FriendsFragment 
  // and add it to the Activity

  if (!isInTwoPaneMode()) {
   
   mFriendsFragment = new FriendsFragment();

   
   FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
   fragmentTransaction.add(R.id.fragment_container, mFriendsFragment);
   fragmentTransaction.commit();
   
   

  } else {

   // Otherwise, save a reference to the FeedFragment for later use

   mFeedFragment = (FeedFragment) getFragmentManager()
     .findFragmentById(R.id.feed_frag);
  }

 }

 // If there is no fragment_container ID, then the application is in
 // two-pane mode

 private boolean isInTwoPaneMode() {

  return findViewById(R.id.fragment_container) == null;
 
 }

 // Display selected Twitter feed

 public void onItemSelected(int position) {

  Log.i(TAG, "Entered onItemSelected(" + position + ")");

  // If there is no FeedFragment instance, then create one

  if (mFeedFragment == null)
   mFeedFragment = new FeedFragment();

  // If in single-pane mode, replace single visible Fragment

  if (!isInTwoPaneMode()) {

   
   FragmentTransaction transaction = getFragmentManager().beginTransaction();
   mFeedFragment.setRetainInstance(true);
   transaction.replace(R.id.fragment_container, mFeedFragment);
   transaction.addToBackStack(null);
   transaction.commit();
   

   // execute transaction now
   getFragmentManager().executePendingTransactions();

  }

  // Update Twitter feed display on FriendFragment
  mFeedFragment.updateFeedDisplay(position);

 }

}
In line no 26 its mentioned that  If the layout is single-pane, create the FriendsFragment  and add it to the Activity. So its added programmatically as


if (!isInTwoPaneMode()) {
                                   
                                    mFriendsFragment = new FriendsFragment();
}
 

FragmentManager()  takes care of managing fragments. Add the FriendsFragments to the fragment_container frame mentioned in main_activity layout.

FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
   fragmentTransaction.add(R.id.fragment_container, mFriendsFragment);
   fragmentTransaction.commit();
On selecting item of FriendFragment it calls the FeedFagment as
public void onItemSelected(int position) {

  Log.i(TAG, "Entered onItemSelected(" + position + ")");

  // If there is no FeedFragment instance, then create one

  if (mFeedFragment == null)
   mFeedFragment = new FeedFragment();

  // If in single-pane mode, replace single visible Fragment

  if (!isInTwoPaneMode()) {

   
   FragmentTransaction transaction = getFragmentManager().beginTransaction();
   mFeedFragment.setRetainInstance(true);
   transaction.replace(R.id.fragment_container, mFeedFragment);
   transaction.addToBackStack(null);
   transaction.commit();
   

   // execute transaction now
   getFragmentManager().executePendingTransactions();

  }

  // Update Twitter feed display on FriendFragment
  mFeedFragment.updateFeedDisplay(position);

 }

}
If  its phone then its single pane mode,in that case friendfragment will be replaced by FeedFragment. If its tablet FeedFragment will be displayed in its side. The code for replacing FriendFragment is
public void onItemSelected(int position) {

  Log.i(TAG, "Entered onItemSelected(" + position + ")");

  // If there is no FeedFragment instance, then create one

  if (mFeedFragment == null)
   mFeedFragment = new FeedFragment();

  // If in single-pane mode, replace single visible Fragment

  if (!isInTwoPaneMode()) {

   
   FragmentTransaction transaction = getFragmentManager().beginTransaction();
   mFeedFragment.setRetainInstance(true);
   transaction.replace(R.id.fragment_container, mFeedFragment);
   transaction.addToBackStack(null);
   transaction.commit();
   

   // execute transaction now
   getFragmentManager().executePendingTransactions();

  }

  // Update Twitter feed display on FriendFragment
  mFeedFragment.updateFeedDisplay(position);

 }

}
Feeds here aren't real time feeds rather its stored as raw data in a text file.
Friend Fragment
Feed Fragment

How to pass object from one activity to another in Android?



Passing a string variable from one activity to another is easy peasy. We use putExtra & getExtra methods of Intent class as follows.
Intent i = new Intent(this, SecondActivity.class);
i.putExtra("KEY",YourData);
To get the string value back in SecondActivity class,we use code
Bundle extras = getIntent().getExtras();
if(extras !=null) {
    String value = extras.getString("KEY");
} 

What about passing object from one activity to another?
In this sample project, we want to pass an instance of an ToDoItem from our main activity to another. ToDoItem will hold these information: Title, Priority,status,date & time.
First, we construct the ToDoItem like any Java Object. Create all the fields you want the object to contain and generate getters and setters for each. We then create the methods we would need to be able to pass, and subsequently receive, this object between activities.

To pass an ToDoItem, we would need to put it in an Intent and pass it using

Intent.putExtra(String key, Bundle bundle).
public static void packageIntent(Intent intent, String title,
                     Priority priority, Status status, String date) {

              intent.putExtra(ToDoItem.TITLE, title);
              intent.putExtra(ToDoItem.PRIORITY, priority.toString());
              intent.putExtra(ToDoItem.STATUS, status.toString());
              intent.putExtra(ToDoItem.DATE, date);
       
       }
Here, we simply put all the values in the object that we want to pass 
Next, we should be able to convert this back to an ToDoItem object in the receiving Activity. This task is done by the following method:
ToDoItem(Intent intent) {

              mTitle = intent.getStringExtra(ToDoItem.TITLE);
              mPriority = Priority.valueOf(intent.getStringExtra(ToDoItem.PRIORITY));
              mStatus = Status.valueOf(intent.getStringExtra(ToDoItem.STATUS));

              try {
                     mDate = ToDoItem.FORMAT.parse(intent.getStringExtra(ToDoItem.DATE));
              } catch (ParseException e) {
                     mDate = new Date();
              }
       }

I created a simple app that asks the user for the five
values we would need to populate ToDoItem.

When the user clicks on the "create item" button, the application creates a new ToItemItem based on the values in the form and adds this to an ArrayList of ToDoItems.
private void onCreateToDoItem() {
     // Create a newToDoItem
     ToDoItem todoitem = new ToDoItem ();
     todoitem. setTitle (mTitleText.getText().ToString());
     todoitem. setPriority(getPriority) 
        todoitem. setStatus(getStatus)
        todoitem. setDate(getDate)

     // You can then do whatever you want with this object
     // like adding it to an ArrayList or saving it to a database
     mItems.add(todoitem);
   
     Toast.makeText(ObjectSender.this, "ToDoItem added!", Toast.LENGTH_SHORT).show();
}
When the user clicks on the "submit item" button,
private void onSubmitObject() {
     Intent intent = new Intent(ObjectSender.this, ObjectReceiver.class);

     // For simplicity, we will always get the second value

     // In a "real" application, the Key should be defined in a constants file
      Intent data = new Intent(ObjectSender.this,ObjectReceiver.class);
                           ToDoItem.packageIntent(data, titleString, priority, status, fullDate);

                           //TODO - return data Intent and finish
                           startActivity(data);
}
Upon receiving the Intent, the new activity simply displays the values in the ToDoItem passed into it. Here's how we can get back the value.

public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.todo_item);

 // Get the extras passed to this Activity
 setUpViews(getIntent().getExtras());       
}
private void setUpViews(Bundle extras) {
        
        ToDoItem toDoItem = new ToDoItem(getIntent());
   // The ToDoItem fields are now populated, so we set the texts
 ((TextView) findViewById(R.id.titleView)).setText(toDoItem.getTitle());
 ((TextView) findViewById(R.id.priorityView)).setText(toDoItem.getPriority().toString());
 ((TextView) findViewById(R.id.StatusLabel)).setText(toDoItem.getStatus().toString());
 ((TextView) findViewById(R.id.dateView)).setText(toDoItem.FORMAT.format(toDoItem.getDate()));
}

 
Here's how the sending & receiving screen activity looks like.

Here is the ToDoItem class
package com.example.passobject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.content.Intent;

public class ToDoItem {

    public static final String ITEM_SEP =
System.getProperty("line.separator");

    public enum Priority {

        LOW, MED, HIGH

    };
    public enum Status {

        NOTDONE, DONE

    };
    public final static String TITLE = "title";

    public final static String PRIORITY = "priority";

    public final static String STATUS = "status";

    public final static String DATE = "date";

    public final static String FILENAME = "filename";

    public final static SimpleDateFormat FORMAT = new
SimpleDateFormat(

            "yyyy-MM-dd
HH:mm:ss", Locale.US);

    private String mTitle = new String();

    private Priority mPriority = Priority.LOW;

    private Status mStatus = Status.NOTDONE;

    private Date mDate = new Date();

    ToDoItem(String title, Priority priority, Status status,
Date date) {

        this.mTitle = title;

        this.mPriority = priority;

        this.mStatus = status;

        this.mDate = date;

    }
    // Create a new ToDoItem from data packaged in an Intent

    ToDoItem(Intent intent) {

        mTitle =
intent.getStringExtra(ToDoItem.TITLE);

        mPriority =
Priority.valueOf(intent.getStringExtra(ToDoItem.PRIORITY));

        mStatus =
Status.valueOf(intent.getStringExtra(ToDoItem.STATUS));
        try {

            mDate =
ToDoItem.FORMAT.parse(intent.getStringExtra(ToDoItem.DATE));

        } catch (ParseException e) {

            mDate = new Date();

        }

    }

     public ToDoItem(){
        

     }

    public String getTitle() {

        return mTitle;

    }



    public void setTitle(String title) {

        mTitle = title;

    }

    public Priority getPriority() {

        return mPriority;

    }

    public void setPriority(Priority priority) {

        mPriority = priority;

    }

    public Status getStatus() {

        return mStatus;

    }

    public void setStatus(Status status) {

        mStatus = status;

    }

    public Date getDate() {

        return mDate;

    }

    public void setDate(Date date) {

        mDate = date;

    }

    // Take a set of String data values and 

    // package them for transport in an Intent

    public static void packageIntent(Intent intent, String
title,

            Priority priority,
Status status, String date) {
        intent.putExtra(ToDoItem.TITLE, title);

        intent.putExtra(ToDoItem.PRIORITY, priority.toString());

        intent.putExtra(ToDoItem.STATUS,
status.toString());

        intent.putExtra(ToDoItem.DATE, date);
   
    }

    public String toString() {

        return mTitle + ITEM_SEP + mPriority +
ITEM_SEP + mStatus + ITEM_SEP

                +
FORMAT.format(mDate);

    }
    public String toLog() {

        return "Title:" + mTitle +
ITEM_SEP + "Priority:" + mPriority

                +
ITEM_SEP + "Status:" + mStatus + ITEM_SEP + "Date:"

                +
FORMAT.format(mDate);

    }

}

Here is the main activity which sends the object
package com.example.passobject;

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


import java.util.Date;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import com.example.passobject.ToDoItem.Priority;
import com.example.passobject.ToDoItem.Status;
import com.example.passobject.ToDoItem;
public class ObjectSender extends Activity {
    
    // 7 days in milliseconds - 7 * 24 * 60 * 60 * 1000
    private static final int SEVEN_DAYS = 604800000;

    
    private static String timeString;
    private static String dateString;
    private static TextView dateView;
    private static TextView timeView;
    private final List mItems = new ArrayList();
    
    private Date mDate;
    private RadioGroup mPriorityRadioGroup;
    private RadioGroup mStatusRadioGroup;
    private EditText mTitleText;
    private RadioButton mDefaultStatusButton;
    private RadioButton mDefaultPriorityButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_todo);

        mTitleText = (EditText) findViewById(R.id.title);
        mDefaultStatusButton = (RadioButton) findViewById(R.id.statusDone);
        mDefaultPriorityButton = (RadioButton) findViewById(R.id.medPriority);
        mPriorityRadioGroup = (RadioGroup) findViewById(R.id.priorityGroup);
        mStatusRadioGroup = (RadioGroup) findViewById(R.id.statusGroup);
        dateView = (TextView) findViewById(R.id.date);
        timeView = (TextView) findViewById(R.id.time);

        // Set the default date and time

        setDefaultDateTime();

        // OnClickListener for the Date button, calls showDatePickerDialog() to show
        // the Date dialog

        final Button datePickerButton = (Button) findViewById(R.id.date_picker_button);
        datePickerButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showDatePickerDialog();
            }
        });

        // OnClickListener for the Time button, calls showTimePickerDialog() to show
        // the Time Dialog

        final Button timePickerButton = (Button) findViewById(R.id.time_picker_button);
        timePickerButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showTimePickerDialog();
            }
        });

        // OnClickListener for the Cancel Button, 

        final Button cancelButton = (Button) findViewById(R.id.cancelButton);
        cancelButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                log("Entered cancelButton.OnClickListener.onClick()");

                
                ToDoItem toDoItem = new ToDoItem();
                toDoItem. setTitle (mTitleText.getText().toString());
                toDoItem. setPriority(getPriority()) ;
                    toDoItem. setStatus(getStatus());
                    toDoItem. setDate(mDate);

                 // You can then do whatever you want with this object
                 // like adding it to an ArrayList or saving it to a database
                 mItems.add(toDoItem);
              
                 Toast.makeText(ObjectSender.this, "ToDoItem added!", Toast.LENGTH_SHORT).show();

            }
        });

        //OnClickListener for the Reset Button

        final Button resetButton = (Button) findViewById(R.id.resetButton);
        resetButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                log("Entered resetButton.OnClickListener.onClick()");

               
                mTitleText.setText("");
                mDefaultStatusButton.setChecked(true);
                mDefaultPriorityButton.setChecked(true);               
                    setDefaultDateTime();
            }
        });

        // OnClickListener for the Submit Button
        // Implement onClick().
       
        final Button submitButton = (Button) findViewById(R.id.submitButton);
        submitButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                log("Entered submitButton.OnClickListener.onClick()");

                // Gather ToDoItem data 
            
                
                Priority priority = getPriority();
              
                Status status = getStatus();
               
                String titleString = mTitleText.getText().toString();

                // Date
                String fullDate = dateString + " " + timeString;

                // Package ToDoItem data into an Intent
                Intent data = new Intent(ObjectSender.this,ObjectReceiver.class);
                ToDoItem.packageIntent(data, titleString, priority, status, fullDate);
                                startActivity(data);
               
               
            }
        });
    }

   
    
    // Use this method to set the default date and time
    
    private void setDefaultDateTime() {

        // Default is current time + 7 days
        mDate = new Date();
        mDate = new Date(mDate.getTime() + SEVEN_DAYS);

        Calendar c = Calendar.getInstance();
        c.setTime(mDate);

        setDateString(c.get(Calendar.YEAR), c.get(Calendar.MONTH),
                c.get(Calendar.DAY_OF_MONTH));

        dateView.setText(dateString);

        setTimeString(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE),
                c.get(Calendar.MILLISECOND));

        timeView.setText(timeString);
    }

    private static void setDateString(int year, int monthOfYear, int dayOfMonth) {

        // Increment monthOfYear for Calendar/Date -> Time Format setting
        monthOfYear++;
        String mon = "" + monthOfYear;
        String day = "" + dayOfMonth;

        if (monthOfYear < 10)
            mon = "0" + monthOfYear;
        if (dayOfMonth < 10)
            day = "0" + dayOfMonth;

        dateString = year + "-" + mon + "-" + day;
    }

    private static void setTimeString(int hourOfDay, int minute, int mili) {
        String hour = "" + hourOfDay;
        String min = "" + minute;

        if (hourOfDay < 10)
            hour = "0" + hourOfDay;
        if (minute < 10)
            min = "0" + minute;

        timeString = hour + ":" + min + ":00";
    }

    private Priority getPriority() {

        switch (mPriorityRadioGroup.getCheckedRadioButtonId()) {
        case R.id.lowPriority: {
            return Priority.LOW;
        }
        case R.id.highPriority: {
            return Priority.HIGH;
        }
        default: {
            return Priority.MED;
        }
        }
    }

    private Status getStatus() {

        switch (mStatusRadioGroup.getCheckedRadioButtonId()) {
        case R.id.statusDone: {
            return Status.DONE;
        }
        default: {
            return Status.NOTDONE;
        }
        }
    }

    // DialogFragment used to pick a ToDoItem deadline date

    public static class DatePickerFragment extends DialogFragment implements
            DatePickerDialog.OnDateSetListener {

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            // Use the current date as the default date in the picker

            final Calendar c = Calendar.getInstance();
            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH);
            int day = c.get(Calendar.DAY_OF_MONTH);

            // Create a new instance of DatePickerDialog and return it
            return new DatePickerDialog(getActivity(), this, year, month, day);
        }

        @Override
        public void onDateSet(DatePicker view, int year, int monthOfYear,
                int dayOfMonth) {
            setDateString(year, monthOfYear, dayOfMonth);

            dateView.setText(dateString);
        }

    }

    // DialogFragment used to pick a ToDoItem deadline time

    public static class TimePickerFragment extends DialogFragment implements
            TimePickerDialog.OnTimeSetListener {

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            // Use the current time as the default values for the picker
            final Calendar c = Calendar.getInstance();
            int hour = c.get(Calendar.HOUR_OF_DAY);
            int minute = c.get(Calendar.MINUTE);

            // Create a new instance of TimePickerDialog and return
            return new TimePickerDialog(getActivity(), this, hour, minute,
                    true);
        }

        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
            setTimeString(hourOfDay, minute, 0);

            timeView.setText(timeString);
        }
    }

    private void showDatePickerDialog() {
        DialogFragment newFragment = new DatePickerFragment();
        newFragment.show(getFragmentManager(), "datePicker");
    }

    private void showTimePickerDialog() {
        DialogFragment newFragment = new TimePickerFragment();
        newFragment.show(getFragmentManager(), "timePicker");
    }

    private void log(String msg) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.i(TAG, msg);
    }

}
Here is script for activity which receives it.
package com.example.passobject;
import com.example.passobject.ToDoItem;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class ObjectReceiver extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.todo_item);

 // Get the extras passed to this Activity
 setUpViews(getIntent().getExtras());       
}

private void setUpViews(Bundle extras) {
       
        ToDoItem toDoItem = new ToDoItem(getIntent());
       
    

 // The AttendeeObject fields are now populated, so we set the texts
 ((TextView) findViewById(R.id.titleView)).setText(toDoItem.getTitle());
 ((TextView) findViewById(R.id.priorityView)).setText(toDoItem.getPriority().toString());
 ((TextView) findViewById(R.id.StatusLabel)).setText(toDoItem.getStatus().toString());
 ((TextView) findViewById(R.id.dateView)).setText(toDoItem.FORMAT.format(toDoItem.getDate()));
}

}

Saturday, February 15, 2014

What is LayoutInflater? Why we need to inflate and when?

LayoutInflater is a class used to instantiate layout XML file into its corresponding view objects which can be used in java programs.
In simple terms there are two ways to create UI in android. One is static way and another is dynamic or programmatically.
Suppose we have a simple layout main.xml  having one textview and one edittext as follow.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/layout1"
    >
<TextView
        android:id="@+id/namelabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Enter your name"
        android:textAppearance="?android:attr/textAppearanceLarge" >
    </TextView>
    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="14dp"
        android:ems="10">
    </EditText>
</LinearLayout>
We can display this layout in static way by
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
Dynamic way of creating a view means the view is not mentioned in our main.xml but we want to show with this in run time. For example We have another xml in layout folder as  footer.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/TextView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:text="Add your record"
    android:textSize="24sp" >
 </TextView>
We want to show this textbox in run time within our main UI. So here we will inflate text.xml . See how

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        final LayoutInflater  inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        TextView t = (TextView)inflater.inflate(R.layout.footer,null);

         lLayout = (LinearLayout)findViewById(R.id.layout1);

         lLayout.addView(t);

Here I have used getSystemService (String) to retrieve a  LayoutInflater instance. I can use getLayoutInflator() too to inflate instead of using getSystemService (String)  like below

 

LayoutInflator inflater = getLayoutInflater();

              TextView t = (TextView) inflater.inflate(R.layout.footer, null);

                               lLayout.addView(t);

We have inflated the view footer using inflater and converted it Textview object. In this example we have inflated a simple textview. If you want to know how to inflate a listview , check this Inflating Listview post.


Before Inflation
 
After Inflation
 

  You can download the complete source code from here.
You might be interested to know

How to inflate a listview?