- 投稿日:2019-08-11T23:33:29+09:00
[Java]RecyclerViewの使用方法とアニメーション付きスワイプ処理の実装をメモ。
1. はじめに
1.1 お断り
このサイトではQiita内の投稿をいくつかリンクさせていただいております。不愉快だと感じた投稿者様はコメントしていただければ幸いです。対応させていただきます。
1.2 目的
RecyclerView
はとても便利です。僕はListView
の代わりに使っているのですがその実装方法とスワイプの実装を忘れてしまうのでここにメモをします。スワイプのアニメーションはGmail
のメール削除のスワイプをまねます。2. RecyclerView本体
この実装内容は「RecyclerViewの基本」by@naoi様と同じです。とても分かりやすく解説されています。
RecyclerView
の仕組みは少し複雑なので図も覚えとくといいと思いますよ。ここでは以下の四つを制作します。
-adapter_row.xml
-DataModel.java
-ViewHolder.java
-Adapter.java
今回、入れるデータは画像と文字列にしましょう。
2.1 一列のレイアウトを決める (adapter_row.xml)
RecyclerView
の一列のレイアウトを決めます。adapter_row<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/imageView_adapter_show_bitmap" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/textView_adapter_show_string" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </android.support.constraint.ConstraintLayout>2.2 構造体を作る (DataModel.java)
Javaに構造体はありませんが、
Class
で代用できますよね。DataModel.javapublic class DataModel { private Bitmap mBitmap; private String mString; public Bitmap getBitmap () { return mBitmap; } public String getString () { return mString; } public void setBitmap (Bitmap mBitmap) { this.mBitmap = mBitmap; } public void setString (String mString) { this.mString = mString; } }メンバ変数に
m
を付ける習慣って一般的にはないんですかね...余談ですが「get~」とか「set~」っていうのは
getter/setter
ていうらしいですが、AndroidStudio
で、public
まで打つとメンバ変数のgetter/setter
を作ってくれるそう。ちょっと名前変えたらそれで完成だからありがたい。2.3 一行内のViewを取得 (ViewHolder.java)
ViewHolder
を作ります。ここでxml
本体は指定しませんが一行のなかのView
をfindViewByID()
します。ViewHolder.javapublic class ViewHolder extends RecyclerView.ViewHolder { public ImageView mImageView; public TextView mTextView; // コンストラクタ public ViewHolder (@NonNull View itemView) { super(itemView); mImageView = itemView.findViewById(R.id.imageView_adapter_show_bitmap); mTextView = itemView.findViewById(R.id.textView_adapter_show_string); } }コンストラクタは
RecyclerView.ViewHolder
を継承すると引数にitemView
を追加するように要求されます。2.4 データを配置する (Adapter.java)
Adapter.javapublic class Adapter extends RecyclerView.Adapter<ViewHolder> { private List<DataModel> insertDataList; public Adapter (List<DataModel> list) { this.insertDataList = list; } @NonNull @Override public NoteViewHolder onCreateViewHolder (@NonNull ViewGroup viewGroup, int i) { View inflate = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.adapter_row, viewGroup, false); return new ViewHolder(inflate); } @Override public void onBindViewHolder (@NonNull ViewHolder viewHolder, int i) { noteViewHolder.mImageView.setImageBitmap(insertDataList.get(i).getBitmap()); noteViewHolder.mTextView.setText(insertDataList.get(i).getString()); } @Override public int getItemCount () { return insertDataList.size(); } }3.使い方
Activity
等での使い方は以下の通りです。
Adapterは他のと競合してしまうかも...(僕は実際、違う名前を付けている。)MainActivity.javapublic class RegisterNoteActivity extends AppCompatActivity { RecyclerView mRecyclerViewList; @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerViewList = findViewById(R.id.recyclerView_main); LinearLayoutManager manager = new LinearLayoutManager(this); mRecyclerViewList.setHasFixedSize(false); mRecyclerViewList.setLayoutManager(manager); mRecyclerViewList.setAdapter(new Adapter(createData())); } private List<NoteDataModel> createData() { List<NoteDataModel> list = new ArrayList<>(); for (int index = 0; index < 100; index++) { // 一行分のデータ NoteDataModel rowData = new NoteDataModel(); rowData.setBitmap(/*なんかの画像*/); rowData.setmString("この行は" + (index + 1) + "回目の繰り返しです。"); list.add(rowData); } return list; } }4. スワイプ
アニメーション付きスワイプを実装しましょう。
実をいうともともとスワイプを実装すると横にずれたり、シュッって消えたりするアニメーションはついてきます。色とアイコンはついてこないのでここを実装すればいいということです。
今回は左スワイプの時のみ削除にします。色は赤でアイコンは自前のゴミ箱マークです。MainActivity.java// ...省略 @Override protected void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register_note); // ...省略... mRecyclerViewList.setAdapter(new Adapter(createData())); // さっきの // ここから追加 final Drawable deleteIcon = ContextCompat.getDrawable(this, R.drawable.ic_action_delete); ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) { @Override public boolean onMove (@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) { return false; } @Override public void onSwiped (@NonNull RecyclerView.ViewHolder viewHolder, int i) { int swipedPosition = viewHolder.getAdapterPosition(); Adapter adapter = (Adapter) mRecyclerView.getAdapter(); // 登録とかするんだったらなにかのリストから削除をする処理はここ // 削除されたことを知らせて反映させる。 adapter.notifyItemRemoved(swipedPosition); } @Override public void onChildDraw (@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); View itemView = viewHolder.itemView; // キャンセルされた時 if (dX == 0f && !isCurrentlyActive) { clearCanvas(c, itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, false); return; } ColorDrawable background = new ColorDrawable(); background .setColor(Color.parseColor("#f44336")); background.setBounds(itemView.getRight() + (int)dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); background.draw(c); int deleteIconTop = itemView.getTop() + (itemView.getHeight() - deleteIcon.getIntrinsicHeight()) / 2; int deleteIconMargin = (itemView.getHeight() - deleteIcon.getIntrinsicHeight()) / 2; int deleteIconLeft = itemView.getRight() - deleteIconMargin - deleteIcon.getIntrinsicWidth(); int deleteIconRight = itemView.getRight() - deleteIconMargin; int deleteIconBottom = deleteIconTop + deleteIcon.getIntrinsicHeight(); deleteIcon.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom); deleteIcon.draw(c); } }; new ItemTouchHelper(callback).attachToRecyclerView(mRecyclerView); } private void clearCanvas(Canvas c, int left, int top, int right, int bottom) { Paint paint = new Paint(); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); c.drawRect(left, top, right, bottom, paint); } // 省略...アイコンの画像や計算、色コード、処理思想は「Android のリストをスワイプして削除する #あれどうやるの?」by@shts様とそのGithubからいただきました。無断ですみません。
スワイプが完了したときに発火するのは
onSwiped
ですが、それに対してキャンセルしたとしても途中に毎フレームごとに呼ばれるのがonChildDraw
です。onMove
はドラッグアンドドロップも許可したとき用だそうですがfalse
を返しとけばいいのかな?追記ですが右スワイプと左スワイプ両方を許可するのは以下の通りにやればいいみたいです。
ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { @Override public boolean onMove (@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) { return false; } @Override public void onSwiped (@NonNull RecyclerView.ViewHolder viewHolder, int i) { } @Override public void onChildDraw (@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); if (dX < 0) { // 左スワイプのとき } else { // 右スワイプのとき } } };隠れてぱっと見では見えないけど、一行目の最後、
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT
になってるので気を付けてください。
onChildDraw
は上記通りなのですが、onSwiped
での処理の分け方はわからないです。(i
を使うのかな?)5.まとめ
まずは参考にさせていただいたサイトの投稿者様誠にありがとうございました。少し雑ではありますがこちらでまとめて紹介させていただきます。
RecyclerViewの基本
RecyclerView本体についてほぼ同じようにまねさせていただたきました。RecyclerViewでドラッグアンドドロップの移動とスワイプの削除
スワイプのイメージをつかみました。Android のリストをスワイプして削除する #あれどうやるの?
スワイプの処理についてJavaに書き直させていただきました。
→画像と詳しい処理は付属のGitHubからです。Android で RecyclerView を使って横スワイプで要素を削除する方法のメモ
JavaでAdapterをどうやて更新するかを参考にしました。RecyclerViewのアイテムをスワイプで削除する方法
投稿外での追加の処理について参考にしました。皆さんありがとうございました。
こうまでして他人のコードを取りまくっていくことでしか処理を生み出せない自分が情けないですが、だからこそだれかのためになれればなと思います。Twitter: https://twitter.com/Cyber_Hacnosuke (フォローしてくださいお願いします。)
いいねもお願いします。
- 投稿日:2019-08-11T13:04:27+09:00
【Programming News】Qiitaまとめ記事 Weekly August 2nd week, 2019 Vol.4
筆者が2019/8/4(日)~8/10(土)に気になったQiitaの記事のまとめのまとめを作成しました。日々のまとめ記事のWeekly版です。
皆様が興味のある言語や思いもよらぬハック方法をこの中から見つけられたら幸いです。
Java
- Tips
- Spring Framework
- Spring Boot
Python
- Django
- Tips
- PyAutoGUIを使ったPythonアプリをexe化するまで
- Kali LinuxにWingIDE(Python統合開発環境)インストール
- Watsonで数独を解く! Decision Optimizerを使ってみた
- pythonのパッケージ階層の話
- Gray-Scottモデルで模様のアニメーションを描く
- Expatを使ってPythonでXMLを解析する話
- PipenvでDjango開発環境をつくる
- 【Python】 Pythonで自己位置推定
- WGANgpで無限にラーメン画像生成する話
- 30行で顔認識(OpenCV)してファイル出力!
- PythonでJSONの入出力(エンコーディングもしっかりと)
- Python + Jinja2 でデータを HTML に埋め込んで JavaScript 側から利用する
- Python スタイルガイドとリンター
- Kaggle
- Tools
Ruby
Rails
- Beginner
- Tips
- RubyのRailsをMySQLでHerokuにあげてみた
- RubyOnRails/自動更新機能の実装
- RubyOnRails/インクリメンタルサーチの実装
- Rails6 のちょい足しな新機能を試す63(db:system:change 編)
- Rails 3-5 複数のデータベースに接続する方法
- Railsのerbをslimに変更する方法
- Rails6新機能 ActionText使用方法
- Rails6 のちょい足しな新機能を試す64(db:seed 編)
- RailsのStrong Parametersを一括で処理するメソッド
- Railsで開発されているOSS
- 本番環境でRailsを起動しようとした時のMysql5.7系に関するエラー
- Rails6 のちょい足しな新機能を試す65(timestamps precision編)
- Railsにdeviseを導入する方法
- deviseの日本語対応
- RailsでS3から画像やPDFファイルをダウンロードする方法
- Railsのサービスクラスを作る前に考えるべきこと
- rails font-awesome-sass導入方法
- AWS利用上のセキュリティを確保する方法
- railsでYoutube data APIを使ってみた
- gem'devise'に頼りすぎていて、sessionとcookieの概念が疎かだったので、まとめる
C#
Android
- Tips
- Androidでグラフを作ってみる
- FragmentでLiveData#observeを使うときの第一引数(Owner)には
viewLifecycleOwner
を使う- Cordova 9.0にバージョンアップする際にハマったこと
- Androidスマホの位置情報をKibanaで可視化してみる
- Android Jetpackのリリース前のバージョンを使う方法
- Android JetpackのApp Crawlerを動かしてみる
- Retrofitの返り値は
Observable
とSingle
などとはどっちがいいか- Activityを再起動させたいけど余分な画面を一枚挟まないといけない…という場合に有効なライブラリ
- AndroidX 導入手順
Swift
- Tips
- Apps
Kotlin
- Tips
Flutter
- Beginner
Fulx
JavaScript
- Beginner
- Tips
React
- Beginner
- Tips
- Apps
Node.js
- Tips
- Express
- Tools
- Apps
Vue.js
- Beginner
- Tips
Vuex
Nuxt.js
- Tips
Nest.js
Angular
jQuery
TypeScript
C#
PowerApps
ReactNative
Laravel
- Tips
C
PHP
CakePHP
Rust
Go言語
- Tips
R言語
- Tips
Scala
Haskell
Unity
Spark
Line
- Tips
- Apps
A-Frame
- Beginner
- Tips
PowerApp
Line
HTML
CSS
Sass
SQL
MySQL
- Tips
PostgreSQL
Oracle
MongoDB
SQL Server
Apache
ビッグデータ
Visual Studio Code
IntelliJ IDEA
AI
IoC
Git
- Beginner
- Tips
AWS
- Beginner
- Tips
- EC2
- AWS Lambda
- LambdaでのCloudWatch LogsからS3へのエクスポート
- Lambda×node.jsでGB単位の動画をStreamAPIでアップロードする方法
- AWS Lambdaでのbundle install
- AWS LambdaとPythonでスクレイピング処理をマイクロサービス化する
- API Gateway + LambdaでAPI Keyの値を取得する
- AWS Lambda:API GatewayとApplication Load Balancerの違い
- CloudWatchの空になったロググループ削除
- LambdaでIAMユーザーのアクセスキーを監視
- AWS Lambdaを使ってAndroid JetpackのリリースをRSSで受け取れるようにした
- Amazon S3
- Amazon MQ
- AWS CDK
- AWS CLI
- AWS SAM
- AWS Clinet VPN
- AWS CloudHSM
- AWS Certificate Manager
- AWS CloudFormation
- AWS CodeCommit
- AWS Textract
- AWS Fargate
- AWS WAF
- AWS Inspector
- DynamoDB
Azure
- Tips
Oracle Cloud
IBM Cloud
Active Directory
Cloud SQL
Cloud9
インフラ
ブロックチェーン
Ethereum
Hyperledger
セキュリティ
機械学習
自然言語処理
Network
RPA
CI
Docker
- Tips
- Dockerイメージをレジストリに登録する(ECR含む)
- Dockerを使ってKali Linuxの環境を構築した時のメモ
- Dockerでrails開発環境構築(リバースプロキシで複数アプリを構築)
- 簡単な静的ページと簡単なAPIサーバーをGoogle Cloud Runで動かす
- Docker上でLaravelを動かしてみよう(laradockなしで)
- AWS (ECS + RDS)+ CircleciによるCI/CDの理解(初学者がインプットすべき情報)~用語と概念理解編~
- Autoware(1.9.1) Docker セットアップ
- Docker for WindowsでDockerイメージを一括削除するワンライナースクリプト
- Laradockでローカルサーバを立ち上げてブラウザ表示する方法
- Docker上にDjangoとReactの環境を構築する
- macにdocker-composeでwordpressをたてる
Heroku
VirtualBox
kubernetes
OpenStack
Swagger
- Tips
AMP
OpenID
OAuth2.0
Elasticsearch
Linux
Cent OS
Windows
Mac
Redis
- Beginner
Google API
Google Apps Script
Google Cloud Platform
Google Colaboratory
Google Cloud Data Catalog
Google Drive
VB.Net
Firebase
Server Side
CSS
BootStrap
WordPress
Develop
- Beginner
- Tips
- Tools
Keras
PowerShell
Vim
Atom
awk
LaTex
Redmine
UML
- Beginner
Raspberry
- Tips
- Apps
RPA
IoT
Alexa
Line
SharePoint
VBA
ShellScript
PowerShell
Slack
Nim
Emacs
WPF
UI
Ansible
Arduino
Julia
Coral
ionic
- Tips
QRCode
OCR
EC-CUBE
- Beginner
資格
転職
更新情報
Kotlin
- Kotlin入門
Android
Java
IDE