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

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

新規登録して質問してみよう
ただいま回答率
85.35%
リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

Kotlin

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

Q&A

解決済

2回答

1032閲覧

CardView で、ボタンを押したら Card が出てくるはずだが、ボタンを押すとアプリが強制終了する

Liao

総合スコア9

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

Kotlin

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

0グッド

0クリップ

投稿2020/03/25 11:57

編集2020/03/26 09:54

前提・実現したいこと

かんたんなメモ帳のようなアプリを作っています。

装置の内容:
イメージ説明 イメージ説明
• 赤いボタンを押したら黄色いリストが出て、もう1度押すと黄色いリストをしまう
• プラスボタンを押すと、黄色いリストが増える
• 黄色いリスト、青いリストともに書き込み可能

発生している問題・エラーメッセージ

イメージ説明
このような感じで青いリストは表示できるし、書き込みもできる状態です。
そして、黄色いリストも出てくるようなコードを書いてあるのですが、赤いボタンを押しても黄色いリストが出てこず、アプリがダウンしてしまいます。

アプリがダウンせず、ちゃんと黄色いリストが出てくるようにしたい。

該当のソースコード

Kotlin

1package com.example.expandable_cardview_2 2 3import androidx.appcompat.app.AppCompatActivity 4import android.os.Bundle 5import androidx.recyclerview.widget.LinearLayoutManager 6import kotlinx.android.synthetic.main.activity_main.* 7 8class MainActivity : AppCompatActivity() { 9 10 override fun onCreate(savedInstanceState: Bundle?) { 11 super.onCreate(savedInstanceState) 12 setContentView(R.layout.activity_main) 13 14 val cardView= recycler_cardview 15 val itemList = mutableListOf<ExpandableCardViewAdapter.Item>() 16 17 val item = ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.PARENT) 18 item.children = listOf( 19 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 20 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 21 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 22 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 23 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD)) 24 itemList.add(item) 25 26 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.PARENT) 27 item.children = listOf( 28 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 29 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 30 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 31 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD), 32 ExpandableCardViewAdapter.Item(ExpandableCardViewAdapter.CHILD)) 33 itemList.add(item) 34 35 cardView.layoutManager = LinearLayoutManager(this) 36 cardView.adapter = ExpandableCardViewAdapter(itemList) 37 } 38}

リストを広げる class のコードも載せておきます。ただ、下のコードにはエラーが出てきませんでした。

package com.example.expandable_cardview_2 import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.cardview_parent.view.* class ExpandableCardViewAdapter(var items: MutableList<Item>) : RecyclerView.Adapter<RecyclerView.ViewHolder> (){ companion object { const val PARENT = 0 const val CHILD = 1 const val OPEN = 0.0F const val CLOSE = 180.0F } data class Item(val type: Int = 0, var text: String = "Default", var children: List<Item>? = null) inner class ItemHolder(v: View) : RecyclerView.ViewHolder(v) { val toggleImageView:ImageView = v.item_toggle_bottun } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) var view: View? = null when (viewType) { PARENT -> view = inflater.inflate(R.layout.cardview_parent, parent, false) CHILD -> view = inflater.inflate(R.layout.cardview_child, parent, false) } return this.ItemHolder(view!!) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val itemHolder = holder as? ItemHolder val item = items[position] itemHolder?.let { it -> it.toggleImageView.let { it1 -> it1.setImageResource(R.drawable.toggle) it1.rotation = if (item.children == null) OPEN else CLOSE it1.setOnClickListener {view -> val start: Int = items.indexOf(item) + 1 if (item.children == null) { var count = 0 var nextHeader = items.indexOf(items.find { it2 -> (count++ >= start) && (it2.type == item.type) }) if (nextHeader == -1) nextHeader = items.size item.children = items.slice(start until nextHeader) val end = item.children!!.size if (end > 0) items.removeAll(item.children!!) view.animate().rotation(CLOSE).start() notifyItemRangeRemoved(start, end) } else { item.children?.let { items.addAll(start, it) view.animate().rotation(OPEN).start() notifyItemRangeInserted(start, it.size) item.children = null } } } } } } override fun getItemCount(): Int = items.size override fun getItemViewType(position: Int): Int = items[position].type }

試したこと

クラッシュログを載せておきます。

2020-03-26 18:51:53.846 5070-5070/com.example.expandable_cardview_2 E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.expandable_cardview_2, PID: 5070 java.lang.IllegalStateException: v.item_toggle_bottun must not be null at com.example.expandable_cardview_2.ExpandableCardViewAdapter$ItemHolder.<init>(ExpandableCardViewAdapter.kt:24) at com.example.expandable_cardview_2.ExpandableCardViewAdapter.onCreateViewHolder(ExpandableCardViewAdapter.kt:36) at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078) at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114) at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303) at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627) at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587) at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665) at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134) at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851) at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404) at android.view.View.layout(View.java:17523) at android.view.ViewGroup.layout(ViewGroup.java:5612) at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915) at android.view.View.layout(View.java:17523) at android.view.ViewGroup.layout(ViewGroup.java:5612) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) at android.widget.FrameLayout.onLayout(FrameLayout.java:261) at android.view.View.layout(View.java:17523) at android.view.ViewGroup.layout(ViewGroup.java:5612) at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:446) at android.view.View.layout(View.java:17523) at android.view.ViewGroup.layout(ViewGroup.java:5612) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) at android.widget.FrameLayout.onLayout(FrameLayout.java:261) at android.view.View.layout(View.java:17523) at android.view.ViewGroup.layout(ViewGroup.java:5612) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585) at android.widget.LinearLayout.onLayout(LinearLayout.java:1494) at android.view.View.layout(View.java:17523) at android.view.ViewGroup.layout(ViewGroup.java:5612) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) at android.widget.FrameLayout.onLayout(FrameLayout.java:261) at com.android.internal.policy.DecorView.onLayout(DecorView.java:724) at android.view.View.layout(View.java:17523) at android.view.ViewGroup.layout(ViewGroup.java:5612) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2342) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2069) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871) at android.view.Choreographer.doCallbacks(Choreographer.java:683) at android.view.Choreographer.doFrame(Choreographer.java:619) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

補足情報(FW/ツールのバージョンなど)

Kotlin version:1.3.71 (最新バージョンです)
Android Studio を使っています。

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

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

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

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

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

quadii.shii

2020/03/26 07:35

Logcatのクラッシュログを貼りつけていただけると分かりやすいです。
Liao

2020/03/26 10:01

クラッシュログを載せておきました。
guest

回答2

0

自己解決

inner class ItemHolder(v: View) : RecyclerView.ViewHolder(v) { val toggleImageView:ImageView = v.item_toggle_bottun }
it1.setImageResource(R.drawable.toggle) it1.rotation = if (item.children == null) OPEN else CLOSE it1.setOnClickListener {view ->

というコードを

inner class ItemHolder(v: View) : RecyclerView.ViewHolder(v) { val toggleImageView:ImageView? = v.item_toggle_bottun }
it1?.setImageResource(R.drawable.toggle) it1?.rotation = if (item.children == null) OPEN else CLOSE it1?.setOnClickListener {view ->

というふうに変えたところ、null ではなくなりました。

投稿2020/03/27 15:30

Liao

総合スコア9

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

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

0

クラッシュログの読み方

クラッシュログの見るべきはどんな例外を吐いているかです。

log

1java.lang.IllegalStateException: v.item_toggle_bottun must not be null

Kotlin

1inner class ItemHolder(v: View) : RecyclerView.ViewHolder(v) { 2 val toggleImageView:ImageView = v.item_toggle_bottun 3}

ここで宣言しているtoggleImageView:ImageViewv.item_toggle_bottunを代入していますが、何らかの理由でnullになっているようです。

ここでviewの生成を定数で切り分けています。

Kotlin

1 when (viewType) { 2 PARENT -> view = inflater.inflate(R.layout.cardview_parent, parent, false) 3 CHILD -> view = inflater.inflate(R.layout.cardview_child, parent, false) 4 } 5 6 return this.ItemHolder(view!!)

レイアウトXMLがないので分かりませんが、おそらくR.layout.cardview_childのほうにはitem_toggle_bottunというIDを持つ要素がないのではないでしょうか。

その場合、そのIDで要素が見つからないのでnullが帰ります。

修正案を追記

cardview_childのレイアウトXMLにitem_toggle_bottunにどのように追記するかというお尋ねをいただいていますが、結論から申し上げるとこの種のボタンは子要素のビューに追加すべきではありません。

ExpandableListView(展開可能リストビュー)として実装しておられるのだと思いますが、親セルを展開したときに子セルが親セルをリプレイスしてしまう現在の実装は根本的に展開リストビューの設計趣旨から外れています。

ネットで検索すると展開リストビューの自作実装例などが(開発言語を問わず)たくさん出てくるとは思いますが、親セルと子セルの関係は以下のようになっているべきです。

リストビュー ├ 親セル │ ├ 子セル │ └ 子セル ├ 親セル

この実装をどのように行うかは根本的な作り変えになるので現状の実装を修正するというレベルではありません。
teratailで質問する内容でもありません。

  • 会社等に所属して作業しておられるのであればメンター格の先輩にお尋ねになるがふさわしいと思います。
  • 自学自習に取り組み、かつ限界を感じているのであれば有料オンラインスクール等で学ばれるのがよいと思います。

投稿2020/03/26 12:38

編集2020/03/27 00:41
quadii.shii

総合スコア257

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

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

Liao

2020/03/26 16:09 編集

回答ありがとうございます。 item_toggle_bottun についてなのですが、 ```cardview_child.xml <?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cardview_child="http://schemas.android.com/apk/res-auto" android:id="@+id/cardview_child" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginVertical="3dp" android:layout_marginStart="30dp" android:layout_marginEnd="10dp" cardview_child:cardBackgroundColor="#ffd54f" cardview_child:cardCornerRadius="8dp"> <EditText android:id="@+id/item_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:autofillHints="@string/click_here" android:hint="@string/click_here" android:inputType="text" android:textColor="#448aff"> </EditText> </androidx.cardview.widget.CardView> ``` のなかにどのように記入すればいいのでしょうか?
Liao

2020/03/27 04:04 編集

すみません。 「R.layout.cardview_childのほうにはitem_toggle_bottunというIDを持つ要素がないのではないでしょうか。」 という言葉の意味がよくわからず、どうすればいいのかいいのかわかりませんでした。
Liao

2020/03/27 04:39

やはり、item_toggle_bottun が null になる理由がわかりません。 val toggleImageView:ImageView = v.item_toggle_bottun と return this.ItemHolder(view!!) に原因があるらしいのですが、これを null にしないということでしょうか?
quadii.shii

2020/03/27 05:07

CHILD -> view = inflater.inflate(R.layout.cardview_child, parent, false) でインフレートしたitem_toggle_bottunを持たないviewを this.ItemHolder(view!!)のコンストラクタに引数として渡しているからです。
quadii.shii

2020/03/27 05:08

ItemHolderのクラス内ではコンストラクタ内引数v:Viewがitem_toggle_bottunを持っている前提で書かれています。
Liao

2020/03/27 13:04

null になった理由はよくわかりました。 ただ、どうすればこの v:View に item_toggle_bottun を持たせることができるのか分からないです。 すみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問