I'm currently trying to make a scrollable grid of ScratchViews, but the views that have already been scratched by the user, are appearing as not scratched when the user scrolls down and back up again, because the adapter is repainting each of the views back to their original unscratched state.
I've tried the solutions posted here: I want my RecyclerView to not recycle some items, but preventing the views from being recycled apparently doesn't prevent them from being redrawn.
Here is my code:
Fragment:
class ScratchOffGameFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_scratch_off_game, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
var data = ArrayList<ScratchOffGameItem>()
for (i in 1..20) {
var aux = ScratchOffGameItem()
data.add(aux)
}
scratchOffGameRecycle.layoutManager = GridLayoutManager(context, 3)
val scratchOffGameAdapter = ScratchOffGameAdapter(activity!!,data)
scratchOffGameRecycle.recycledViewPool.setMaxRecycledViews(1,0);
scratchOffGameRecycle.adapter = scratchOffGameAdapter
}
Adapter:
class ScratchOffGameAdapter(var context: Context, private val mData: ArrayList<ScratchOffGameItem>) : RecyclerView.Adapter<ScratchOffGameAdapter.ViewHolder>() {
private val mInflater: LayoutInflater = LayoutInflater.from(context)
inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView)
@NonNull
override fun onCreateViewHolder(@NonNull parent: ViewGroup, viewType: Int): ViewHolder {
val view = mInflater.inflate(R.layout.scratch_off_game_item, parent, false)
return ViewHolder(view)
}
// binds the data to the TextView in each cell
override fun onBindViewHolder(@NonNull holder: ViewHolder, position: Int) {
holder.setIsRecyclable(false)
}
override fun onViewAttachedToWindow(holder: ViewHolder) {
super.onViewAttachedToWindow(holder)
ScratchoffController(context)
.setThresholdPercent(0.80)
.setTouchRadiusDip(context, 30)
.attach(holder.itemView.scratch_view, holder.itemView.scratch_view_behind)
}
// total number of cells
override fun getItemCount(): Int {
return mData.size
}
override fun getItemViewType(position: Int): Int {
return 1
}
}
Item being painted by the adapter (scratch_off_game_item.xml):
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/achievementItem"
android:layout_width="110dp"
android:layout_height="90dp"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="30dp"
android:layout_marginTop="20dp"
android:layout_marginRight="30dp"
android:background="@drawable/achievements_border">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<RelativeLayout
android:id="@+id/scratch_view_behind"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/zing_rust_demo_base"
android:gravity="center"
android:text="20"
android:textColor="@color/black"
android:textSize="24sp"
android:layout_centerInParent="true"/>
</RelativeLayout>
<com.jackpocket.scratchoff.views.ScratchableLinearLayout
android:id="@+id/scratch_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/gold" >
<ImageView
android:layout_width="73dp"
android:layout_height="42dp"
android:src="@drawable/scratch_here_ic" />
</com.jackpocket.scratchoff.views.ScratchableLinearLayout>
</RelativeLayout>
</FrameLayout>
And RecyclerView:
<android.support.v7.widget.RecyclerView
android:id="@+id/scratchOffGameRecycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/youWin"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:layout_marginRight="50dp"
android:layout_marginBottom="10dp"
android:background="@drawable/bg_gold_rectangle"
android:columnWidth="100dp"
android:numColumns="3" />
As additional information, the libraries that I've tried using are these: 'com.jackpocket:scratchoff:1.3.0', 'com.github.cooltechworks:ScratchView:v1.1'in conjuction with both recycler and grid views to no avail.
What I ended up doing was changing the scratchoff library to this one: 'com.goibibo.libs:scratchcardview:0.1.6' ('com.jackpocket:scratchoff:1.3.0' had problems setting the listener inside the OnBindViewHolder method) and making a compromise to only save fully scratched views and not partially scratched ones. Here are the modifications I made:
OnBindViewHolder:
override fun onBindViewHolder(@NonNull holder: ViewHolder, position: Int) {
holder.itemView.number.text = mData[position].number
var scratchRelativeLayoutView = holder.itemView.scratch_card
holder.setIsRecyclable(false)
if(mData[position].isScratched && scratchRelativeLayoutView!=null) {
scratchRelativeLayoutView.visibility = View.GONE
holder.itemView.numberHidden.text = mData[position].number
holder.itemView.numberHidden.visibility = View.VISIBLE
}
else {
scratchRelativeLayoutView.setStrokeWidth(5)
scratchRelativeLayoutView.setScratchView(R.layout.lyt_scratch) // scratchable layout
scratchRelativeLayoutView.setRevealListener(object : ScratchRelativeLayoutView.IRevealListener {
override fun onRevealed(tv: ScratchRelativeLayoutView) {
mData[position].isScratched = true
}
override fun onRevealPercentChangedListener(siv: ScratchRelativeLayoutView, percent: Float) {
if (percent>0.5) {
siv.reveal()
}
}
})
}
}
scratch_off_game_item.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/achievementItem"
android:layout_width="90dp"
android:layout_height="90dp">
<TextView
android:id="@+id/numberHidden"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="@font/zing_rust_demo_base"
android:gravity="center"
android:text="23"
android:background="@color/white_scratch_off"
android:textColor="@color/black"
android:textSize="24sp"
android:layout_gravity="center"/>
<com.goibibo.libs.views.ScratchRelativeLayoutView
android:id="@+id/scratch_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white_scratch_off">
<TextView
android:id="@+id/number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/zing_rust_demo_base"
android:gravity="center"
android:textColor="@color/black"
android:textSize="24sp"
android:layout_centerInParent="true"/>
</com.goibibo.libs.views.ScratchRelativeLayoutView>
</FrameLayout>