Desplazar el elemento ListView De derecha a izquierda mostrar el botón de borrado

Tengo un ListView personalizado que muestra la lista de palabras que seleccionan de la base de datos. Cuando deslizo este elemento listview quiero mostrar el botón Eliminar como imagen a continuación. Y cuando presiono ese botón es borrado de la base de datos y refresco el listview. metro Desplegar elemento de vista de lista

Ya veo este código de ejemplo aquí . Pero todavía no funciona.

EDIT: entre otras opciones hay una bonita biblioteca que podría resolver su problema: https://github.com/daimajia/AndroidSwipeLayout

He buscado en google mucho y encontrar el proyecto más adecuado es el swipmenulistview https://github.com/baoyongzhang/SwipeMenuListView en github.

Solía ​​tener el mismo problema para encontrar una buena biblioteca para hacer eso. Eventualmente, creé una biblioteca que puede hacer eso: SwipeRevealLayout

En el archivo gradle:

dependencies { compile 'com.chauthai.swipereveallayout:swipe-reveal-layout:1.4.0' } 

En su archivo xml:

 <com.chauthai.swipereveallayout.SwipeRevealLayout android:layout_width="match_parent" android:layout_height="match_parent" app:mode="same_level" app:dragEdge="left"> <!-- Your secondary layout here --> <FrameLayout android:layout_width="wrap_content" android:layout_height="match_parent" /> <!-- Your main layout here --> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" /> </com.chauthai.swipereveallayout.SwipeRevealLayout> 

A continuación, en el archivo adaptador:

 public class Adapter extends RecyclerView.Adapter { // This object helps you save/restore the open/close state of each view private final ViewBinderHelper viewBinderHelper = new ViewBinderHelper(); @Override public void onBindViewHolder(ViewHolder holder, int position) { // get your data object first. YourDataObject dataObject = mDataSet.get(position); // Save/restore the open/close state. // You need to provide a String id which uniquely defines the data object. viewBinderHelper.bind(holder.swipeRevealLayout, dataObject.getId()); // do your regular binding stuff here } } 

Había creado una demostración en mi github que incluye al pasar de derecha a izquierda un botón de borrado aparecerá y luego puede eliminar su elemento de ListView y actualizar su ListView.

Acabo de obtener su trabajo con el ViewSwitcher en un ListItem.

List_item.xml:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ViewSwitcher android:id="@+id/list_switcher" android:layout_width="match_parent" android:layout_height="fill_parent" android:inAnimation="@android:anim/slide_in_left" android:outAnimation="@android:anim/slide_out_right" android:measureAllChildren="false" > <TextView android:id="@+id/tv_item_name" android:layout_width="match_parent" android:layout_height="50dp" android:layout_gravity="center_vertical" android:maxHeight="50dp" android:paddingLeft="10dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:clickable="false" android:gravity="center" > <Button android:id="@+id/b_edit_in_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Edit" android:paddingLeft="20dp" android:paddingRight="20dp" /> <Button android:id="@+id/b_delete_in_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Delete" android:paddingLeft="20dp" android:paddingRight="20dp" android:background="@android:color/holo_red_dark" /> </LinearLayout> </ViewSwitcher> 

En ListAdapter: implemente OnclickListeners para el botón Editar y Eliminar en el método getView (). La captura aquí es obtener la posición del ListItem clicado dentro de los métodos onClick. Para esto se utilizan los métodos setTag () y getTag ().

 @Override public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub final ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); convertView = mInflater.inflate(R.layout.list_item, null); viewHolder.viewSwitcher=(ViewSwitcher)convertView.findViewById(R.id.list_switcher); viewHolder.itemName = (TextView) convertView .findViewById(R.id.tv_item_name); viewHolder.deleteitem=(Button)convertView.findViewById(R.id.b_delete_in_list); viewHolder.deleteItem.setTag(position); viewHolder.editItem=(Button)convertView.findViewById(R.id.b_edit_in_list); viewHolder.editItem.setTag(position); viewHolder.deleteItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub fragment.deleteItemList((Integer)v.getTag()); } }); viewHolder.editItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub fragment.editItemList(position); } }); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.itemName.setText(itemlist[position]); return convertView; } 

En el fragmento, agregue un detector de gestos para detectar el gesto de fling:

 public class MyGestureListener extends SimpleOnGestureListener { private ListView list; public MyGestureListener(ListView list) { this.list = list; } // CONDITIONS ARE TYPICALLY VELOCITY OR DISTANCE @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // if (INSERT_CONDITIONS_HERE) ltor=(e2.getX()-e1.getX()>DELTA_X); if (showDeleteButton(e1)) { return true; } return super.onFling(e1, e2, velocityX, velocityY); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return super.onScroll(e1, e2, distanceX, distanceY); } private boolean showDeleteButton(MotionEvent e1) { int pos = list.pointToPosition((int) e1.getX(), (int) e1.getY()); return showDeleteButton(pos); } private boolean showDeleteButton(int pos) { View child = list.getChildAt(pos); if (child != null) { Button delete = (Button) child .findViewById(R.id.b_edit_in_list); ViewSwitcher viewSwitcher = (ViewSwitcher) child .findViewById(R.id.host_list_switcher); TextView hostName = (TextView) child .findViewById(R.id.tv_host_name); if (delete != null) { viewSwitcher.setInAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_in_left)); viewSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_out_right)); } viewSwitcher.showNext(); // frameLayout.setVisibility(View.VISIBLE); } return true; } return false; } } 

En el método onCreateView del fragmento,

 GestureDetector gestureDetector = new GestureDetector(getActivity(), new MyGestureListener(hostList)); hostList.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub if (gestureDetector.onTouchEvent(event)) { return true; } else { return false; } } }); 

Esto funcionó para mí. Debería refinarlo más.

Ver allí el acoplamiento era muy agradable y simple. Su trabajo bien … u no quieren que cualquier biblioteca está funcionando bien. Haga clic aquí

 OnTouchListener gestureListener = new View.OnTouchListener() { private int padding = 0; private int initialx = 0; private int currentx = 0; private ViewHolder viewHolder; public boolean onTouch(View v, MotionEvent event) { if ( event.getAction() == MotionEvent.ACTION_DOWN) { padding = 0; initialx = (int) event.getX(); currentx = (int) event.getX(); viewHolder = ((ViewHolder) v.getTag()); } if ( event.getAction() == MotionEvent.ACTION_MOVE) { currentx = (int) event.getX(); padding = currentx - initialx; } if ( event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { padding = 0; initialx = 0; currentx = 0; } if(viewHolder != null) { if(padding == 0) { v.setBackgroundColor(0xFF000000 ); if(viewHolder.running) v.setBackgroundColor(0xFF058805); } if(padding > 75) { viewHolder.running = true; v.setBackgroundColor(0xFF00FF00 ); viewHolder.icon.setImageResource(R.drawable.clock_running); } if(padding < -75) { viewHolder.running = false; v.setBackgroundColor(0xFFFF0000 ); } v.setPadding(padding, 0,0, 0); } return true; } }; 

Definir un ViewPager en su diseño .xml:

 <android.support.v4.view.ViewPager android:id="@+id/example_pager" android:layout_width="fill_parent" android:layout_height="@dimen/abc_action_bar_default_height" /> 

Y luego, en su actividad / fragmento, configure un adaptador de paginador personalizado:

En una actividad:

 protected void onCreate(Bundle savedInstanceState) { PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager()); ViewPager pager = (ViewPager) findViewById(R.id.example_pager); pager.setAdapter(adapter); // pager.setOnPageChangeListener(this); // You can set a page listener here pager.setCurrentItem(0); } 

En un fragmento:

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_layout, container, false); if (view != null) { PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager()); ViewPager pager = (ViewPager) view.findViewById(R.id.example_pager); pager.setAdapter(adapter); // pager.setOnPageChangeListener(this); // You can set a page listener here pager.setCurrentItem(0); } return view; } 

Cree nuestra clase de paginador personalizada:

 // setup your PagerAdapter which extends FragmentPagerAdapter class PagerAdapter extends FragmentPagerAdapter { public static final int NUM_PAGES = 2; private CustomFragment[] mFragments = new CustomFragment[NUM_PAGES]; public PagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); } @ Override public int getCount() { return NUM_PAGES; } @ Override public Fragment getItem(int position) { if (mFragments[position] == null) { // this calls the newInstance from when you setup the ListFragment mFragments[position] = new CustomFragment(); } return mFragments[position]; } } 

Es una pérdida de tiempo implementar desde cero esta funcionalidad. Implementé la biblioteca recomendada por SalutonMondo y estoy muy satisfecho. Es muy simple de usar y muy rápido. He mejorado la biblioteca original y he añadido un nuevo oyente de clics para el clic de artículo. También agregué la biblioteca impresionante de la fuente ( http://fortawesome.github.io/Font-Awesome/ ) y ahora usted puede simplemente agregar un nuevo título del artículo y especificar el nombre del icono de la fuente impresionante.

Aquí está el enlace github

Está disponible una aplicación que muestra una vista de lista que combina el desplazamiento a borrar y el arrastrar para reordenar elementos. El código se basa en el código de Chet Haase para borrar a borrar y el código de Daniel Olshansky para arrastrar a reordenar.

El código de Chet elimina un elemento inmediatamente. He mejorado en esto haciendo que funcione más como Gmail donde swiping revela una vista inferior que indica que el elemento se elimina, pero proporciona un botón Deshacer donde el usuario tiene la posibilidad de deshacer la eliminación. El código de Chet también tiene un error. Si tiene menos elementos en la vista de lista que la altura de la vista de lista y elimina el último elemento, el último elemento no se eliminará. Esto fue arreglado en mi código.

El código de Daniel requiere presionar mucho sobre un elemento. Muchos usuarios encuentran esto poco intuitivo ya que tiende a ser una función oculta. En su lugar, modifiqué el código para permitir un botón "Mover". Simplemente presione el botón y arrastre el elemento. Esto está más en consonancia con la forma en que funciona la aplicación Google Noticias cuando reordena temas de noticias.

El código fuente junto con una aplicación demo está disponible en: https://github.com/JohannBlake/ListViewOrderAndSwipe

Chet y Daniel son ambos de Google.

El video de Chet sobre la eliminación de elementos se puede ver en: https://www.youtube.com/watch?v=YCHNAi9kJI4

El video de Daniel sobre reordenación de artículos se puede ver en: https://www.youtube.com/watch?v=_BZIvjMgH-Q

Una cantidad considerable de trabajo entró encolado todo esto juntos para proporcionar una experiencia de UI aparentemente, por lo que apreciaría un Like o Up Vote. Por favor, también protagonice el proyecto en Github.

He ido a través de toneladas de bibliotecas de terceros para tratar de lograr esto. Pero ninguno de ellos muestra la suavidad y la experiencia de uso que yo quería. Entonces decidí escribirlo yo mismo. Y el resultado fue, bueno, me encantó. Compartiré el código aquí. Tal vez lo escribiré como una biblioteca que se puede incrustar en cualquier vista de reciclador en el futuro. Pero por ahora aquí está el código.

Nota: tengo el uso de la vista de reciclador y ViewHolder. Algunos valores son hardcoded así que cambíelos según su requisito.

  • Row_layout.xml

     <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:orientation="horizontal"> <Button android:id="@+id/slide_button_2" android:text="Button2" android:layout_width="80dp" android:layout_height="80dp" /> <Button android:id="@+id/slide_button_1" android:text="Button1" android:layout_width="80dp" android:layout_height="80dp" /> </LinearLayout> <LinearLayout android:id="@+id/chat_row_cell" android:layout_width="match_parent" android:layout_height="80dp" android:orientation="horizontal" android:background="@color/white"> <ImageView android:id="@+id/chat_image" android:layout_width="60dp" android:layout_height="60dp" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_marginRight="10dp" android:layout_gravity="center"/> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/chat_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/md_grey_800" android:textSize="18sp"/> <TextView android:id="@+id/chat_subtitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/md_grey_600"/> </LinearLayout> </LinearLayout> </LinearLayout> 

  • ChatAdaptor.java

    Public class ChatAdaptor extends RecyclerView.Adapter {

     List<MXGroupChatSession> sessions; Context context; ChatAdaptorInterface listener; public interface ChatAdaptorInterface{ void cellClicked(MXGroupChatSession session); void utilityButton1Clicked(MXGroupChatSession session); void utilityButton2Clicked(MXGroupChatSession session); } public ChatAdaptor(List<MXGroupChatSession> sessions, ChatAdaptorInterface listener, Context context){ this.sessions=sessions; this.context=context; this.listener=listener; } @Override public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view=(View)LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_row,null); ChatViewHolder chatViewHolder=new ChatViewHolder(view); return chatViewHolder; } @Override public void onBindViewHolder(ChatViewHolder holder, final int position) { MXGroupChatSession session=this.sessions.get(position); holder.selectedSession=session; holder.titleView.setText(session.getTopic()); holder.subtitleView.setText(session.getLastFeedContent()); Picasso.with(context).load(new File(session.getCoverImagePath())).transform(new CircleTransformPicasso()).into(holder.imageView); } @Override public int getItemCount() { return sessions.size(); } public class ChatViewHolder extends RecyclerView.ViewHolder{ ImageView imageView; TextView titleView; TextView subtitleView; ViewGroup cell; ViewGroup cellContainer; Button button1; Button button2; MXGroupChatSession selectedSession; private GestureDetectorCompat gestureDetector; float totalx; float buttonTotalWidth; Boolean open=false; Boolean isScrolling=false; public ChatViewHolder(View itemView) { super(itemView); cell=(ViewGroup) itemView.findViewById(R.id.chat_row_cell); cellContainer=(ViewGroup) itemView.findViewById(R.id.chat_row_container); button1=(Button) itemView.findViewById(R.id.slide_button_1); button2=(Button) itemView.findViewById(R.id.slide_button_2); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.utilityButton1Clicked(selectedSession); } }); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.utilityButton2Clicked(selectedSession); } }); ViewTreeObserver vto = cellContainer.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { buttonTotalWidth = button1.getWidth()+button2.getWidth(); } }); this.titleView=(TextView)itemView.findViewById(R.id.chat_title); subtitleView=(TextView)itemView.findViewById(R.id.chat_subtitle); imageView=(ImageView)itemView.findViewById(R.id.chat_image); gestureDetector=new GestureDetectorCompat(context,new ChatRowGesture()); cell.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(gestureDetector.onTouchEvent(event)){ return true; } if(event.getAction() == MotionEvent.ACTION_UP) { if(isScrolling ) { isScrolling = false; handleScrollFinished(); }; } else if(event.getAction() == MotionEvent.ACTION_CANCEL){ if(isScrolling ) { isScrolling = false; handleScrollFinished(); }; } return false; } }); } public class ChatRowGesture extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { if (!open){ listener.cellClicked(selectedSession); } return true; } @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { isScrolling=true; totalx=totalx+distanceX; freescroll(totalx); return true; } } void handleScrollFinished(){ if (open){ if (totalx>2*buttonTotalWidth/3){ slideLeft(); totalx=buttonTotalWidth; }else{ slideRight(); totalx=0; } }else{ if (totalx>buttonTotalWidth/3){ slideLeft(); totalx=buttonTotalWidth; }else{ slideRight(); totalx=0; } } } void slideRight(){ TransitionManager.beginDelayedTransition(cellContainer); ViewGroup.MarginLayoutParams params; params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams(); params.setMargins(0,0,0,0); cell.setLayoutParams(params); open=false; } void slideLeft(){ TransitionManager.beginDelayedTransition(cellContainer); ViewGroup.MarginLayoutParams params; params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams(); params.setMargins(((int)buttonTotalWidth*-1),0,(int)buttonTotalWidth,0); cell.setLayoutParams(params); open=true; } void freescroll(float x){ if (x<buttonTotalWidth && x>0){ int xint=(int)x; ViewGroup.MarginLayoutParams params; params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams(); params.setMargins(params.leftMargin,0,xint,0); cell.setLayoutParams(params); } } } 

Espero que esto ayude a alguien !!

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.