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:
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:
Subscribe like and stay tuned!
You may also like
The post Gmail like – Flip animated Multi selection list view with action mode. appeared first on Techie Dreams.