Recently I found couple of applications that have that nice feature when you swipe item on list view you get menu with additional options that you can click and perform an action . I checked out Android Arsenal to see what libraries are already available for this functionality. I found two interesting implementations : SwipeMenuListView and SwipeListView. In this article I shall show you how you can use this first one and discuss little bit what I liked and disliked in this implementation. Latter one I shall leave for another article.
For SwipeMenuListView you can find source code on a GitHub, also you can find some demo code. I modified little bit this demo code so that I can test it and present it in this article. First let us start with importing this library into our project. This is pretty simple, all you need to do is checkout the project, take all classes from the package com.baoyz.swipemenulistview, create same package in your project and copy these classes. That’s all, no need for any additional configuration.
Now, how we are going to use this library in our project? First of all, we shall create main layout that will just have SimpleMenuListView tag inside:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.baoyz.swipemenulistview.SwipeMenuListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"/> </LinearLayout>
This is pretty simple, if you look at the implementation of class com.baoyz.swipemenulistview.SwipeMenuListView you shall see that it extends ListView class, this means that all attributes of the tag ListView should be applicable for this implementation, but I have not found any attributes that are custom for this component. for purpose of presentation we shall create one more layout that will be used for each row in a list view, later we shall define adapter and use this layout.
<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="wrap_content" android:padding="8dp" > <ImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/item_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="10sp" android:layout_toRightOf="@+id/image_view" android:text="name" android:textColor="@android:color/black" android:textSize="18sp" /> </RelativeLayout>
To make use of this layout we need custom adapter:
public class CustomArrayAdapter extends ArrayAdapter<String>{ protected LayoutInflater inflater; protected int layout; public CustomArrayAdapter(Activity activity, int resourceId, List<String> objects){ super(activity, resourceId, objects); layout = resourceId; inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = inflater.inflate(layout, parent, false); TextView tv = (TextView)v.findViewById(R.id.item_label); tv.setText(getItem(position)); return v; } }
And finally let us see how main activity looks like:
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SwipeMenuListView listView = (SwipeMenuListView)findViewById(R.id.listView); final List<String> list = new ArrayList<>(); list.add("Test 1"); list.add("Test 2"); list.add("Test 3"); final CustomArrayAdapter adapter = new CustomArrayAdapter(this, R.layout.list_item, list); listView.setAdapter(adapter); SwipeMenuCreator creator = new SwipeMenuCreator() { @Override public void create(SwipeMenu menu) { //create an action that will be showed on swiping an item in the list SwipeMenuItem item1 = new SwipeMenuItem( getApplicationContext()); item1.setBackground(new ColorDrawable(Color.DKGRAY)); // set width of an option (px) item1.setWidth(200); item1.setTitle("Action 1"); item1.setTitleSize(18); item1.setTitleColor(Color.WHITE); menu.addMenuItem(item1); SwipeMenuItem item2 = new SwipeMenuItem( getApplicationContext()); // set item background item2.setBackground(new ColorDrawable(Color.RED)); item2.setWidth(200); item2.setTitle("Action 2"); item2.setTitleSize(18); item2.setTitleColor(Color.WHITE); menu.addMenuItem(item2); } }; //set MenuCreator listView.setMenuCreator(creator); // set SwipeListener listView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() { @Override public void onSwipeStart(int position) { // swipe start } @Override public void onSwipeEnd(int position) { // swipe end } }); listView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(int position, SwipeMenu menu, int index) { String value = adapter.getItem(position); switch (index) { case 0: Toast.makeText(getApplicationContext(), "Action 1 for "+ value , Toast.LENGTH_SHORT).show(); break; case 1: Toast.makeText(getApplicationContext(), "Action 2 for "+ value , Toast.LENGTH_SHORT).show(); break; } return false; }}); } }
First part of method onCreate represents setting the layout, fetching the SwipeMenuListView from defined layout, defining list of values for items in the list view and instantiating adapter for SwipeMenuListView. Second partof the code defines SwipeMenuCreator. For this class you have to ovrerride createMenu method that has a parameter of SwipeMenu class. SwipeMenu represents a list of items defined as SwipeMenuItems (options in the menu that represent actions), this menu is showed once you swipe an item of a list view. For each SwipeMenuItem you can define: id, icon, background, title, title color, title size and width. Width is defined in px so in the example on GitHub authors provided a method dp2px that you can use.
After you set MenuCreator, next is to define and set OnSwipeListener for SwipeMenuListView. OnSwipeListener is an interface that has two methods defined: onSwipeStart and onSwipeEnd where you can override and define certain actions, in this example we have left them empty.
Final step in setting up SwipeMenuListView is to set OnMenuItemClickListener. In this listener you are defining actions that are to be executed on selection of each item in the swipe menu. All what is needed here is to override method onMenuItemClick. This method provides as a parameter index that identifies item that is clicked and position of the item from SwipeMenuListView. Once you define this listener everything is ready and should work perfectly fine. Below you can see an screenshot of application we described here.
Now what I would like to see as enhancement of this project/library is that we can define our menu items using xml layout file.N, looking at the limitations on this library there are some that can be solved in future releases, one of them is a number of items and width of and item you can have in the swipe menu, in a way it is limited by the width of your screen, so if list of items in swipe menu go beyond the border of the screen after swipe, you will not be able to select them. In that way, another enhancement that I would like to see here is that once swipe menu is opened you are able to swipe trough the menu list and position yourself on a item you want to select.
Next time we shall look at another library that provides same functionality.
gud evng sir
for 3 listview iems it works perfectly.when we want to perform 20 listview items i got position problem plz tell me how to overcome this problem.
What do you mean by position problem (what is happening exactly)? Also post a part of your code that you believe it is making problem.
I have the same issue… for eg:
items.add(new Item(“Item 1″,”First Item on the list”,”abc”,”Item 1.4″,”Item 1.5″));
items.add(new Item(“Item 2″,”Second Item on the list”,”xyz”,”item 2.4″,”item 2.5″));
items.add(new Item(“Item 3″,”Third Item on the list”,”qwe”,”item 3.4″,”item 3.5″));
items.add(new Item(“Item 4″,”Forth Item on the list”,”qwe”,”item 4.4″,”item 4.5″));
items.add(new Item(“Item 5″,”Fifth Item on the list”,”qwe”,”item 5.4″,”item 5.5″));
items.add(new Item(“Item 6″,”Sixth Item on the list”,”qwe”,”item 6.4″,”item 6.5″));
items.add(new Item(“Item 7″,”Seventh Item on the list”,”qwe”,”item 7.4″,”item 7.5″));
this is the array list… but in the application, the position of these items are random and also some of the items disappear as well.. Can you help me??
Hello!
Very good your tutorial! I’m just a problem in the presentation of the lines, when I use the com.baoyz.swipemenulistview.SwipeMenuListView view the text and the image of the lines is repeated. I’ll post a picture to illustrate what I mean. Do you know if there is a bug that? When I use the common ListView not have this problem.
Thank you for your attention.
Link to the image: Left ListView – Right SwipeMenuListView
https://peoplewaytecnologia-my.sharepoint.com/personal/ramorim_peopleway_com_br/_layouts/15/guestaccess.aspx?guestaccesstoken=PoC0cHOf9ya9PurOgXa8TXTX0w7NPvEC4Q3xPWrqikk%3d&docid=0355700484af54e699d9be5c86093b78c
Can you post some of your code, it will be easier to check the problem.
Hi!
Thx for attention!
All code here
activity_main.xml
Activity
protected Usuario usuario;
/**
* O DAO do Usuário.
*/
protected UsuarioDAO usuarioDAO;
/**
/**
* A lista de empresas.
*
*/
private SwipeMenuListView listEmpresas;
/** O BO da mensagem
private MensagemBO mensagemBO;
*/
/**
* O BO da empresa
*/
private EmpresaBO empresaBO;
/**
* Lista de empresa temporaria utilizada para mudar de ‘recentes’ para
* ‘todos’ e vice-versa
*/
private List empresasTemp;
/**
* A lista completa de empresas
*/
private List empresas;
/**
* O Comparator que ordena por quantidade de PA.
*/
private Comparator comparatorEmpresaPorPa;
/**
* O Comparator que ordena por ultimo acesso
*/
private Comparator comparatorEmpresaUltimoAcesso;
/**
* O Adapter da lista de todas as empresas
*/
private EmpresasAdapter empresasAdapterTodos;
/**
* O Adapter da lista das empresas recentemente acessadas
*/
private EmpresasAdapter empresasAdapterRecentes;
/**
* O Adapter da lista das empresas favoritas
*/
private EmpresasAdapter empresasAdapterFavoritos;
private BroadcastReceiver mBroadcastReceiver;
private ProgressBar progressCarregamentoLista;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, “onCreate(Bundle savedInstanceState)”);
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mainContext = this;
abas = (LinearLayout) findViewById(R.id.layoutBotoes);
/*
O campo utilizado para busca na lista de empresas
*/
EditText editBusca = (EditText) findViewById(R.id.editBusca);
listEmpresas = (SwipeMenuListView) findViewById(R.id.listEmpresas);// (SwipeMenuListView)
progressCarregamentoLista = (ProgressBar) findViewById(R.id.progressCarregamento);
// Atualiza a lista de Empresas
empresaBO = new EmpresaBO(this);
comparatorEmpresaPorPa = new ComparatorEmpresaPorPa();
comparatorEmpresaUltimoAcesso = new ComparatorEmpresaUltimoAcesso();
usuarioDAO = new UsuarioDAO(this);
usuario = usuarioDAO.getUsuario();
usuarioDAO.fechar();
empresas = empresaBO.buscarTodos();
empresasTemp = empresas;
// Primeira ordenção da lista ordena por PA.
Collections.sort(empresasTemp, comparatorEmpresaPorPa);
// Configura a busca nas lista de empresas
editBusca.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
empresasAdapterTodos.getFilter().filter(s);
empresasAdapterRecentes.getFilter().filter(s);
empresasAdapterFavoritos.getFilter().filter(s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
// configura os adapters para a listagem
empresasAdapterTodos = new EmpresasAdapter(this, empresasTemp);
empresasAdapterRecentes = new EmpresasAdapter(this, new ArrayList());
empresasAdapterFavoritos = new EmpresasAdapter(this, new ArrayList());
// Criacao do botao lateral da listEmpresas para o historico
SwipeMenuCreator creator = new SwipeMenuCreator() {
@Override
public void create(SwipeMenu menu) {
// create “open” item
SwipeMenuItem historicoItem = new SwipeMenuItem(
getApplicationContext());
// set item background
historicoItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
0xCE)));
// set item width
historicoItem.setWidth(dp2px(90));
// set item title
historicoItem.setTitle(“Historico”);
// set item title fontsize
historicoItem.setTitleSize(18);
// set item title font color
historicoItem.setTitleColor(Color.WHITE);
historicoItem.setIcon(R.drawable.ic_menu_recent_history);
// add to menu
menu.addMenuItem(historicoItem);
}
};
listEmpresas.setMenuCreator(creator);
listEmpresas.setAdapter(empresasAdapterTodos);
listEmpresas.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
switch (index) {
case 0:
carregarHistorico(position);
break;
}
// false : close the menu; true : not close the menu
return false;
}
});
// Inicia o chat com a empresa selecionada.
listEmpresas.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Log.i(CATEGORIA, “Iniciando Chat com:” + id + “(id da lista)”);
iniciarChat(position, false);
}
});
}
I need to implement swiping from both the sides to show different menu options. How can I do this? Please advice. Thanks.
Well you shall have to find library for this … try it on https://android-arsenal.com/
How can I add a custom view as a menu item. I have a layout(xml file). I want to show that as menu when user swipes the list row. Is it possible ?
I think I mentioned at the end of this article that this is currently a limitation to have your custom layout as option menu that shows up after you swipe element. Maybe there is a newer version now of this library. Please check.
Do I need to purchase license to use this library in my commercial android application.
http://opensource.org/licenses/MIT
how can i hide previously opened item and open the new one in a single swipe or touchEvent
Not sure that this is possible in this library.
You can do this by setting “setOnItemClickListener” to swipeListView and override onItemClick.
add the follwing code inside onItemClick
swipeListView.smoothOpenMenu(position);
This will open the new item and close the previously opened.
Can you provide a code of deleting an element in swipe list view?
adapter.remove(adapter.getItem(position));
adapter.notifyDataSetChanged();
Hope this will help 🙂
how can i disable the swipe functioin of listview under some conditions?