Quantcast
Channel: TechieDreams
Viewing all articles
Browse latest Browse all 21

Gmail like – Flip animated Multi selection list view with action mode.

$
0
0

Android Gmail App has a very beautiful and smooth multi selection list, where you can select multiple items and perform an action over the selected items.

Here in this tutorial we are going to create a similar effect on custom list where we have a image and a title and on-click of the image it gets checked with a flip animation.

Also if you are new for creating a custom list please go through my previous tutorials:

http://techiedreams.com/android-simple-custom-list-views-with-examples/

Note : In this tutorial i used ABS(Actionbar Sherlock) for the Actionbar and Actionmode to support older versions also. Please find the library in the download package import it and add it to the project.

Here’s how the final result looks like:

td_an_p13_1              td_an_p13_2

First thing prior jumping in to this tutorial you should know how this works.

1. We flip the image half way (to middle).

2. End of the animation we now have image view rotated 90° we can imagine it as a thin line.

3. Now its time to change the image to inverse of the previous (Ex: if unchecked image is showing we replace it with checked image).

4. Now we run the second animation to rotate it from middle to normal. Done!

Hope you gone thorough my custom listview tutorial and have the custom list running, now

1. Create two anim files in the ‘anim’ folder of resources.

a) to_middle.xml :

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="200"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="0.0"
    android:toYScale="1.0" />

b) from_middle.xml :

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="200"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="0.0"
    android:toYScale="1.0" />

 

Now Lets jump in to the Main list activity where we initialize the Adapter and set our list view. Here is how the MainActivity looks like:

import java.util.ArrayList;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

public class MainActivity extends SherlockActivity implements OnItemClickListener {

	ListView lvMyList;
	ArrayList<MyListItem> listItems = new ArrayList<MyListItem>();
	ActionBar actionBar;
	MyListAdapter myListAdapter;

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

		lvMyList = (ListView) findViewById(R.id.lvMyList);
		lvMyList.setOnItemClickListener(this);

		for (int i = 0; i < 20; i++) {
			MyListItem item = new MyListItem();
			item.setTitle("Sample Title " + (i + 1));
			listItems.add(item);
		}

		myListAdapter = new MyListAdapter(this, listItems);
		lvMyList.setAdapter(myListAdapter);

	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
		// show description

	}

	public static final class AnActionModeOfEpicProportions implements ActionMode.Callback {

		Context ctx;

		public AnActionModeOfEpicProportions(Context ctx) {
			this.ctx = ctx;
		}

		@Override
		public boolean onCreateActionMode(ActionMode mode, Menu menu) {

			menu.add("Delete").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
			menu.add("Archive").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
			menu.add("Mark unread").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
			menu.add("Move").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
			menu.add("Remove star").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

			return true;
		}

		@Override
		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
			return false;
		}

		@Override
		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

			Toast toast = null;

			ArrayList<MyListItem> selectedListItems = new ArrayList<MyListItem>();

			StringBuilder selectedItems = new StringBuilder();

			// get items selected
			for (MyListItem i : ((MainActivity) ctx).myListAdapter.mailList) {
				if (i.isChecked()) {
					selectedListItems.add(i);
					selectedItems.append(i.getTitle()).append(", ");
				}
			}

			if (item.getTitle().equals("Delete")) {
				// Delete
				toast = Toast.makeText(ctx, "Delete: " + selectedItems.toString(), Toast.LENGTH_SHORT);

			} else if (item.getTitle().equals("Archive")) {
				// Archive
				toast = Toast.makeText(ctx, "Archive: " + selectedItems.toString(), Toast.LENGTH_SHORT);

			} else if (item.getTitle().equals("Mark unread")) {
				// Mark unread
				toast = Toast.makeText(ctx, "Mark unread: " + selectedItems.toString(), Toast.LENGTH_SHORT);

			} else if (item.getTitle().equals("Move")) {
				// Move
				toast = Toast.makeText(ctx, "Move: " + selectedItems.toString(), Toast.LENGTH_SHORT);

			} else if (item.getTitle().equals("Remove star")) {
				// Remove star
				toast = Toast.makeText(ctx, "Remove star: " + selectedItems.toString(), Toast.LENGTH_SHORT);

			}
			if (toast != null) {
				toast.show();
			}
			mode.finish();
			return true;
		}

		@Override
		public void onDestroyActionMode(ActionMode mode) {
			// Action mode is finished reset the list and 'checked count' also
			// set all the list items checked states to false
			((MainActivity) ctx).myListAdapter.checkedCount = 0;
			((MainActivity) ctx).myListAdapter.isActionModeShowing = false;
			// set list items states to false
			for (MyListItem item : ((MainActivity) ctx).listItems) {
				item.setIsChecked(false);
			}
			((MainActivity) ctx).myListAdapter.notifyDataSetChanged();
			Toast.makeText(ctx, "Action mode closed", Toast.LENGTH_SHORT).show();
		}
	}

}

 

Now, Lets jump in to the meat of the Application, The Adapter class:

import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.actionbarsherlock.view.ActionMode;

public class MyListAdapter extends BaseAdapter {

	Context context;
	ArrayList<MyListItem> mailList;
	Animation animation1;
	Animation animation2;
	ImageView ivFlip;
	int checkedCount = 0;
	ActionMode mMode;
	boolean isActionModeShowing;

	public MyListAdapter(Context context, ArrayList<MyListItem> mailList) {
		this.context = context;
		this.mailList = mailList;

		animation1 = AnimationUtils.loadAnimation(context, R.anim.to_middle);
		animation2 = AnimationUtils.loadAnimation(context, R.anim.from_middle);

		isActionModeShowing = false;
	}

	@Override
	public int getCount() {
		return mailList.size();
	}

	@Override
	public MyListItem getItem(int position) {
		return mailList.get(position);
	}

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

	@SuppressWarnings("deprecation")
	@Override
	public View getView(final int position, View convertView, ViewGroup parent) {
		ViewHolder holder;

		LayoutInflater inflater = (LayoutInflater) context.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		if (convertView == null) {
			convertView = inflater.inflate(R.layout.list_item, null);
			holder = new ViewHolder();
			holder.title = (TextView) convertView.findViewById(R.id.title);
			holder.selectBox = (ImageView) convertView.findViewById(R.id.selectBox);
			convertView.setTag(holder);
		}

		holder = (ViewHolder) convertView.getTag();

		holder.title.setText(getItem(position).getTitle());
		holder.selectBox.setTag("" + position);
		holder.selectBox.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				ivFlip = (ImageView) v;
				ivFlip.clearAnimation();
				ivFlip.setAnimation(animation1);
				ivFlip.startAnimation(animation1);
				setAnimListners(mailList.get(Integer.parseInt(v.getTag().toString())));
			}

		});

		if (mailList.get(position).isChecked()) {
			holder.selectBox.setImageResource(R.drawable.cb_checked);
			convertView.setBackgroundColor(context.getResources().getColor(R.color.list_highlight));

		} else {
			holder.selectBox.setImageResource(R.drawable.cb_unchecked);
			convertView.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.list_selector));

		}

		return convertView;

	}

	private void setAnimListners(final MyListItem curMail) {
		AnimationListener animListner;
		animListner = new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
				if (animation == animation1) {
					if (curMail.isChecked()) {
						ivFlip.setImageResource(R.drawable.cb_unchecked);
					} else {
						ivFlip.setImageResource(R.drawable.cb_checked);
					}
					ivFlip.clearAnimation();
					ivFlip.setAnimation(animation2);
					ivFlip.startAnimation(animation2);
				} else {
					curMail.setIsChecked(!curMail.isChecked());
					setCount();
					setActionMode();
				}
			}

			// Set selected count
			private void setCount() {
				if (curMail.isChecked()) {
					checkedCount++;
				} else {
					if (checkedCount != 0) {
						checkedCount--;
					}
				}

			}

			// Show/Hide action mode
			private void setActionMode() {
				if (checkedCount > 0) {
					if (!isActionModeShowing) {
						mMode = ((MainActivity) context).startActionMode(new MainActivity.AnActionModeOfEpicProportions(context));
						isActionModeShowing = true;
					}
				} else if (mMode != null) {
					mMode.finish();
					isActionModeShowing = false;
				}

				// Set action mode title
				if (mMode != null)
					mMode.setTitle(String.valueOf(checkedCount));

				notifyDataSetChanged();

			}

			@Override
			public void onAnimationRepeat(Animation arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onAnimationEnd(Animation arg0) {
				// TODO Auto-generated method stub

			}
		};

		animation1.setAnimationListener(animListner);
		animation2.setAnimationListener(animListner);

	}

	static class ViewHolder {
		TextView title;
		ImageView selectBox;
	}

}

 

MyListItem is an Entity where it holds the list items Name and Checked state. Here how it looks:

public class MyListItem {

	private String name;
	private boolean isChecked = false;

	public boolean isChecked() {
		return isChecked;
	}

	public void setIsChecked(boolean isChecked) {
		this.isChecked = isChecked;
	}

	public String getTitle() {
		return name;
	}

	public void setTitle(String name) {
		this.name = name;
	}
}

 

 Download Sources:

TD Flip Multiselect List

Subscribe like and stay tuned!

The post Gmail like – Flip animated Multi selection list view with action mode. appeared first on Techie Dreams.


Viewing all articles
Browse latest Browse all 21

Trending Articles