Glisser L'élément ListView de droite à gauche afficher le bouton Supprimer
J'ai un ListView personnalisé montrant la liste des mots sélectionnés à partir de la base de données. Quand je glisse cet article listview je veux montrer le bouton Supprimer comme l'image ci-dessous. Et quand j'appuie sur ce bouton, il est supprimé de la base de données et rafraîchit le listview. m
je regarde déjà dans ce code d'échantillon ici . Mais il ne fonctionne toujours pas.
10 réponses
EDIT: entre autres options, il y a une belle bibliothèque qui pourrait résoudre votre problème: https://github.com/daimajia/AndroidSwipeLayout
j'ai beaucoup cherché sur google et trouver le projet le mieux adapté est le swipmenulistview https://github.com/baoyongzhang/SwipeMenuListView sur github.
j'avais le même problème à trouver une bonne bibliothèque pour faire ça. Finalement, j'ai créé une bibliothèque qui peut faire cela: SwipeRevealLayout
dans gradle file:
dependencies {
compile 'com.chauthai.swipereveallayout:swipe-reveal-layout:1.4.0'
}
dans votre fichier 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>
puis dans votre fichier adaptateur:
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
}
}
j'avais créé une démo sur mon github qui inclut Sur le balayage de droite à gauche un bouton Supprimer apparaîtra et vous pouvez ensuite supprimer votre article de la ListView et mettre à jour votre ListView.
je viens d'obtenir son travail en utilisant le viseur dans 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>
dans le ListAdapter: Implémenter OnclickListeners pour le bouton Edit et Delete dans la méthode getView (). Le piège ici est d'obtenir la position du Listem cliqué à l'intérieur des méthodes onClick. les méthodes setTag() et getTag() sont utilisées pour cela.
@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;
}
dans le Fragment, Ajouter un L'auditeur de geste pour détecter le geste 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;
}
}
dans la méthode onCreateView du Fragment,
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;
}
}
});
ça a marché pour moi. Devrait affiner davantage.
voir là lien était très agréable et simple. son travail très bien... tu ne veux pas d'une bibliothèque qui fonctionne bien. cliquez sur ici
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;
}
};
une application est disponible qui montre un listview qui combine le swiping-to-delete et le glisser-déposer pour réorganiser des articles. Le code est basé sur Chet Haase du code de balayage à supprimer et Daniel Olshansky du code pour le déplacement à réorganiser.
le code de Chet supprime un élément immédiatement. J'ai amélioré cela en le faisant fonctionner plus comme Gmail où swiping révèle une vue du bas qui indique que l'article est supprimé, mais fournit un bouton Annuler où l'Utilisateur a le possibilité d'annuler la suppression. Le code de Chet contient aussi un bug. Si vous avez moins d'items dans la liste que la hauteur de la listview est et vous supprimer le dernier élément, le dernier élément semble pas être supprimé. Ceci a été corrigé dans mon code.
le code de Daniel exige de presser longtemps sur un article. Beaucoup d'utilisateurs trouvent cette fonction peu intuitive car elle tend à être cachée. Au lieu de cela, j'ai modifié le code pour permettre un bouton "Déplacer". Vous appuyez simplement sur le bouton et faites glisser l'élément. Ce n'est plus en ligne avec la façon dont Google Actualités application fonctionne lorsque vous réorganisez des sujets d'actualité.
le code source avec une application de démonstration est disponible à: https://github.com/JohannBlake/ListViewOrderAndSwipe
Chet et Daniel sont tous deux de Google.
la vidéo de Chet sur la suppression d'articles peut être consultée à: https://www.youtube.com/watch?v=YCHNAi9kJI4
vidéo sur la réorganisation des éléments peut être consulté à l': https://www.youtube.com/watch?v=_BZIvjMgH-Q
une somme considérable de travail a été consacrée au collage de tout cela pour fournir une expérience D'assurance-chômage sans apparence, alors j'apprécierais un vote similaire ou plus. Veuillez également commencer le projet à Github.
définissez un ViewPager dans votre mise en page .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" />
et ensuite, dans votre activité / fragment, définissez un adaptateur de pageur personnalisé:
dans une activité:
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);
}
dans un fragment:
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;
}
créer notre classe de pager personnalisé:
// 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];
}
}
C'est une perte de temps pour mettre en œuvre à partir de zéro cette fonctionnalité. J'ai mis en œuvre la bibliothèque recommandée par SalutonMondo et je suis très satisfait. Il est très simple à utiliser et très rapide. J'ai amélioré la bibliothèque originale et j'ai ajouté un nouveau lecteur de clics pour le clic d'article. J'ai aussi ajouté font awesome library ( http://fortawesome.github.io/Font-Awesome / ) et maintenant vous pouvez simplement ajouter un nouveau titre d'article et spécifier le nom de l'icône de font awesome.
ici est le lien github
j'ai parcouru des tonnes de bibliothèques tierces pour essayer d'atteindre cet objectif. Mais aucun d'entre eux ne présente l'expérience de la douceur et de la convivialité que je voulais. Alors j'ai décidé d'écrire moi-même. Et le résultat a été , eh bien, je l'ai aimé. Je partagerai le code ici. Peut-être que je vais l'écrire comme une bibliothèque qui peut être intégré dans tout recycleur vue dans l'avenir. Mais pour l'instant voici le code.
Note: j'utilise la vue recycleur et la vue Holder. Certaines valeurs sont codées de manière à changer selon vos exigences.
-
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.Adaptateur {
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); } } }
Espérons que cela aide quelqu'un!!