Je souhaite développer un affichage sous forme de liste qui, une fois balayée de gauche à droite - affiche dans le coin gauche une icône d'acceptation (vrai) (non cliquable - indique uniquement un changement de couleur lorsque vous balayez de gauche à droite), comme dans la capture d'écran suivante:
Lorsque je glisse de gauche à droite, il accepte (en appelant l'API "accept"), .__ et, lorsque je glisse de droite à gauche, le message suivant s'affiche:
Ceci est fait dans iOS, mais je ne trouve pas comment faire cela dans Android, j'ai essayé de googler mais je ne trouvais pas exactement ce que je voulais.
J'ai essayé l'exemple suivant: http://www.tutecentral.com/Android-swipe-listview/
mais dans cet exemple, lorsque je balaie de gauche à droite et de droite à gauche, la même méthode onOpened (..) est appelée. Il est donc déroutant de savoir quand appeler accept et quand appeler une API rejetée, car la même méthode est appelée pour tout type de glisser.
et je souhaite également que les images accept (du côté gauche) et rejetées (du côté droit) ne s'affichent que lorsque je balaie le curseur gauche-droite ou droite-gauche, mais lorsque je lève le doigt, elles doivent disparaître et l'ensemble de la liste doit être affiché. (ne jamais montrer les deux images en même temps).
Alors, aidez-moi à comprendre comment procéder.
Ma question est quelque peu déroutante mais je ne sais pas comment expliquer toute l'animation, alors j'ai essayé de l'expliquer comme ci-dessus.
Si quelqu'un peut m'aider, ce serait très apprécié.
Solution numéro 1:
Vous devez faire comme suit pour atteindre "près" de votre fonctionnalité,
Enveloppe l'adaptateur de votre ListView
Comme suit:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create an Adapter for your content
String[] content = new String[20];
for (int i=0;i<20;i++) content[i] = "Row "+(i+1);
ArrayAdapter<String> stringAdapter = new ArrayAdapter<String>(
this,
R.layout.row_bg,
R.id.text,
new ArrayList<String>(Arrays.asList(content))
);
// Wrap your content in a SwipeActionAdapter
mAdapter = new SwipeActionAdapter(stringAdapter);
// Pass a reference of your ListView to the SwipeActionAdapter
mAdapter.setListView(getListView());
// Set the SwipeActionAdapter as the Adapter for your ListView
setListAdapter(mAdapter);
}
Créer une mise en page d'arrière-plan pour chaque direction de balayage
J'aime suivre:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create an Adapter for your content
String[] content = new String[20];
for (int i=0;i<20;i++) content[i] = "Row "+(i+1);
ArrayAdapter<String> stringAdapter = new ArrayAdapter<String>(
this,
R.layout.row_bg,
R.id.text,
new ArrayList<String>(Arrays.asList(content))
);
// Wrap your content in a SwipeActionAdapter
mAdapter = new SwipeActionAdapter(stringAdapter);
// Pass a reference of your ListView to the SwipeActionAdapter
mAdapter.setListView(getListView());
// Set the SwipeActionAdapter as the Adapter for your ListView
setListAdapter(mAdapter);
// Set backgrounds for the swipe directions
mAdapter.addBackground(SwipeDirections.DIRECTION_FAR_LEFT,R.layout.row_bg_left_far)
.addBackground(SwipeDirections.DIRECTION_NORMAL_LEFT,R.layout.row_bg_left)
.addBackground(SwipeDirections.DIRECTION_FAR_RIGHT,R.layout.row_bg_right_far)
.addBackground(SwipeDirections.DIRECTION_NORMAL_RIGHT,R.layout.row_bg_right);
}
Vous avez les deux bibliothèques et exemple de ici: https://github.com/wdullaer/SwipeActionAdapter
Cela n’exécutera pas exactement ce que vous voulez, mais j’espère que cela vous aidera beaucoup à remplir vos fonctions.
Solution numéro 2:
La solution 2 concerne le changement de code dans votre code utilisé: http://www.tutecentral.com/Android-swipe-listview/
j'avais essayé ton code depuis le lien http://www.tutecentral.com/Android-swipe-listview/ et en changeant un peu de code pour résoudre avec succès ton problème (ta confusion) à propos de la méthode onOpened (..) (appelée de gauche à droite et vice versa)
Premier changement:
le fichier de disposition custom_row.xml comporte trois boutons swipe_button1 à 3, remove au milieu d’eux.
Copier coller le code suivant pour rester deux boutons:
<Button
Android:id="@+id/swipe_button1"
Android:layout_width="48dp"
Android:layout_height="48dp"
Android:layout_alignParentLeft="true"
Android:layout_alignParentTop="true"
Android:background="@drawable/your_accept_image" />
<Button
Android:id="@+id/swipe_button3"
style="@style/MyListButtonAction"
Android:layout_width="48dp"
Android:layout_height="48dp"
Android:layout_alignParentRight="true"
Android:layout_alignParentTop="true"
Android:background="@drawable/your_reject_image" />
Reste le même code pour cette mise en page.
Deuxième changement:
Alors maintenant, votre code d’acceptation et de rejet et le code de liste sont prêts, discutez maintenant de la méthode onOpened (..).
Solution de confusion 1 - Vous avez dit, votre méthode onOpend (...) a appelé la même chose de gauche à droite et vice-verset
-> juste pour changer suivant:
public void onOpened(int position, boolean toRight) {
if(toRight)
{
// for left to right your api calling here
swipelistview.closeAnimate(position);
}
else
{
// for right to left your api calling here
swipelistview.closeAnimate(position);
}
}
Solution de confusion 2 quand je prends le doigt vers le haut, il doit afficher tout le listview ou les côtés de listview doivent le conserver dans les coins pour que cela ne fonctionne pas
-> je l'ai déjà répondu ci-dessus
appelé swipelistview.closeAnimate (position); dans les deux cas sinon, il masque à gauche l'acceptation et à droite l'image de rejeter lorsque vous faites glisser votre doigt vers la gauche et la droite.
Le code final est donc le suivant:
Disposition complète de cutom_row.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent" >
<RelativeLayout
Android:id="@+id/back"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:tag="back" >
<Button
Android:id="@+id/swipe_button1"
Android:layout_width="48dp"
Android:layout_height="48dp"
Android:layout_alignParentLeft="true"
Android:layout_alignParentTop="true"
Android:background="@drawable/accept_image" />
<Button
Android:id="@+id/swipe_button3"
style="@style/MyListButtonAction"
Android:layout_width="48dp"
Android:layout_height="48dp"
Android:layout_alignParentRight="true"
Android:layout_alignParentTop="true"
Android:background="@drawable/reject_image" />
</RelativeLayout>
<RelativeLayout
Android:id="@+id/front"
style="@style/MyListFrontContent"
Android:orientation="vertical"
Android:tag="front" >
<ImageView
Android:id="@+id/example_image"
style="@style/MyListImage" />
<TextView
Android:id="@+id/example_itemname"
style="@style/MyListTitle"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:layout_toRightOf="@id/example_image" />
</RelativeLayout>
</FrameLayout>
Ensemble MainActivity.Java
public class MainActivity extends Activity {
SwipeListView swipelistview;
ItemAdapter adapter;
List<ItemRow> itemData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipelistview=(SwipeListView)findViewById(R.id.example_swipe_lv_list);
itemData=new ArrayList<ItemRow>();
adapter=new ItemAdapter(this,R.layout.custom_row,itemData);
swipelistview.setSwipeListViewListener(new BaseSwipeListViewListener() {
@Override
public void onOpened(int position, boolean toRight) {
if(toRight)
{
// for left to right your api calling here
swipelistview.closeAnimate(position);
}
else
{
// for right to left your api calling here
swipelistview.closeAnimate(position);
}
}
@Override
public void onClosed(int position, boolean fromRight) {
// close list slide
}
@Override
public void onListChanged() {
}
@Override
public void onMove(int position, float x) {
}
@Override
public void onStartOpen(int position, int action, boolean right) {
Log.d("swipe", String.format("onStartOpen %d - action %d", position, action));
}
@Override
public void onStartClose(int position, boolean right) {
Log.d("swipe", String.format("onStartClose %d", position));
}
@Override
public void onClickFrontView(int position) {
Log.d("swipe", String.format("onClickFrontView %d", position));
}
@Override
public void onClickBackView(int position) {
Log.d("swipe", String.format("onClickBackView %d", position));
swipelistview.closeAnimate(position);//when you touch back view it will close
}
@Override
public void onDismiss(int[] reverseSortedPositions) {
}
});
//These are the swipe listview settings. you can change these
//setting as your requirement
swipelistview.setSwipeMode(SwipeListView.SWIPE_MODE_BOTH); // there are five swiping modes
// swipelistview.setSwipeActionLeft(SwipeListView.SWIPE_ACTION_DISMISS); //there are four swipe actions
swipelistview.setSwipeActionRight(SwipeListView.SWIPE_ACTION_REVEAL);
swipelistview.setOffsetLeft(convertDpToPixel(0f)); // left side offset
swipelistview.setOffsetRight(convertDpToPixel(80f)); // right side offset
swipelistview.setAnimationTime(500); // Animation time
swipelistview.setSwipeOpenOnLongPress(true); // enable or disable SwipeOpenOnLongPress
swipelistview.setAdapter(adapter);
for(int i=0;i<10;i++)
{
itemData.add(new ItemRow("Swipe Item"+ i,getResources().getDrawable(R.drawable.ic_launcher) ));
}
adapter.notifyDataSetChanged();
}
public int convertDpToPixel(float dp) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return (int) px;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Les autres codes et bibliothèques restent les mêmes, Cela vous sera utile, à vous aussi, alors profitez-en.
Cela a fonctionné pour moi ... j'espère que cela fonctionnera pour vous ..!
définir OnTouchListener sur listview en tant que
listview.setOnTouchListener(new OnSwipeTouchListener(getActivity(),
listview));
La classe OnSwipeTouchListener est la suivante:
public class OnSwipeTouchListener implements OnTouchListener {
ListView list;
private GestureDetector gestureDetector;
private Context context;
public OnSwipeTouchListener(Context ctx, ListView list) {
gestureDetector = new GestureDetector(ctx, new GestureListener());
context = ctx;
this.list = list;
}
public OnSwipeTouchListener() {
super();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
public void onSwipeRight(int pos) {
//Do what you want after swiping left to right
}
public void onSwipeLeft(int pos) {
//Do what you want after swiping right to left
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
private int getPostion(MotionEvent e1) {
return list.pointToPosition((int) e1.getX(), (int) e1.getY());
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY)
&& Math.abs(distanceX) > SWIPE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0)
onSwipeRight(getPostion(e1));
else
onSwipeLeft(getPostion(e1));
return true;
}
return false;
}
}
}
S'il vous plaît éviter l'approche ci-dessus, sinon vous allez à plein contrôleur avec la logique de vue (quelque chose que vous devez éviter) visitez https://github.com/xenione/SwipeLayout
basée sur la solution @Pratibha Sarode, je l’adapte comme suit avec une listview poupulée avec un curseuradaptor et une base de données: Dans l’activité principale:
//-- Attach cursor adapter to the ListView
lvItems.setAdapter(todoAdapter);
/////////////////// Swipe Management
lvItems.setOnTouchListener(new OnSwipeList(AfficList.this,lvItems){
public void onSwipeRight(int pos) {
AnnonceDbHandler dbHandler = new AnnonceDbHandler(AfficList.this, null, null, 1);
String sIdAnn=dbHandler.RechercheIdIndex(pos);
//Toast.makeText(AfficList.this, "Right ("+pos+") : "+sIdAnn, Toast.LENGTH_SHORT).show();
dbHandler.deleteAnnonce(sIdAnn, AfficList.this);
Cursor NewCursor = dbAnnonces.rawQuery("SELECT * FROM annonces", null);
todoAdapter.swapCursor(NewCursor);
lvItems.setAdapter(todoAdapter);
todoAdapter.notifyDataSetChanged();
}
public void onSwipeLeft(int pos) {
AnnonceDbHandler dbHandler = new AnnonceDbHandler(AfficList.this, null, null, 1);
String sIdAnn=dbHandler.RechercheIdIndex(pos);
//Toast.makeText(AfficList.this, "Right ("+pos+") : "+sIdAnn, Toast.LENGTH_SHORT).show();
dbHandler.deleteAnnonce(sIdAnn, AfficList.this);
Cursor NewCursor = dbAnnonces.rawQuery("SELECT * FROM annonces", null);
todoAdapter.swapCursor(NewCursor);
lvItems.setAdapter(todoAdapter);
todoAdapter.notifyDataSetChanged();
}
});
Cela fonctionne très bien de supprimer des lignes avec le déplacement par glissement!
Jetez un oeil à this library, cela vous donnera de très bons exemples et vous indiquera la bonne direction. Bonne chance.
Utiliser une réponse sur https://stackoverflow.com/a/31094315/2914140 Je l’ai fait.
View.OnTouchListener swipeListener = new View.OnTouchListener() {
private float dx;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dx = v.getX() - event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
// You can limit x-coordinate.
float x = Math.min(event.getRawX() + dx, 0);
// x = Math.max(x, ((View) v.getParent()).getWidth() - v.getWidth()); // Scroll if layout is wider than screen.
v.animate()
.x(x)
.setDuration(0)
.start();
break;
default:
return false;
}
return true;
}
};
Dans getView
de votre adaptateur, écrivez:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_layout, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// Fill data.
final Item item = items.get(position);
viewHolder.caption.setText(item.getCaption());
// Set onTouch listener.
convertView.setOnTouchListener(swipeListener);
return convertView;
}
Je pense que la même chose peut être obtenue en utilisant HorizontalScrollView dans item_layout.xml.