読者です 読者をやめる 読者になる 読者になる

うさがにっき

読書感想文とプログラムのこと書いてきます

RecyclerVIewとCardViewを使ってswipeで消えるリストを作る

Android

概要

こんな感じでswipeで消えるリストを作る
f:id:tiro105:20150320162834p:plain

詳細

まずは画面を構成するcardViewとRecyclerViewを使えるように、RecylerViewを内包したbrnunes:swipeablerecyclerviewをgradleに記述する

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.github.brnunes:swipeablerecyclerview:1.0.0'
    compile "com.android.support:cardview-v7:+"
}

cardView, RecyclerViewはlollipopから採用されたwidgetなので詳しくはここら辺を見る
CardView | Android Developers
RecyclerView | Android Developers

特にrecyclerviewはlistviewの進化版みたいな扱われ方をしがちだが、そもそもの理念が違うっぽいので注意、ここらへんにわかりやすく書いてくれている
sys1yagi.hatenablog.com

話を本筋に戻す
RecylerViewのadapter

public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {
    private LayoutInflater mLayoutInflater;
    private ArrayList<String> mDataList;

    public SampleAdapter(Context context, ArrayList<String> dataList) {
        super();
        mLayoutInflater = LayoutInflater.from(context);
        mDataList = dataList;
    }

    // getViewのinfrateするところだけ取り出した感じ
    @Override
    public SampleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = mLayoutInflater.inflate(R.layout.list_item, parent, false);
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }

    @Override
    public int getItemCount() {
        return mDataList.size();
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String data = (String) mDataList.get(position);
        holder.text.setText(data);
    }

    // ViewHolder内でwidgetを割り当てる
    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView text;

        public ViewHolder(View v) {
            super(v);
            text = (TextView) v.findViewById(R.id.text);
        }
    }
}

activity

public class MainActivity extends Activity {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        // コンテンツの変化でRecyclerViewのサイズが変わらない場合は、
        // パフォーマンスを向上させることができる
        mRecyclerView.setHasFixedSize(true);

        // LinearLayoutManagerを使用する
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);
        // テストデータを作成する
        final ArrayList<String> myDataSet = new ArrayList<String>() {
            {
                add("北海道");
                add("青森県");
                add("茨城県");
                add("新潟県");
                add("三重県");
                add("鳥取県");
                add("徳島県");
                add("福岡県");
                add("沖縄県");
                add("岩手県");
                add("栃木県");
                add("富山県");
                add("滋賀県");
                add("島根県");
                add("香川県");
                add("佐賀県");
            }
        };

        // アダプタを指定する
        mAdapter = new SampleAdapter(this, myDataSet);
        mRecyclerView.setAdapter(mAdapter);

        SwipeableRecyclerViewTouchListener swipeTouchListener =
                new SwipeableRecyclerViewTouchListener(mRecyclerView,
                        new SwipeableRecyclerViewTouchListener.SwipeListener() {
                            @Override
                            public boolean canSwipe(int position) {
                                return true;
                            }

                            @Override
                            public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
                                for (int position : reverseSortedPositions) {
                                    myDataSet.remove(position);
                                    mAdapter.notifyItemRemoved(position);
                                }
                                mAdapter.notifyDataSetChanged();
                            }

                            @Override
                            public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
                                for (int position : reverseSortedPositions) {
                                    myDataSet.remove(position);
                                    mAdapter.notifyItemRemoved(position);
                                }
                                mAdapter.notifyDataSetChanged();
                            }
                        });

        mRecyclerView.addOnItemTouchListener(swipeTouchListener);
    }

}

SwipeableRecyclerViewTouchListenerをrecyclerViewに設定すればOK
非常にわかりやすいインタフェースで神がかっていて説明は不要と思うが一応のちの自分のために

public boolean canSwipe(int position)

  • postionのものがswipeできるかを記載

public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions)

  • 設定でマルチタッチとかできるからreverseSortedPositionsはint[]なのかな?とりあえず何もしなかったら対象のpositionが一つだけ帰ってくる

public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions)

  • 設定でマルチタッチとかできるからreverseSortedPositionsはint[]なのかな?とりあえず何もしなかったら対象のpositionが一つだけ帰ってくる

一応activityとadapterのxmlもはっとく
activity

<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="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

adapter

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:padding="25dp"
    android:elevation="10dp"
    card_view:cardBackgroundColor="#ffaaaa"
    card_view:cardCornerRadius="8dp">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="40dp"
         />

</android.support.v7.widget.CardView>

これでswipeで消えるリスト実現できる
ライブラリ作ってくれた人に感謝、感謝

参考

stackoverflow.com
github.com