web-dev-qa-db-ja.com

Android ListViewを左右にスワイプして承認および拒否

次のスクリーンショットのように、左から右にスワイプすると、左隅に受け入れ(true)アイコン(クリック不可-左から右にスワイプすると色の変化のみが表示される)を表示するリストビューを開発します。

enter image description here

左から右にスワイプすると受け入れられ(「accept」APIを呼び出します)、右から左にスワイプすると次のように表示されます。

enter image description here

これはiOSで行われますが、Androidでこれを行う方法が見つかりません。グーグルで試しましたが、必要なものを正確に見つけることができませんでした。

次の例を試してみました: http://www.tutecentral.com/Android-swipe-listview/

しかし、その例では、左から右および右から左にスワイプすると、同じonOpened(..)メソッドが呼び出されるため、同じメソッドがどのタイプでも呼び出されるため、acceptを呼び出すタイミングとreject APIを呼び出すタイミングを知るのは混乱しますスワイプの。

そして、私は左右にスワイプしたときにのみ受け入れ(左側)と拒否(右側)の画像を表示したいが、指を離すとそれらは消えなければならず、ListView全体が表示されるはずです(両方の画像を同時に表示しないでください)。

だから、誰も私がこれを行う方法を理解するのを助けてください。

私の質問はやや混乱しますが、アニメーション全体を説明する方法がわからないので、上記のように説明しようとしました。

誰かが私を助けることができれば、それは非常にありがたいです。

11
Joseph Mekwan

ソリューション番号1:

機能の「近く」に到達するには、次のようにする必要があります。

ListViewのアダプタをラップします

次のように:

  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);
  }

スワイプの方向ごとに背景レイアウトを作成します

次のように:

  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);
}

ここからライブラリとサンプルの両方を取得しました: https://github.com/wdullaer/SwipeActionAdapter

これはあなたが望むようには正確ではありませんが、これがあなたの機能を果たすのに大いに役立つことを願っています。

ソリューション番号2:

ソリューション2は、使用済みコードの一部のコードを変更することです: http://www.tutecentral.com/Android-swipe-listview/ =

リンクからコードを試してみました http://www.tutecentral.com/Android-swipe-listview/ といくつかのコードを変更し、onOpened(..)に関する問題(混乱)を正常に解決しましたメソッド(左から右、またはその逆)

最初の変更:

  1. custom_row.xmlレイアウトファイルには3つのボタンswipe_button1から3があり、それらの中央を削除します。

  2. 残りの2つのボタンの次のコードをコピーして貼り付けます。

    <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" />
    

このレイアウトのコードは同じままです。

2番目の変更:

これで、受け入れコードと拒否コードおよびリストコードの準備ができました。onOpened(..)メソッドについて説明します。

混乱の解決策1-あなたが言った、あなたのonOpend(...)メソッドは同じように左から右とその逆

->次を変更するだけです:

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);
            }


        }

混乱の解決策2指を離すと、リストビュー全体が表示されるか、リストビューの側面が角を保持する必要があるため、動作しません

->私はすでに上記で答えました

swipelistview.closeAnimate(position);と呼ばれる場合、それ以外の場合は、左右にスワイプしたときに左の受け入れ画像と右の拒否画像が非表示になります。

最終的なコードは次のとおりです。

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>

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;
  }

 }

他のコードとライブラリは同じままですが、あなたや他の人にも役立つので、楽しんでください。

14
Nirav Mehta

それは私のために働いた...それがあなたのために働くことを願っています..!

onTouchListenerをlistviewに設定します

listview.setOnTouchListener(new OnSwipeTouchListener(getActivity(),
            listview));

OnSwipeTouchListenerクラスは次のとおりです。

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;
        }

    }
}
7
Pratibha Sarode

それ以外の場合は、ビューロジック(回避する必要があるもの)を使用してコントローラーをフルフィルすることになります https://github.com/xenione/SwipeLayout いくつかの例があるスワイプメーカーがあります

1
Xenione

@Pratibha Sarodeソリューションに基づいて、カーソルアダプタとデータベースでポピュレートされたリストビューで次のように適応します:主なアクティビティ:

  //-- 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();
        }
    });

スワイプ移動で行を削除するのは素晴らしいことです!

1
AndroLogiciels

this libraryを見てください。非常に良い例を示し、uを正しい方向に向けます。幸運を。

1
EE66

https://stackoverflow.com/a/31094315/291414 で答えを使用して、私はそうしました。

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;
    }
};

アダプターのgetViewに以下を記述します。

@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;
}

Item_layout.xml内でHorizo​​ntalScrollViewを使用しても同じことが実現できると思います。

0
CoolMind