Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package io.github.chayanforyou.stickynotes.adapter
- import android.content.Context
- import android.graphics.BitmapFactory
- import android.os.Handler
- import android.os.Looper
- import android.view.LayoutInflater
- import android.view.View
- import android.view.ViewGroup
- import androidx.recyclerview.widget.DiffUtil
- import androidx.recyclerview.widget.ListAdapter
- import androidx.recyclerview.widget.RecyclerView
- import com.google.android.gms.ads.AdListener
- import com.google.android.gms.ads.AdLoader
- import com.google.android.gms.ads.AdRequest
- import com.google.android.gms.ads.LoadAdError
- import com.google.android.gms.ads.nativead.NativeAd
- import io.github.chayanforyou.stickynotes.data.Note
- import io.github.chayanforyou.stickynotes.databinding.ItemNativeAdBinding
- import io.github.chayanforyou.stickynotes.databinding.ItemNoteBinding
- import io.github.chayanforyou.stickynotes.utils.NoteUtils
- import io.github.chayanforyou.stickynotes.R
- private const val VIEW_TYPE_NOTE = 0
- private const val VIEW_TYPE_AD = 1
- private const val ADS_AFTER = 5
- private const val AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110"
- sealed class AdapterItem {
- data class NoteItem(val note: Note) : AdapterItem()
- data class AdItem(val nativeAd: NativeAd) : AdapterItem()
- }
- class NoteAdapter(
- private val context: Context,
- private val onNoteClick: (Note) -> Unit,
- private val onNoteLongClick: (Note) -> Unit
- ) : ListAdapter<AdapterItem, RecyclerView.ViewHolder>(AdapterItemDiffCallback()) {
- private val adPositions = mutableSetOf<Int>()
- private val mainHandler = Handler(Looper.getMainLooper())
- override fun getItemViewType(position: Int): Int {
- return when (getItem(position)) {
- is AdapterItem.NoteItem -> VIEW_TYPE_NOTE
- is AdapterItem.AdItem -> VIEW_TYPE_AD
- }
- }
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- val inflater = LayoutInflater.from(parent.context)
- return when (viewType) {
- VIEW_TYPE_AD -> {
- val binding = ItemNativeAdBinding.inflate(inflater, parent, false)
- NativeAdViewHolder(binding)
- }
- else -> {
- val binding = ItemNoteBinding.inflate(inflater, parent, false)
- NoteViewHolder(binding, onNoteClick, onNoteLongClick)
- }
- }
- }
- override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- when (val item = getItem(position)) {
- is AdapterItem.NoteItem -> (holder as NoteViewHolder).bind(item.note)
- is AdapterItem.AdItem -> (holder as NativeAdViewHolder).bind(item.nativeAd)
- }
- }
- fun submitNotes(notes: List<Note>) {
- val items = mutableListOf<AdapterItem>()
- adPositions.clear()
- notes.forEachIndexed { index, note ->
- items.add(AdapterItem.NoteItem(note))
- if ((index + 1) % ADS_AFTER == 0) {
- adPositions.add(items.size)
- }
- }
- super.submitList(items)
- loadAds()
- }
- private fun loadAds() {
- adPositions.forEach { position -> loadAdForPosition(position) }
- }
- private fun loadAdForPosition(position: Int) {
- val adLoader = AdLoader.Builder(context, AD_UNIT_ID)
- .forNativeAd { nativeAd ->
- mainHandler.post { insertAdAtPosition(position, nativeAd) }
- }
- .withAdListener(object : AdListener() {
- override fun onAdFailedToLoad(adError: LoadAdError) {
- adPositions.remove(position)
- }
- })
- .build()
- adLoader.loadAd(AdRequest.Builder().build())
- }
- private fun insertAdAtPosition(position: Int, nativeAd: NativeAd) {
- val currentList = currentList.toMutableList()
- val adsInsertedBefore = adPositions.count { it < position }
- val adjustedPosition = position + adsInsertedBefore
- if (adjustedPosition <= currentList.size) {
- currentList.add(adjustedPosition, AdapterItem.AdItem(nativeAd))
- submitList(currentList)
- }
- }
- class NoteViewHolder(
- private val binding: ItemNoteBinding,
- private val onNoteClick: (Note) -> Unit,
- private val onNoteLongClick: (Note) -> Unit
- ) : RecyclerView.ViewHolder(binding.root) {
- fun bind(note: Note) {
- binding.apply {
- tvText.text = note.text
- tvText.textSize = note.textSize.toFloat()
- tvText.gravity = note.textAlign
- tvText.typeface = NoteUtils.getTypeface(root.context, note.textFont)
- tvText.setTextColor(NoteUtils.getTextColor(note.textColor))
- ivHolder.apply {
- if (note.holderStyle != 0) {
- setImageResource(NoteUtils.getHolderResource(note.holderStyle))
- rotation = note.angle.toFloat()
- } else {
- setImageDrawable(null)
- }
- }
- rlBg.apply {
- setBackgroundResource(NoteUtils.getBackgroundResource(note.backgroundColor))
- alpha = note.alpha / 255f
- rotation = note.angle.toFloat()
- }
- ivDrawing.visibility = if (note.imageData != null && note.imageData.isNotEmpty()) {
- val bitmap =
- BitmapFactory.decodeByteArray(note.imageData, 0, note.imageData.size)
- ivDrawing.setImageBitmap(bitmap)
- View.VISIBLE
- } else {
- View.GONE
- }
- ivLock.visibility = if (note.password != null) View.VISIBLE else View.GONE
- ivSelected.visibility = View.GONE
- }
- itemView.setOnClickListener { onNoteClick(note) }
- itemView.setOnLongClickListener {
- onNoteLongClick(note)
- true
- }
- }
- }
- class NativeAdViewHolder(private val binding: ItemNativeAdBinding) :
- RecyclerView.ViewHolder(binding.root) {
- fun bind(nativeAd: NativeAd) {
- binding.apply {
- nativeAdView.mediaView = adMedia
- nativeAdView.headlineView = adHeadline
- nativeAdView.bodyView = adBody
- nativeAdView.callToActionView = adCallToAction
- adHeadline.text = nativeAd.headline
- adBody.text = nativeAd.body
- adCallToAction.text = nativeAd.callToAction
- nativeAdView.setNativeAd(nativeAd)
- }
- }
- }
- private class AdapterItemDiffCallback : DiffUtil.ItemCallback<AdapterItem>() {
- override fun areItemsTheSame(oldItem: AdapterItem, newItem: AdapterItem): Boolean {
- return when {
- oldItem is AdapterItem.NoteItem && newItem is AdapterItem.NoteItem -> oldItem.note.id == newItem.note.id
- oldItem is AdapterItem.AdItem && newItem is AdapterItem.AdItem -> true
- else -> false
- }
- }
- override fun areContentsTheSame(oldItem: AdapterItem, newItem: AdapterItem): Boolean {
- return when {
- oldItem is AdapterItem.NoteItem && newItem is AdapterItem.NoteItem -> {
- val baseEqual = oldItem.note.copy(imageData = null) == newItem.note.copy(imageData = null)
- val imageEqual = oldItem.note.imageData.contentEqualsNullable(newItem.note.imageData)
- baseEqual && imageEqual
- }
- oldItem is AdapterItem.AdItem && newItem is AdapterItem.AdItem -> true
- else -> false
- }
- }
- }
- }
- private fun ByteArray?.contentEqualsNullable(other: ByteArray?): Boolean {
- if (this === other) return true
- if (this == null || other == null) return false
- return this.contentEquals(other)
- }
Advertisement
Add Comment
Please, Sign In to add comment