Thursday, October 4, 2012

Android custom Listview

- Kalimuthu Regaswamy
Most of android mobile applications has a listview that displays something. And its been a practise by all android developes to add a view of their taste, just by customizing the listview to what required. This blog explains how to create a custom listview in android mobile. I hope this blog will help any android application builders who need to customize listview. The view I am trying out here has a image, two textview and a multiple choice option. 


Designing Listview:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<ListView
android:id="@id/android:list"
android:layout_width="fill_parent"
android:layout_height="394dp"
android:layout_margin="5dp"
android:layout_weight="0.95"
android:cacheColorHint="#0000"
android:clipToPadding="true"
android:dividerHeight="1px"
android:scrollbars="none"
android:soundEffectsEnabled="true" >
</ListView>
</RelativeLayout>

Designing custom cell:

<?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:orientation="vertical" >

<ImageView
android:id="@+id/Listimage"
android:layout_width="96px"
android:layout_height="96px"
android:layout_alignParentLeft="true"
android:layout_margin="1dp"
android:layout_marginTop="21dp"
android:background="@drawable/ic_launcher" />

<TextView
android:id="@+id/name"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="119dp"
android:layout_toRightOf="@+id/Listimage"
android:ellipsize="end"
android:text="TextView"
android:textSize="20px"
android:textStyle="bold" />

<TextView
android:id="@+id/no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/Listimage"
android:layout_alignLeft="@+id/name"
android:layout_marginBottom="14dp"
android:layout_marginLeft="16dp"
android:text="TextView"
android:textSize="15px" />

<CheckBox
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/no"
android:layout_alignParentRight="true"
/>
</RelativeLayout>

Creating pojo class:
The pojo class here gets and sets the needed objects

public class Pojo {
public String name;
public String no;
public String desc;
public String post;
private Boolean isSelected;
public Boolean getIsSelected() {
 return isSelected;
}
public void setIsSelected(Boolean isSelected) {
 this.isSelected = isSelected;
}
public String getName() {
 return name;
}
public void setName(String name) {
 this.name = name;
}
public String getNo() {
 return no;
}
public void setNo(String no) {
 this.no = no;
}
public String getDesc() {
 return desc;
}
public void setDesc(String desc) {
 this.desc = desc;
}
public String getPost() {
 return post;
}
public void setPost(String post) {
 this.post = post;
}
}

Coding list adapter :I have written a list adapter which actullay adds the custom cells designed into the listview. Adapter,  here is the bridge between a ListView and the data that backs the list. The ListView can display any data provided that it is wrapped in a ListAdapter.

public class MyCustomArrayAdapter extends ArrayAdapter<Pojo> {

 private final List<Pojo> list;
 private final Activity context;
 ViewHolder viewHolder=null ;
 public MyCustomArrayAdapter(Activity context, List<Pojo> list) {
 super(context, R.layout.customlist, list);
 this.context = context;
 this.list = list;
}

static class ViewHolder {
 protected TextView name,no;
 protected ImageView image;
 protected CheckBox checkbox;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
 View view = null;
 if (convertView == null) {
  LayoutInflater inflator = context.getLayoutInflater();
  view = inflator.inflate(R.layout.customlist, null);
  viewHolder = new ViewHolder();
  viewHolder.name = (TextView) view.findViewById(R.id.name);
  viewHolder.name.setTextColor(Color.BLACK);
  viewHolder.name.setEllipsize(TruncateAt.MIDDLE);
  viewHolder.no = (TextView) view.findViewById(R.id.no);
  viewHolder.no.setTextColor(Color.BLACK);
  viewHolder.image = (ImageView)         
  view.findViewById(R.id.Listimage);
  viewHolder.name.setText(list.get(position).getName());
  viewHolder.no.setText(list.get(position).getNo());
  viewHolder.checkbox =(CheckBox) view.findViewById(R.id.check);
  viewHolder.checkbox.setOnCheckedChangeListener(new 
   CompoundButton.OnCheckedChangeListener() {
    public void onCheckedChanged(CompoundButton buttonView,
    boolean isChecked) {
     Pojo element = (Pojo) viewHolder.checkbox
     .getTag();
     element.setIsSelected(buttonView.isChecked());
    }
  });
  viewHolder.image.setBackgroundResource(R.drawable.ic_launcher);
  viewHolder.checkbox.setTag(list.get(position));
  } else {
   view = convertView;
   ((ViewHolder)  
            view.getTag()).checkbox.setTag(list.get(position));             
    }
  return view;
 }

Main activity class:
This is where the list is loaded. Here I have replaced the default array adapter with the custom adapter.

public class MainActivity extends ListActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 ArrayAdapter<Pojo> adapter = new MyCustomArrayAdapter(
 MainActivity.this, getData());
 setListAdapter(adapter);
}
public List<Pojo> getData(){
 List<Pojo> addList =new ArrayList<Pojo>();
 Pojo objectPojo=new Pojo();
 objectPojo.setName("muthu");
 objectPojo.setNo("1234");
 objectPojo.setDesc("android ");
 objectPojo.setPost("Developer");
 objectPojo.setIsSelected(false);
 addList.add(objectPojo);
 objectPojo=new Pojo();
 objectPojo.setName("kali");
 objectPojo.setNo("3456");
 objectPojo.setDesc("iPhone ");
 objectPojo.setPost("Developer");
 objectPojo.setIsSelected(false);
 addList.add(objectPojo);

 objectPojo=new Pojo();
 objectPojo.setName("arasu");
 objectPojo.setNo("5678");
 objectPojo.setDesc("windows ");
 objectPojo.setPost("Developer");
 objectPojo.setIsSelected(false);
 addList.add(objectPojo);
 objectPojo=new Pojo();
 objectPojo.setName("anbu");
 objectPojo.setNo("8901");
 objectPojo.setDesc("mac ");
 objectPojo.setPost("Developer");
 objectPojo.setIsSelected(false);
 addList.add(objectPojo);
 return addList;
 }
}
Android developers can just copy and paste the codes to get the listview customized as shown above. 





Camera integration in iPhone

- Rashid Khaleefa
Overview:
Blog on how to integrate camera into iPhone application.
You can easily include camera feature into any ios application provided the device has a camera support, and you make use of the imagePickerController of apple.

Camera integration:
You have to create a secondary view controller for managing the overlap view to the camera.
This customises the way how the camera screen should apper once camera is initiated from your application.
Use the apples imagepickerController to pic the image snaped.
Creating overlayViewController
  1. Declare the needed controlls in .h file
  2. Implement those in .m
  3. Include the UIImagePickerControllerDelegate
  4. Create needed delegates for your overlayViewController
A Sample overlay having buttons takepicture button and done button with actions takePhoto, close respectively for those. Also the delegate methods didTakePicture, the method where you get the snaped picture and didFinshWithCamera that can be used to perform any action once you are done with camera.

The .h file of overlayViewController:

@protocol OverlayViewControllerDelegate;
@interface OverlayViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
id <OverlayViewControllerDelegate> delegate;
UIImagePickerController *imagePickerController;
@private
UIBarButtonItem *takePictureButton;
UIBarButtonItem *cancelButton;
}

@property (nonatomic, assign) id <OverlayViewControllerDelegate> delegate;
@property (nonatomic, retain) UIImagePickerController *imagePickerController;

@property (nonatomic, retain) IBOutlet UIBarButtonItem *takePictureButton;
@property (nonatomic, retain) IBOutlet UIBarButtonItem *cancelButton;

- (void)setupImagePicker:(UIImagePickerControllerSourceType)sourceType;

// camera page (overlay view)
- (IBAction)done:(id)sender;
- (IBAction)takePhoto:(id)sender;
@end

@protocol OverlayViewControllerDelegate
- (void)didTakePicture:(UIImage *)picture;
- (void)didFinishWithCamera;
@end

Now in you .m file, Initiate the imagePickerController and map its delegate

self.imagePickerController = [[[UIImagePickerController alloc] init] autorelease];
self.imagePickerController.delegate = self;

- (void)setupImagePicker:(UIImagePickerControllerSourceType)sourceType
{
NSLog(@"enters setupImagePicker");
self.imagePickerController.sourceType = sourceType;
if (sourceType == UIImagePickerControllerSourceTypeCamera)
{
// user wants to use the camera interface
//
self.imagePickerController.showsCameraControls = NO;
if ([[self.imagePickerController.cameraOverlayView subviews] count] == 0)
{
// setup your custom overlay view for the camera
//
// ensure that your custom view's frame fits within the parent frame
CGRect overlayViewFrame = self.imagePickerController.cameraOverlayView.frame;
CGRect newFrame = CGRectMake(0.0,
CGRectGetHeight(overlayViewFrame) -
self.view.frame.size.height - 10.0,
CGRectGetWidth(overlayViewFrame),
self.view.frame.size.height + 10.0);
self.view.frame = newFrame;
[self.imagePickerController.cameraOverlayView addSubview:self.view];
}
}
}

This calls the didFinishWithCamera delegats.

- (IBAction)done:(id)sender
{
[self.delegate didFinishWithCamera];
}

Action that maps takesPhoto. This just calls the takePicture of imgaePickerController which is responsible for initiating still image capture.

- (IBAction)takePhoto:(id)sender
{
[self.imagePickerController takePicture];
}

Also include the follwoing delegates of imgePicker which gets called when an image is taken by the camera.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
if (self.delegate)
[self.delegate didTakePicture:image];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self.delegate didFinishWithCamera]; // tell your delegate we are finished with the picker
}
Thats all for overlayViewController

Now How to use this in your class. You have to now include the overlayController delegate and imgaPickerController in header of the class where you wish to inclue a button for a camera capture.
Now call the below function in the button action you need.

- (void)showImagePicker:(UIImagePickerControllerSourceType)sourceType
{
NSLog(@"entered showImagePicker camera");
if ([UIImagePickerController isSourceTypeAvailable:sourceType])
{
[self.overlayViewController setupImagePicker:sourceType];
[self presentModalViewController:self.overlayViewController.imagePickerController animated:YES];
}
}

This checks for the sourcetype you give that should be a camera sourcetype the syntax is as below

[self showImagePicker:UIImagePickerControllerSourceTypeCamera];

Thats it now include the delegates of overlay class that was created

- (void)didTakePicture:(UIImage *)picture
{
//do some thing with the picture.
}
- (void)didFinishWithCamera
{
[self dismissModalViewControllerAnimated:YES];
}

The didTakePicture tells that a picture was taken, you get the picture you snapped in this delegate. And didFinishWithCamera tells to finish with the camera.
Thats it. You get your camera to snap from your application and the image you snapped.