title: Why are my custom view RecyclerView items "invisible"
body: <p>I need to <code>onDraw</code> the items of a <code>RecyclerView</code>. Using an approach &quot;discovered&quot; at <a href="https://stackoverflow.com/questions/42522121/use-custom-view-in-a-recyclerview-adapter">this SO link</a>, I have gotten - um - partway there.</p>
  <p>Note that I ultimately want to <code>onDraw</code> &quot;over&quot; the custom view. Meaning call <code>super</code> to let the default drawing occur, then <code>paint</code> over unused areas of the (view's) <code>canvas</code>.</p>
  <p>Before starting down this &quot;custom view to allow <code>onDraw</code>&quot; road, I had what you see on the <strong>left</strong> below:</p>
  <p><a href="https://i.stack.imgur.com/fLA3Y.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/fLA3Y.png" alt="enter image description here" /></a>    <a href="https://i.stack.imgur.com/sZHyr.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/sZHyr.png" alt="enter image description here" /></a>   <a href="https://i.stack.imgur.com/EJ6Hz.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/EJ6Hz.png" alt="enter image description here" /></a></p>
  <p>Afterward, I had all &quot;invisible&quot; views (<strong>middle</strong> image above). I say &quot;invisible&quot; because they were still there to be clicked. To help me visualize things (and a bit of <code>onDraw</code> proof of concept) I overrode <code>onDraw</code>  in the custom <code>PuzzleView</code> view, simply calling <code>canvas.drawRect</code> to cover the entire canvas in Green, and now see the <strong>right</strong> image above.</p>
  <p>I am not sure what I'm doing wrong here.</p>
  <p>Also, if it occurs to you that - well, why don't I simply <code>onDraw</code> the whole thing - that's not practical for a variety of reasons.</p>
  <p>So, here's my <code>PuzzleAdapter</code> as it is now:</p>
  <pre><code>class PuzzleAdapter(private val puzzles: List&lt;Puzzle&gt;) : RecyclerView.Adapter&lt;PuzzleAdapter.PuzzleHolder&gt;() {
  
      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PuzzleAdapter.PuzzleHolder {
          //val v = LayoutInflater.from(parent.context).inflate(R.layout.item_puzzle, parent, false)
          //not inflating, creating PuzzleView (which is inflating itself)
          val v = PuzzleView(parent.context)
          v.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
          return PuzzleHolder(v)
      }
  
      override fun getItemCount() = puzzles.size
  
      //unchanged between these two versions
      override fun onBindViewHolder(h: PuzzleAdapter.PuzzleHolder, pos: Int) {
          val p = puzzles[pos]
          h.view.puzzleItem_text_ndx.text = &quot;# &quot; + p.descr()
          h.view.puzzleItem_text_details.text = &quot;Ndx: ${p.puzzleNdx}&quot;
          h.view.setOnClickListener {
              Log.d(&quot;##&quot;, &quot;PuzzleHolder.onClick (bunch#${p.parentBunch.bunchID}; puzzle#${p.puzzleNdx})&quot;)
              val action = BunchFragmentDirections.navBunchToPuzzle(PuzzleParcel(p.parentBunch.bunchID, p.puzzleNdx))
              it.findNavController().navigate(action)
          }
      }
  
      inner class PuzzleHolder(v: View) : RecyclerView.ViewHolder(v) {
          val view: PuzzleView
          init {
              view = v as PuzzleView
          }
      }
  }
  </code></pre>
  <p><strong>PuzzleAdapter before</strong>:</p>
  <pre><code>class PuzzleAdapter(private val puzzles: List&lt;Puzzle&gt;) : RecyclerView.Adapter&lt;PuzzleAdapter.PuzzleHolder&gt;() {
  
      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PuzzleAdapter.PuzzleHolder {
          val v = LayoutInflater.from(parent.context).inflate(R.layout.item_puzzle, parent, false)
          return PuzzleHolder(v)
      }
  
      override fun getItemCount() = puzzles.size
  
      //unchanged between these two versions
      override fun onBindViewHolder(h: PuzzleAdapter.PuzzleHolder, pos: Int) {
          val p = puzzles[pos]
          h.view.puzzleItem_text_ndx.text = &quot;# &quot; + p.descr()
          h.view.puzzleItem_text_details.text = &quot;Ndx: ${p.puzzleNdx}&quot;
          h.view.setOnClickListener {
              Log.d(&quot;##&quot;, &quot;PuzzleHolder.onClick (bunch#${p.parentBunch.bunchID}; puzzle#${p.puzzleNdx})&quot;)
              val action = BunchFragmentDirections.navBunchToPuzzle(PuzzleParcel(p.parentBunch.bunchID, p.puzzleNdx))
              it.findNavController().navigate(action)
          }
      }
  
      inner class PuzzleHolder(v: View) : RecyclerView.ViewHolder(v) {
          var view: View = v
      }
  }
  </code></pre>
  <p><strong>PuzzleView</strong> (the <strong>custom view</strong> I am using with the Adapter):</p>
  <pre><code>class PuzzleView : RelativeLayout {
      constructor (context: Context) : super(context) { init(context, null, 0) }
      constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { init(context, attrs, 0) }
      constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { init(context, attrs, defStyle) }
  
      private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) {
          inflate(getContext(), R.layout.item_puzzle, this)
      }
  
      override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
          //this.layout(l, t, r, b)
      }
  
      val rect = Rect(0, 0, 0, 0)
      val paint = Paint()
      override fun onDraw(canvas: Canvas) {
          //super.onDraw(canvas)
          Log.d(&quot;##&quot;, &quot;PuzzleView.onDraw()&quot;)
          rect.right = width - 10
          rect.bottom = height - 10
          val bkgrColor = ContextCompat.getColor(App.context, R.color.Green)
          paint.style = Paint.Style.FILL
          paint.color = bkgrColor
          canvas.drawRect(rect, paint)
      }
  }
  </code></pre>
  <p>A few thoughts on the above class/code:</p>
  <ul>
  <li><code>override fun onLayout</code> is required</li>
  <li>I have other custom views that work fine (not in relation to a RecyclerView) with an empty <code>onLayout</code></li>
  <li>I tried (it's commented out in the above code) <code>this.layout(l, t, r, b)</code> but get a stack overflow exception</li>
  </ul>
  <p>My only real thoughts here are (1) that there's something I'm supposed to be doing in this <code>onLayout</code> method, but I can't think of what; or (2) there's something wrong with the way that I'm inflating <code>item_puzzle</code>, but - again - I can't think of what. (I tried a few things on this, to no avail). I cannot think of anything else!</p>
  <p>And here's all the other code I think could possibly be relevant:</p>
  <p>From the <strong>Fragment containing the RecyclerView</strong> (it's what is shown in the above three images):</p>
  <pre><code>    bunch_recycler.layoutManager = GridLayoutManager(this.context, 3)
      bunch_recycler.adapter = PuzzleAdapter(bunch.puzzles)
  </code></pre>
  <p>Finally, the <strong>XML for</strong> the item itself, <strong>item_puzzle</strong>:</p>
  <p><a href="https://i.stack.imgur.com/z0EA1.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/z0EA1.png" alt="enter image description here" /></a></p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;androidx.cardview.widget.CardView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
      android:layout_width=&quot;match_parent&quot;
      android:layout_height=&quot;wrap_content&quot;
      android:layout_marginBottom=&quot;16dp&quot;
      android:layout_marginStart=&quot;16dp&quot;
      android:layout_marginEnd=&quot;16dp&quot;
      app:cardBackgroundColor=&quot;@color/facadeLight&quot;
      app:cardElevation=&quot;0dp&quot;
      &gt;
  
      &lt;RelativeLayout
          android:layout_width=&quot;wrap_content&quot;
          android:layout_height=&quot;wrap_content&quot;
          android:background=&quot;@drawable/shape_puzzle&quot;
          &gt;
  
          &lt;TextView
              android:id=&quot;@+id/puzzleItem_text_ndx&quot;
              android:layout_width=&quot;wrap_content&quot;
              android:layout_height=&quot;wrap_content&quot;
              android:layout_centerHorizontal=&quot;true&quot;
              android:layout_marginEnd=&quot;16dp&quot;
              android:ellipsize=&quot;end&quot;
              android:fontFamily=&quot;@font/showg&quot;
              android:maxLines=&quot;1&quot;
              android:text=&quot;17&quot;
              android:textColor=&quot;@color/facadeDark&quot;
              android:textSize=&quot;32sp&quot;
              /&gt;
  
          &lt;TextView
              android:id=&quot;@+id/puzzleItem_text_details&quot;
              android:layout_width=&quot;wrap_content&quot;
              android:layout_height=&quot;wrap_content&quot;
              android:layout_below=&quot;@+id/puzzleItem_text_ndx&quot;
              android:layout_marginStart=&quot;8dp&quot;
              android:text=&quot;details&quot;
              android:textSize=&quot;12sp&quot;
              /&gt;
      &lt;/RelativeLayout&gt;
  
  &lt;/androidx.cardview.widget.CardView&gt;
  </code></pre>
  <p>Also, if &quot;custom view to allow onDraw&quot; isn't the correct (or best) way of accomplishing my goal here, please let me know that as well.</p>
  <p>Using:</p>
  <ul>
  <li>Windows 10</li>
  <li>Android Studio 3.4</li>
  <li>Kotlin 1.3.31</li>
  <li>Gradle 3.4.0</li>
  <li>and the following:</li>
  </ul>
  <pre><code>    implementation &quot;org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version&quot;
      implementation 'androidx.appcompat:appcompat:1.1.0-alpha05'
      implementation 'androidx.core:core-ktx:1.2.0-alpha01'
      implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
  
      testImplementation 'junit:junit:4.12'
      androidTestImplementation 'androidx.test:runner:1.2.0-beta01'
      androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-beta01'
  
      implementation 'androidx.navigation:navigation-fragment-ktx:2.0.0'
      implementation 'androidx.navigation:navigation-ui-ktx:2.0.0'
  </code></pre>
  <h2>Afterthought</h2>
  <p>I saw (in a 4 1/2-year-old <a href="https://www.youtube.com/watch?v=ZiU06u_vuG8&amp;t=67s" rel="nofollow noreferrer">youtube video</a> overriding <code>getView</code> to assign subviews in a similar-seeming situation. There is no <code>getView</code> method to override in today's <code>RecyclerView</code>. The closest thing I see is <code>getItemViewType(position: Int): Int</code> which doesn't seem promising either (I read up on it a bit). Just thought I'd mention this in case it triggers a thought for you (where it didn't for me).</p>