質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

847閲覧

RecyclerViewタスクの削除時に日付が表示されない

kbayashi

総合スコア18

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

1グッド

0クリップ

投稿2020/03/14 05:25

3月14日の先頭のタスクを削除すると
イメージ説明
日付が表示されなくなります。
![イメージ説明

##原因・実現したいこと
原因は、同じ日付なら先頭以降のタスクの日付を削除する。そうでなければ、表示する。という処理をonBindViewHolder内に記載しており、削除時にはそれが呼び出されないので表示されないです。なので、削除処理を記載しているTaskAddアクティビティからonBindViewHolderを呼び出したいと思っているのですが、どう呼び出せば良いのでしょうか?
addTaskで削除時にnotifyDataSetChangedを呼び出しましたが、何も起こりませんでした。

Main

1class MainActivity : AppCompatActivity() { 2 private lateinit var realm: Realm 3 private var date: String? = null 4 5 override fun onCreate(savedInstanceState: Bundle?) { 6 super.onCreate(savedInstanceState) 7 setContentView(R.layout.activity_main) 8 setSupportActionBar(toolbar) 9 //インスタンスを取得 10 realm = Realm.getDefaultInstance() 11 task_list.layoutManager = LinearLayoutManager(this) 12 var task = realm.where<Task>().findAll() 13 task = task.sort("date") 14 val adapter = TaskAdapter(task,realm) 15 task_list.adapter = adapter 16 17 //タスク 追加ボタンタップ 18 addTask.setOnClickListener { view -> 19 //日付を編集画面に渡す 20 val nowDate = Date() 21 var format = SimpleDateFormat("HH:mm") 22 val nowTime = format.format(nowDate) 23 //選択されず初期の状態で追加ボタンを押されたら現在日時を渡す 24 if(date == null){ 25 format = SimpleDateFormat("yyyy/MM/dd") 26 date = format.format(nowDate) 27 } 28 val intent = Intent(this, TaskAddActivity::class.java) 29 date += " ${nowTime}" 30 intent.putExtra("DATE",date) 31 startActivity(intent) 32 } 33 //カレンダーの日付が選択された時 34 calendarView.setOnDateChangeListener { 35 calendarView, year, month, day -> 36 //2020/11/11形式で渡す 37 date = "${year}/${month+1}/${day}" 38 39 } 40 //adapterのlistenerに関数をセット 41 adapter.setOnclickListener {id:Long? -> 42 val intent = Intent(this, TaskAddActivity::class.java) 43 .putExtra("task_id",id) 44 startActivity(intent) 45 } 46 47 //Recyclerがスクロールされたら 48 /*task_list.addOnScrollListener( 49 50 )*/ 51 } 52 53 override fun onCreateOptionsMenu(menu: Menu): Boolean { 54 // Inflate the menu; this adds items to the action bar if it is present. 55 menuInflater.inflate(R.menu.menu_main, menu) 56 return true 57 } 58 59 override fun onOptionsItemSelected(item: MenuItem): Boolean { 60 // Handle action bar item clicks here. The action bar will 61 // automatically handle clicks on the Home/Up button, so long 62 // as you specify a parent activity in AndroidManifest.xml. 63 return when (item.itemId) { 64 R.id.action_settings -> true 65 else -> super.onOptionsItemSelected(item) 66 } 67 } 68 69 override fun onDestroy() { 70 super.onDestroy() 71 realm.close() 72 } 73}

TaskAdd

1class TaskAddActivity : AppCompatActivity() { 2 3 private lateinit var realm: Realm 4 5 override fun onCreate(savedInstanceState: Bundle?) { 6 super.onCreate(savedInstanceState) 7 setContentView(R.layout.activity_task_add) 8 realm = Realm.getDefaultInstance() 9 10 //編集なら削除ボタンを表示 11 val taskId = intent?.getLongExtra("task_id", -1L) 12 if( taskId != -1L){ 13 val task = realm.where<Task>().equalTo("id", taskId).findFirst() 14 titleEdit.setText(task?.title) 15 //削除ボタン表示 16 delete.visibility = View.VISIBLE 17 }else{ 18 //非表示 19 delete.visibility = View.INVISIBLE 20 } 21 22 //保存ボタンタップ 23 save.setOnClickListener {view -> 24 when(taskId){ 25 //新規登録 26 -1L->{ 27 //トランザクション開始 28 //入力されたタスクを保存 29 realm.executeTransaction {db: Realm -> 30 val maxId = db.where<Task>().max("id") 31 val nextId = (maxId?.toLong() ?: 0L) +1 32 val task = db.createObject<Task>(nextId) 33 //カレンダーに選択された日付を入手 34 val calendar = intent.getStringExtra("DATE") 35 val date = calendar.toDate("yyyy/MM/dd HH:mm") 36 if(date != null) task.date = date 37 task.title = titleEdit.text.toString() 38 39 } 40 Snackbar.make(view, "追加しました", Snackbar.LENGTH_SHORT) 41 .setAction("戻る", {finish()}) 42 .setActionTextColor(Color.YELLOW) 43 .show() 44 45 } 46 47 //編集モード 48 else->{ 49 realm.executeTransaction{db: Realm -> 50 val task = db.where<Task>().equalTo("id", taskId).findFirst() 51 task?.title = titleEdit.text.toString() 52 } 53 Snackbar.make(view, "修正しました", Snackbar.LENGTH_SHORT) 54 .setAction("戻る",{finish()}) 55 .setActionTextColor(Color.YELLOW) 56 .show() 57 } 58 59 } 60 61 } 62 //削除ボタン 63 delete.setOnClickListener { 64 realm.executeTransaction {db: Realm -> 65 66 db.where<Task>().equalTo("id", taskId) 67 ?.findFirst() 68 ?.deleteFromRealm() 69 } 70 71 Snackbar.make(it, "削除しました", Snackbar.LENGTH_SHORT) 72 .setAction("戻る", {finish()}) 73 .setActionTextColor(Color.YELLOW) 74 .show() 75 76 } 77 78 } 79 80 override fun onDestroy() { 81 super.onDestroy() 82 realm.close() 83 } 84 85 //文字を日付に変換 86 private fun String.toDate(pattern: String = "yyyy/MM/dd HH:mm"): Date?{ 87 return try{ 88 SimpleDateFormat(pattern).parse(this) 89 }catch (e: IllegalArgumentException){ 90 return null 91 }catch (e: ParseException){ 92 return null 93 } 94 } 95 96 97}

adapter

1class TaskAdapter(data: OrderedRealmCollection<Task>, val realm: Realm): 2RealmRecyclerViewAdapter<Task, TaskAdapter.ViewHolder>(data, true){ 3 4 private var listener:((Long?)-> Unit)? = null 5 6 fun setOnclickListener(listener: (Long?)-> Unit){ 7 this.listener = listener 8 } 9 10 init { 11 setHasStableIds(true) 12 } 13 14 //セルに使用するビューを決める 15 class ViewHolder(cell: View) : RecyclerView.ViewHolder(cell){ 16 val date: TextView = cell.findViewById(R.id.monthText) 17 val title: TextView = cell.findViewById(R.id.textTask) 18 val time: TextView = cell.findViewById(R.id.timeText) 19 val switch: Switch = cell.findViewById(R.id.switch1) 20 } 21 22 //セルが必要になるたびに呼び出される 23 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskAdapter.ViewHolder { 24 val inflater = LayoutInflater.from(parent.context) 25 //セルにビューを適用 26 val view = inflater.inflate(R.layout.task_list, parent, false) 27 28 return ViewHolder(view) 29 30 } 31 32 //指定された位置にデータを表示する必要がある時、呼び出される 33 override fun onBindViewHolder(holder: TaskAdapter.ViewHolder, position: Int) { 34 35 //データを取得 36 val task: Task? = getItem(position) 37 //Viewに値をセット 38 holder.date.text = DateFormat.format("yyyy/MM/dd", task?.date) 39 holder.date.setVisibility(View.VISIBLE) 40 holder.time.text = DateFormat.format("HH:mm", task?.date) 41 holder.switch.setOnCheckedChangeListener(null) 42 holder.title.text = task?.title 43 if(task?.flg != null) { 44 holder.switch.isChecked = task?.flg 45 holder.title.text = fontDraw(task?.flg, holder.title) 46 } 47 48 //タスクがタップされた時 49 holder.title.setOnClickListener { 50 //メインでセットした関数を実行 51 listener?.invoke(task?.id) 52 } 53 54 55 //前の項目があるなら 56 val prevTask: Task? = if (position > 0) getItem(position - 1) else null 57 val df = SimpleDateFormat("yyyy/MM/dd") 58 if(prevTask != null){ 59 //日付が一致するなら日付を消してくっつける 60 if(df.format(prevTask?.date) == df.format(task?.date)){ 61 holder.date.setVisibility(View.GONE); 62 } 63 } 64 65 //swichビューが切り替わった時 66 holder.switch.setOnCheckedChangeListener { compoundButton, b -> 67 68 realm.executeTransaction {db: Realm-> 69 var get_task : Task? 70 get_task = db.where<Task>().equalTo("id", task?.id).findFirst() 71 get_task?.flg = holder.switch.isChecked 72 } 73 74 } 75 } 76 77 override fun getItemId(position: Int): Long { 78 return getItem(position)?.id ?: 0 79 } 80 81 //タスクが完了済みなら線を引く、そうでなければ線を消す 82 private fun fontDraw(flg:Boolean, font: TextView): String{ 83 84 val paint = font.paint 85 if(flg) { 86 // なぜか再代入しなければ、取り消し線が引かれない 87 font.text = font.text 88 // 取り消し線を引く 89 paint.flags = font.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG 90 // アンチエイリアスをオンにする 91 paint.isAntiAlias = true 92 }else{ 93 font.text = font.text 94 paint.flags = font.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv() 95 } 96 97 return font.text.toString() 98 } 99 100}
s.k👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ViewHolder はスクロール時やデータ更新時に再利用されますから、セルの状態を変更する場合は常に変更する必要があります。

Kotlin

1 //指定された位置にデータを表示する必要がある時、呼び出される 2 override fun onBindViewHolder(holder: TaskAdapter.ViewHolder, position: Int) { 3 4 // 略 5 6 //前の項目があるなら 7 val prevTask: Task? = if (position > 0) getItem(position - 1) else null 8 val df = SimpleDateFormat("yyyy/MM/dd") 9 if(prevTask != null){ 10 //日付が一致するなら日付を消してくっつける 11 if(df.format(prevTask?.date) == df.format(task?.date)){ 12 holder.date.setVisibility(View.GONE); 13 } 14 } 15 16 // 略 17 }

つまり、ここで一度日付を GONE にしたセルが再利用された場合に VISIBLE に戻す必要があります。

Kotlin

1 //日付が一致するなら日付を消してくっつける 2 if (prevTask != null && df.format(prevTask.date) == df.format(task?.date)) { 3 holder.date.setVisibility(View.GONE); 4 } else { 5 holder.date.setVisibility(View.VISIBLE); 6 }

投稿2020/03/14 06:43

hoshi-takanori

総合スコア7895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kbayashi

2020/03/15 06:26

いつも親身に回答していただきありがとうございます。 セルの再利用とはこの場合で言うと、ひとつ上のセルのデータが削除された場合は、そのデータが削除されたセルを使い、その下のセルのデータを表示させるということでしょうか? もしそれが合っているならセルのデータを削除した場合、onbindViewHoloderが呼び出されると思うのですが、自分の場合は削除されても呼び出されないの、でVISIBLEにすることが出来ません。
hoshi-takanori

2020/03/15 06:48

onBindViewHolder は自分で呼び出すものではなく、RecyclerView が表示の際に勝手に呼び出します。
kbayashi

2020/03/15 07:32

回答ありがとうございます。 onBIndViewHolderは自分で呼ぶことはできないことはわかりました。 なので、Taskaddアクティビティでセルのデータを削除し、Mainアクティビティにfinishiで戻った時に、日付が表示されなない状態を修正するには、mainアクティビティのOnRestert時にnotifyDataSetChangedを呼び出して更新をかけようとと思います。
hoshi-takanori

2020/03/15 07:41

あ、そうか。たぶん Realm で削除や変更をした場合、RealmRecyclerViewAdapter がそれを検知して、自動的に変更されたセルだけ表示を更新するのでしょうね。でも、日付の表示のためには前後のセルも表示を更新する必要があるので、自分で notifyDataSetChanged を呼ぶ必要があるでしょうね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問